diff options
author | Lukas Larsson <[email protected]> | 2018-10-29 11:53:10 +0100 |
---|---|---|
committer | Lukas Larsson <[email protected]> | 2019-01-10 10:19:46 +0100 |
commit | 22550188406d4956ad64aecde38190a2f72eeacd (patch) | |
tree | f0d37bc9cff3988fbc91b01fa810f5620669d666 /erts | |
parent | 78e67434b34813b8efe61f8e8dca445dd12b0f7b (diff) | |
download | otp-22550188406d4956ad64aecde38190a2f72eeacd.tar.gz otp-22550188406d4956ad64aecde38190a2f72eeacd.tar.bz2 otp-22550188406d4956ad64aecde38190a2f72eeacd.zip |
erts: Add erlang:system_flag(system_logger,_)
This flag allows logger and other components to set the
process which log messages from ERTS are to be sent.
Diffstat (limited to 'erts')
-rw-r--r-- | erts/doc/src/erlang.xml | 98 | ||||
-rw-r--r-- | erts/emulator/beam/bif.c | 58 | ||||
-rw-r--r-- | erts/emulator/beam/erl_bif_info.c | 2 | ||||
-rw-r--r-- | erts/emulator/beam/erl_trace.c | 44 | ||||
-rw-r--r-- | erts/emulator/beam/erl_trace.h | 2 | ||||
-rw-r--r-- | erts/emulator/test/system_info_SUITE.erl | 84 | ||||
-rw-r--r-- | erts/preloaded/src/erlang.erl | 6 |
7 files changed, 196 insertions, 98 deletions
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index a42323b13d..7699f64c25 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -7539,7 +7539,39 @@ ok </func> <func> - <name name="system_flag" arity="2" clause_i="14" since=""/> + <name name="system_flag" arity="2" clause_i="14" since="OTP 21.3"/> + <fsummary>Set system logger process.</fsummary> + <desc> + <p>Sets the process that will receive the logging + messages generated by ERTS. If set to <c>undefined</c>, + all logging messages generated by ERTS will be dropped. + The messages will be in the format:</p> + <code> +{log,Level,Format,ArgList,Metadata} where + +Level = atom(), +Format = string(), +ArgList = list(term()), +Metadata = #{ pid => pid(), + group_leader => pid(), + time := logger:timestamp(), + error_logger := #{ emulator := true, tag := atom() } + </code> + <p>If the <c>system_logger</c> process dies, + this flag will be reset to <c>logger</c>.</p> + <p>The default is the process named <c>logger</c>.</p> + <p>Returns the old value of the flag.</p> + <note><p>This function is designed to be used by the + KERNEL <seealso marker="kernel:logger"><c>logger</c></seealso>. + Be careful if you change it to something else as + log messages may be lost. If you want to intercept + emulator log messages, do it by adding a specialized handler + to the KERNEL logger.</p></note> + </desc> + </func> + + <func> + <name name="system_flag" arity="2" clause_i="15" since=""/> <fsummary>Set system flag trace_control_word.</fsummary> <desc> <p>Sets the value of the node trace control word to @@ -7553,7 +7585,7 @@ ok </func> <func> - <name name="system_flag" arity="2" clause_i="15" + <name name="system_flag" arity="2" clause_i="16" anchor="system_flag_time_offset" since="?"/> <fsummary>Finalize the time offset.</fsummary> <desc> @@ -7703,8 +7735,9 @@ ok <seealso marker="#system_info_nif_version"><c>nif_version</c></seealso>, <seealso marker="#system_info_otp_release"><c>otp_release</c></seealso>, <seealso marker="#system_info_port_parallelism"><c>port_parallelism</c></seealso>, - <seealso marker="#system_info_system_version"><c>system_version</c></seealso>, <seealso marker="#system_info_system_architecture"><c>system_architecture</c></seealso>, + <seealso marker="#system_info_system_logger"><c>system_logger</c></seealso>, + <seealso marker="#system_info_system_version"><c>system_version</c></seealso>, <seealso marker="#system_info_trace_control_word"><c>trace_control_word</c></seealso>, <seealso marker="#system_info_version"><c>version</c></seealso>, <seealso marker="#system_info_wordsize"><c>wordsize</c></seealso> @@ -7876,7 +7909,7 @@ ok anchor="system_info_cpu_topology" since=""/> <!-- cpu_topology --> <name name="system_info" arity="1" clause_i="13" since=""/> <!-- {cpu_topology, _} --> <name name="system_info" arity="1" clause_i="38" since=""/> <!-- logical_processors --> - <name name="system_info" arity="1" clause_i="73" since="?"/> <!-- update_cpu_info --> + <name name="system_info" arity="1" clause_i="74" since="?"/> <!-- update_cpu_info --> <fsummary>Information about the CPU topology of the system.</fsummary> <type name="cpu_topology"/> <type name="level_entry"/> @@ -8231,10 +8264,10 @@ ok <name name="system_info" arity="1" clause_i="50" since="OTP 18.0"/> <!-- os_monotonic_time_source --> <name name="system_info" arity="1" clause_i="51" since="OTP 18.0"/> <!-- os_system_time_source --> <name name="system_info" arity="1" clause_i="63" since="OTP 18.0"/> <!-- start_time --> - <name name="system_info" arity="1" clause_i="68" since="OTP 18.0"/> <!-- time_correction --> - <name name="system_info" arity="1" clause_i="69" since="OTP 18.0"/> <!-- time_offset --> - <name name="system_info" arity="1" clause_i="70" since="OTP 18.0"/> <!-- time_warp_mode --> - <name name="system_info" arity="1" clause_i="71" since="?"/> <!-- tolerant_timeofday --> + <name name="system_info" arity="1" clause_i="69" since="OTP 18.0"/> <!-- time_correction --> + <name name="system_info" arity="1" clause_i="70" since="OTP 18.0"/> <!-- time_offset --> + <name name="system_info" arity="1" clause_i="71" since="OTP 18.0"/> <!-- time_warp_mode --> + <name name="system_info" arity="1" clause_i="72" since="?"/> <!-- tolerant_timeofday --> <fsummary>Information about system time.</fsummary> <desc> <marker id="system_info_time_tags"/> @@ -8466,8 +8499,8 @@ ok <name name="system_info" arity="1" clause_i="60" since=""/> <!-- scheduler_id --> <name name="system_info" arity="1" clause_i="61" since=""/> <!-- schedulers --> <name name="system_info" arity="1" clause_i="62" since=""/> <!-- smp_support --> - <name name="system_info" arity="1" clause_i="66" since=""/> <!-- threads --> - <name name="system_info" arity="1" clause_i="67" since=""/> <!-- thread_pool_size --> + <name name="system_info" arity="1" clause_i="67" since=""/> <!-- threads --> + <name name="system_info" arity="1" clause_i="68" since=""/> <!-- thread_pool_size --> <fsummary>Information about system schedulers.</fsummary> <desc> <marker id="system_info_scheduler_tags"/> @@ -8889,19 +8922,20 @@ ok <!-- <name name="system_info" arity="1" clause_i="61"/> schedulers --> <!-- <name name="system_info" arity="1" clause_i="62"/> smp_support --> <!-- <name name="system_info" arity="1" clause_i="63"/> start_time --> - <name name="system_info" arity="1" clause_i="64" since=""/> <!-- system_version --> - <name name="system_info" arity="1" clause_i="65" since=""/> <!-- system_architecture --> - <!-- <name name="system_info" arity="1" clause_i="66"/> threads --> - <!-- <name name="system_info" arity="1" clause_i="67"/> thread_pool_size --> - <!-- <name name="system_info" arity="1" clause_i="68"/> time_correction --> - <!-- <name name="system_info" arity="1" clause_i="69"/> time_offset --> - <!-- <name name="system_info" arity="1" clause_i="70"/> time_warp_mode --> - <!-- <name name="system_info" arity="1" clause_i="71"/> tolerant_timeofday --> - <name name="system_info" arity="1" clause_i="72" since=""/> <!-- trace_control_word --> - <!-- <name name="system_info" arity="1" clause_i="73"/> update_cpu_info --> - <name name="system_info" arity="1" clause_i="74" since=""/> <!-- version --> - <name name="system_info" arity="1" clause_i="75" since=""/> <!-- wordsize --> - <!-- <name name="system_info" arity="1" clause_i="76"/> overview --> + <name name="system_info" arity="1" clause_i="64" since=""/> <!-- system_architecture --> + <name name="system_info" arity="1" clause_i="65" since="OTP 21.3"/> <!-- system_logger --> + <name name="system_info" arity="1" clause_i="66" since=""/> <!-- system_version --> + <!-- <name name="system_info" arity="1" clause_i="67"/> threads --> + <!-- <name name="system_info" arity="1" clause_i="68"/> thread_pool_size --> + <!-- <name name="system_info" arity="1" clause_i="69"/> time_correction --> + <!-- <name name="system_info" arity="1" clause_i="70"/> time_offset --> + <!-- <name name="system_info" arity="1" clause_i="71"/> time_warp_mode --> + <!-- <name name="system_info" arity="1" clause_i="72"/> tolerant_timeofday --> + <name name="system_info" arity="1" clause_i="73" since=""/> <!-- trace_control_word --> + <!-- <name name="system_info" arity="1" clause_i="74"/> update_cpu_info --> + <name name="system_info" arity="1" clause_i="75" since=""/> <!-- version --> + <name name="system_info" arity="1" clause_i="76" since=""/> <!-- wordsize --> + <!-- <name name="system_info" arity="1" clause_i="77"/> overview --> <fsummary>Information about the system.</fsummary> <desc> <marker id="system_info_misc_tags"/> @@ -9057,18 +9091,24 @@ ok <seealso marker="erl#+spp"><c>+spp</c></seealso> in <c>erl(1)</c>.</p> </item> - <tag><marker id="system_info_system_version"/> - <c>system_version</c></tag> - <item> - <p>Returns a string containing version number and - some important properties, such as the number of schedulers.</p> - </item> <tag><marker id="system_info_system_architecture"/> <c>system_architecture</c></tag> <item> <p>Returns a string containing the processor and OS architecture the emulator is built for.</p> </item> + <tag><marker id="system_info_system_logger"/> + <c>system_logger</c></tag> + <item> + <p>Returns the current <c>system_logger</c> as set by + <seealso marker="#system_flag/2"><c>erlang:system_flag(system_logger, _)</c></seealso>.</p> + </item> + <tag><marker id="system_info_system_version"/> + <c>system_version</c></tag> + <item> + <p>Returns a string containing version number and + some important properties, such as the number of schedulers.</p> + </item> <tag><marker id="system_info_trace_control_word"/> <c>trace_control_word</c></tag> <item> diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index f1fac7f8d0..b13c6c90c6 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -4701,6 +4701,9 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2) return erts_bind_schedulers(BIF_P, BIF_ARG_2); } else if (ERTS_IS_ATOM_STR("erts_alloc", BIF_ARG_1)) { return erts_alloc_set_dyn_param(BIF_P, BIF_ARG_2); + } else if (ERTS_IS_ATOM_STR("system_logger", BIF_ARG_1)) { + Eterm res = erts_set_system_logger(BIF_ARG_2); + if (is_value(res)) BIF_RET(res); } error: BIF_ERROR(BIF_P, BADARG); @@ -5203,61 +5206,6 @@ erts_call_dirty_bif(ErtsSchedulerData *esdp, Process *c_p, BeamInstr *I, Eterm * return exiting; } - - -#ifdef HARDDEBUG -/* -You'll need this line in bif.tab to be able to use this debug bif - -bif erlang:send_to_logger/2 - -*/ -BIF_RETTYPE send_to_logger_2(BIF_ALIST_2) -{ - byte *buf; - ErlDrvSizeT len; - if (!is_atom(BIF_ARG_1) || !(is_list(BIF_ARG_2) || - is_nil(BIF_ARG_1))) { - BIF_ERROR(BIF_P,BADARG); - } - if (erts_iolist_size(BIF_ARG_2, &len) != 0) - BIF_ERROR(BIF_P,BADARG); - else if (len == 0) - buf = ""; - else { -#ifdef DEBUG - ErlDrvSizeT len2; -#endif - buf = (byte *) erts_alloc(ERTS_ALC_T_TMP, len+1); -#ifdef DEBUG - len2 = -#else - (void) -#endif - erts_iolist_to_buf(BIF_ARG_2, buf, len); - ASSERT(len2 == len); - buf[len] = '\0'; - switch (BIF_ARG_1) { - case am_info: - erts_send_info_to_logger(BIF_P->group_leader, buf, len); - break; - case am_warning: - erts_send_warning_to_logger(BIF_P->group_leader, buf, len); - break; - case am_error: - erts_send_error_to_logger(BIF_P->group_leader, buf, len); - break; - default: - { - BIF_ERROR(BIF_P,BADARG); - } - } - erts_free(ERTS_ALC_T_TMP, (void *) buf); - } - BIF_RET(am_true); -} -#endif /* HARDDEBUG */ - BIF_RETTYPE get_module_info_1(BIF_ALIST_1) { Eterm ret = erts_module_info_0(BIF_P, BIF_ARG_1); diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c index 7fada0d548..9cc95a5c09 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -3139,6 +3139,8 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1) DECL_AM(tag); BIF_RET(AM_tag); #endif + } else if (ERTS_IS_ATOM_STR("system_logger", BIF_ARG_1)) { + BIF_RET(erts_get_system_logger()); } BIF_ERROR(BIF_P, BADARG); diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c index 2350d4c02f..701fb38147 100644 --- a/erts/emulator/beam/erl_trace.c +++ b/erts/emulator/beam/erl_trace.c @@ -72,6 +72,7 @@ static ErtsTracer default_port_tracer; static Eterm system_monitor; static Eterm system_profile; +static erts_aint_t system_logger; #ifdef HAVE_ERTS_NOW_CPU int erts_cpu_timestamp; @@ -340,6 +341,7 @@ void erts_init_trace(void) { default_port_trace_flags = F_INITIAL_TRACE_FLAGS; default_port_tracer = erts_tracer_nil; system_seq_tracer = erts_tracer_nil; + erts_atomic_init_nob(&system_logger, am_logger); init_sys_msg_dispatcher(); init_tracer_nif(); } @@ -2027,10 +2029,24 @@ enqueue_sys_msg(enum ErtsSysMsgType type, erts_mtx_unlock(&smq_mtx); } +Eterm +erts_get_system_logger(void) +{ + return (Eterm)erts_atomic_read_nob(&system_logger); +} + +Eterm +erts_set_system_logger(Eterm logger) +{ + if (logger != am_logger && logger != am_undefined && !is_internal_pid(logger)) + return THE_NON_VALUE; + return (Eterm)erts_atomic_xchg_nob(&system_logger, logger); +} + void erts_queue_error_logger_message(Eterm from, Eterm msg, ErlHeapFragment *bp) { - enqueue_sys_msg(SYS_MSG_TYPE_ERRLGR, from, am_logger, msg, bp); + enqueue_sys_msg(SYS_MSG_TYPE_ERRLGR, from, erts_get_system_logger(), msg, bp); } void @@ -2271,7 +2287,7 @@ sys_msg_dispatcher_func(void *unused) } break; case SYS_MSG_TYPE_ERRLGR: - receiver = am_logger; + receiver = smqp->to; break; default: receiver = NIL; @@ -2285,8 +2301,15 @@ sys_msg_dispatcher_func(void *unused) if (is_internal_pid(receiver)) { proc = erts_pid2proc(NULL, 0, receiver, proc_locks); if (!proc) { - /* Bad tracer */ - goto failure; + if (smqp->type == SYS_MSG_TYPE_ERRLGR) { + /* Bad logger process, send to kernel 'logger' process */ + erts_set_system_logger(am_logger); + receiver = erts_get_system_logger(); + goto logger; + } else { + /* Bad tracer */ + goto failure; + } } else { ErtsMessage *mp; @@ -2299,9 +2322,9 @@ sys_msg_dispatcher_func(void *unused) #endif erts_proc_unlock(proc, proc_locks); } - } - else if (receiver == am_logger) { - proc = erts_whereis_process(NULL,0,receiver,proc_locks,0); + } else if (receiver == am_logger) { + logger: + proc = erts_whereis_process(NULL,0,am_logger,proc_locks,0); if (!proc) goto failure; else if (smqp->from == proc->common.id) @@ -2309,7 +2332,10 @@ sys_msg_dispatcher_func(void *unused) else goto queue_proc_msg; } - else if (is_internal_port(receiver)) { + else if (receiver == am_undefined) { + goto drop_sys_msg; + } + else if (is_internal_port(receiver)) { port = erts_thr_id2port_sflgs(receiver, ERTS_PORT_SFLGS_INVALID_TRACER_LOOKUP); if (!port) @@ -2366,7 +2392,7 @@ erts_foreach_sys_msg_in_q(void (*func)(Eterm, to = erts_get_system_profile(); break; case SYS_MSG_TYPE_ERRLGR: - to = am_logger; + to = erts_get_system_logger(); break; default: to = NIL; diff --git a/erts/emulator/beam/erl_trace.h b/erts/emulator/beam/erl_trace.h index bccf31606e..b7844d1cb0 100644 --- a/erts/emulator/beam/erl_trace.h +++ b/erts/emulator/beam/erl_trace.h @@ -94,6 +94,8 @@ void erts_foreach_sys_msg_in_q(void (*func)(Eterm, Eterm, Eterm, ErlHeapFragment *)); +Eterm erts_set_system_logger(Eterm); +Eterm erts_get_system_logger(void); void erts_queue_error_logger_message(Eterm, Eterm, ErlHeapFragment *); void erts_send_sys_msg_proc(Eterm, Eterm, Eterm, ErlHeapFragment *); diff --git a/erts/emulator/test/system_info_SUITE.erl b/erts/emulator/test/system_info_SUITE.erl index 21ab6b378a..4e663fed7f 100644 --- a/erts/emulator/test/system_info_SUITE.erl +++ b/erts/emulator/test/system_info_SUITE.erl @@ -37,8 +37,9 @@ -export([process_count/1, system_version/1, misc_smoke_tests/1, heap_size/1, wordsize/1, memory/1, ets_limit/1, atom_limit/1, - ets_count/1, - atom_count/1]). + ets_count/1, atom_count/1, system_logger/1]). + +-export([init/1, handle_event/2, handle_call/2]). suite() -> [{ct_hooks,[ts_install_cth]}, @@ -46,8 +47,8 @@ suite() -> all() -> [process_count, system_version, misc_smoke_tests, - ets_count, - heap_size, wordsize, memory, ets_limit, atom_limit, atom_count]. + ets_count, heap_size, wordsize, memory, ets_limit, atom_limit, atom_count, + system_logger]. %%% %%% The test cases ------------------------------------------------------------- @@ -573,3 +574,78 @@ atom_count(Config) when is_list(Config) -> true = Limit >= Count2, true = Count2 > Count1, ok. + + +system_logger(Config) when is_list(Config) -> + + TC = self(), + + ok = error_logger:add_report_handler(?MODULE, [TC]), + + generate_log_event(), + + flush(1, report_handler), + + Initial = erlang:system_info(system_logger), + + {Logger,_} = spawn_monitor(fun F() -> receive M -> TC ! {system_logger,M}, F() end end), + + Initial = erlang:system_flag(system_logger, Logger), + Logger = erlang:system_info(system_logger), + + generate_log_event(), + flush(1, system_logger), + + Logger = erlang:system_flag(system_logger, Logger), + + generate_log_event(), + flush(1, system_logger), + + exit(Logger, die), + receive {'DOWN',_,_,_,_} -> ok end, + + generate_log_event(), + flush(1, report_handler), + + logger = erlang:system_info(system_logger), + + logger = erlang:system_flag(system_logger, undefined), + generate_log_event(), + flush(), + + undefined = erlang:system_flag(system_logger, Initial), + + ok. + +flush() -> + receive + M -> + ct:fail({unexpected_message, M}) + after 0 -> + ok + end. + +flush(0, _Pat) -> + flush(); +flush(Cnt, Pat) -> + receive + M when element(1,M) =:= Pat -> + ct:log("~p",[M]), + flush(Cnt-1, Pat) + after 500 -> + ct:fail({missing, Cnt, Pat}) + end. + +generate_log_event() -> + {_Pid, Ref} = spawn_monitor(fun() -> ok = nok end), + receive {'DOWN', Ref, _, _, _} -> ok end. + +init([To]) -> + {ok, To}. + +handle_call(Msg, State) -> + {ok, Msg, State}. + +handle_event(Event, State) -> + State ! {report_handler, Event}, + {ok, State}. diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl index c20082a545..5730e999cb 100644 --- a/erts/preloaded/src/erlang.erl +++ b/erts/preloaded/src/erlang.erl @@ -2526,6 +2526,9 @@ subtract(_,_) -> OldSchedulersOnline when SchedulersOnline :: pos_integer(), OldSchedulersOnline :: pos_integer(); + (system_logger, Logger) -> PrevLogger when + Logger :: logger | undefined | pid(), + PrevLogger :: logger | undefined | pid(); (trace_control_word, TCW) -> OldTCW when TCW :: non_neg_integer(), OldTCW :: non_neg_integer(); @@ -2731,8 +2734,9 @@ tuple_to_list(_Tuple) -> (schedulers | schedulers_online) -> pos_integer(); (smp_support) -> boolean(); (start_time) -> integer(); - (system_version) -> string(); (system_architecture) -> string(); + (system_logger) -> logger | undefined | pid(); + (system_version) -> string(); (threads) -> boolean(); (thread_pool_size) -> non_neg_integer(); (time_correction) -> true | false; |