From 9aaffafe826d390169be60dbd95f4769c28a3420 Mon Sep 17 00:00:00 2001 From: Victor Shyba Date: Fri, 10 Apr 2026 15:47:16 -0300 Subject: [PATCH] fix: stack trace formatting and proper ensure_started call --- src/hb_format.erl | 38 ++++++++++++++++++++++++++++++++++ src/hb_system_monitor.erl | 43 +++------------------------------------ 2 files changed, 41 insertions(+), 40 deletions(-) diff --git a/src/hb_format.erl b/src/hb_format.erl index d9ea1ca6d..a256b2fc9 100644 --- a/src/hb_format.erl +++ b/src/hb_format.erl @@ -21,6 +21,7 @@ -export([escape_format/1, short_id/1, trace_to_list/1]). -export([get_trace/1, print_trace/4, trace_macro_helper/5, print_trace_short/4]). -export([process_from_trace/1]). +-export([format_mfa/1, stack_location/1]). -include("include/hb.hrl"). -include_lib("eunit/include/eunit.hrl"). @@ -658,6 +659,43 @@ process_from_trace([TraceElement | Rest], Spawner) -> >> end. +%% @doc Format an MFA tuple or stack frame as `mod:func/arity`. +format_mfa({Mod, Func, Arity, _}) when is_integer(Arity) -> + format_mfa({Mod, Func, Arity}); +format_mfa({Mod, Func, Args, _}) when is_list(Args) -> + format_mfa({Mod, Func, length(Args)}); +format_mfa({Mod, Func, Arity}) when is_integer(Arity) -> + << + (atom_to_binary(Mod))/binary, ":", + (atom_to_binary(Func))/binary, "/", + (integer_to_binary(Arity))/binary + >>; +format_mfa(_) -> + <<"unknown">>. + +%% @doc Build a compact location label from a stack: `mid/current`. +%% Current is the innermost frame (head of stacktrace), mid is +%% roughly 1/3 from the bottom — a frame that gives codebase +%% context without being the generic entry or the leaf. +stack_location([]) -> + <<"unknown">>; +stack_location([Only]) -> + format_mfa(Only); +stack_location(Stack) -> + Current = hd(Stack), + Len = length(Stack), + MidIdx = max(1, Len - (Len div 3)), + Mid = lists:nth(MidIdx, Stack), + case Mid =:= Current of + true -> + format_mfa(Current); + false -> + << + (format_mfa(Mid))/binary, "/", + (format_mfa(Current))/binary + >> + end. + trace_element_is_glue({proc_lib, init_p_do_apply, _, _}) -> true; trace_element_is_glue({hb_pmap, F, _, _}) -> diff --git a/src/hb_system_monitor.erl b/src/hb_system_monitor.erl index baadb1182..b3eaa40fd 100644 --- a/src/hb_system_monitor.erl +++ b/src/hb_system_monitor.erl @@ -154,14 +154,8 @@ init_prometheus() -> %% @doc Format a schedule location for use as a prometheus label. format_location(undefined) -> <<"undefined">>; -format_location({Mod, Func, Arity}) -> - << - (atom_to_binary(Mod))/binary, ":", - (atom_to_binary(Func))/binary, "/", - (integer_to_binary(Arity))/binary - >>; -format_location(_) -> - <<"unknown">>. +format_location(MFA) -> + hb_format:format_mfa(MFA). %% @doc If the timeout exceeds the deep inspection threshold and %% enough time has passed since the last inspection, grab detailed @@ -215,7 +209,7 @@ deep_inspect(Pid, ScheduleInfo) -> ?event(system_monitor, {deep_inspect, Pid, ScheduleInfo, ProcInfo}), Stack = proplists:get_value(current_stacktrace, ProcInfo, []), Entry = stack_entry(Stack), - Location = stack_location(Stack), + Location = hb_format:stack_location(Stack), hb_prometheus:inc(counter, system_monitor_deep_inspect_total, [Entry, Location]). @@ -225,37 +219,6 @@ stack_entry([]) -> stack_entry(Stack) -> hb_format:process_from_trace(Stack). -%% @doc Build a compact location label from the stack: `mid/current`. -%% Current is the innermost frame (head of stacktrace), mid is -%% roughly 1/3 from the bottom — a frame that gives codebase context -%% without being the generic entry or the leaf. -stack_location([]) -> - <<"unknown">>; -stack_location([Only]) -> - format_frame(Only); -stack_location(Stack) -> - Current = hd(Stack), - Len = length(Stack), - MidIdx = max(1, Len - (Len div 3)), - Mid = lists:nth(MidIdx, Stack), - case Mid =:= Current of - true -> - format_frame(Current); - false -> - << - (format_frame(Mid))/binary, "/", - (format_frame(Current))/binary - >> - end. - -%% @doc Format a single stack frame as `mod:func/arity`. -format_frame({Mod, Func, Arity, _}) -> - format_location({Mod, Func, Arity}); -format_frame({Mod, Func, Arity}) -> - format_location({Mod, Func, Arity}); -format_frame(_) -> - <<"unknown">>. - %% @doc Safely retrieve process info. The process may have died %% between the monitor event and our inspection. safe_process_info(Pid, Items) ->