From 0260db664096f6b8f662f22602b3d735c3d34e88 Mon Sep 17 00:00:00 2001 From: Thales Macedo Garitezi Date: Wed, 24 Nov 2021 12:41:35 -0300 Subject: [PATCH] feat(sys_mon): Add proc_lib:initial_call/1 and current_stacktrace (4.3) (Same as #6289 ) This adds the information from `proc_lib:initial_call/1` and the current stacktrace from the process info to `emqx_sys_mon:procinfo/1` to aid in debugging some warnings with no context such as the following: ``` 2021-11-23T12:33:59.387818+00:00 [warning] info: [{old_heap_block_size,45988046},{heap_block_size,22177879},{mbuf_size,0},{stack_size,40},{old_heap_size,22354134},{heap_size,7106339}], line: 130, mfa: emqx_sys_mon:handle_info/2, msg: large_heap, procinfo: [{pid,<0.2667.0>},{memory,579763664},{total_heap_size,68510672},{heap_size,22177879},{stack_size,40},{min_heap_size,233},{initial_call,{proc_lib,init_p,5}},{current_function,{gen,do_call,4}},{registered_name,[]},{status,running},{message_queue_len,360945},{group_leader,<0.1660.0>},{priority,normal},{trap_exit,false},{reductions,16493271},{last_calls,false},{catchlevel,4},{trace,0},{suspending,[]},{sequential_trace_token,[]},{error_handler,error_handler}] ``` --- src/emqx_sys_mon.erl | 10 ++++++++- src/emqx_vm.erl | 2 +- test/emqx_sys_mon_SUITE.erl | 41 ++++++++++++++++++++++++++++++++++--- 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/src/emqx_sys_mon.erl b/src/emqx_sys_mon.erl index 152f975eb..710895bcd 100644 --- a/src/emqx_sys_mon.erl +++ b/src/emqx_sys_mon.erl @@ -182,7 +182,15 @@ procinfo(Pid) -> case {emqx_vm:get_process_info(Pid), emqx_vm:get_process_gc_info(Pid)} of {undefined, _} -> undefined; {_, undefined} -> undefined; - {Info, GcInfo} -> Info ++ GcInfo + {Info, GcInfo} -> get_proc_lib_initial_call(Pid) ++ GcInfo ++ Info + end. + +get_proc_lib_initial_call(Pid) -> + case proc_lib:initial_call(Pid) of + false -> + []; + InitialCall -> + [{proc_lib_initial_call, InitialCall}] end. safe_publish(Event, WarnMsg) -> diff --git a/src/emqx_vm.erl b/src/emqx_vm.erl index 537330b01..dc841229a 100644 --- a/src/emqx_vm.erl +++ b/src/emqx_vm.erl @@ -62,7 +62,7 @@ ]). -define(PROCESS_INFO_KEYS, [initial_call, - current_function, + current_stacktrace, registered_name, status, message_queue_len, diff --git a/test/emqx_sys_mon_SUITE.erl b/test/emqx_sys_mon_SUITE.erl index 70f518ad5..63e7c376a 100644 --- a/test/emqx_sys_mon_SUITE.erl +++ b/test/emqx_sys_mon_SUITE.erl @@ -70,23 +70,51 @@ init_per_testcase(t_sys_mon2, Config) -> (_) -> ok end), Config; +init_per_testcase(t_procinfo, Config) -> + emqx_ct_helpers:boot_modules(all), + emqx_ct_helpers:start_apps([]), + ok = meck:new(emqx_vm, [passthrough, no_history]), + Config; init_per_testcase(_, Config) -> emqx_ct_helpers:boot_modules(all), emqx_ct_helpers:start_apps([]), Config. +end_per_testcase(t_procinfo, _Config) -> + ok = meck:unload(emqx_vm), + emqx_ct_helpers:stop_apps([]); end_per_testcase(_, _Config) -> emqx_ct_helpers:stop_apps([]). t_procinfo(_) -> - ok = meck:new(emqx_vm, [passthrough, no_history]), ok = meck:expect(emqx_vm, get_process_info, fun(_) -> [] end), ok = meck:expect(emqx_vm, get_process_gc_info, fun(_) -> [] end), ?assertEqual([], emqx_sys_mon:procinfo([])), ok = meck:expect(emqx_vm, get_process_info, fun(_) -> ok end), ok = meck:expect(emqx_vm, get_process_gc_info, fun(_) -> undefined end), - ?assertEqual(undefined, emqx_sys_mon:procinfo([])), - ok = meck:unload(emqx_vm). + ?assertEqual(undefined, emqx_sys_mon:procinfo([])). + +t_procinfo_initial_call_and_stacktrace(_) -> + SomePid = proc_lib:spawn(?MODULE, some_function, [self(), arg2]), + receive + {spawned, SomePid} -> + ok + after 100 -> + error(process_not_spawned) + end, + ProcInfo = emqx_sys_mon:procinfo(SomePid), + ?assertEqual( + {?MODULE, some_function, ['Argument__1','Argument__2']}, + proplists:get_value(proc_lib_initial_call, ProcInfo)), + ?assertMatch( + [{?MODULE, some_function, 2, + [{file, _}, + {line, _}]}, + {proc_lib, init_p_do_apply, 3, + [{file, _}, + {line, _}]}], + proplists:get_value(current_stacktrace, ProcInfo)), + SomePid ! stop. t_sys_mon(_Config) -> lists:foreach( @@ -120,3 +148,10 @@ validate_sys_mon_info(PidOrPort, SysMonName,ValidateInfo, InfoOrPort) -> concat_str(ValidateInfo, InfoOrPort, Info) -> WarnInfo = io_lib:format(ValidateInfo, [InfoOrPort, Info]), lists:flatten(WarnInfo). + +some_function(Parent, _Arg2) -> + Parent ! {spawned, self()}, + receive + stop -> + ok + end.