diff options
author | Lukas Larsson <lukas@erlang.org> | 2021-09-30 11:49:30 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-30 11:49:30 +0200 |
commit | 0efa5ed6563614b2e68be9790c7b6bb3205658de (patch) | |
tree | 6173e3c81c9cdf9fe2931e0bff7672d308c283c7 | |
parent | 1f26b218ea612627a3ae10af06680627fff20cfc (diff) | |
parent | f7916862465ad18eb1b71a17a714449a20f29733 (diff) | |
download | erlang-0efa5ed6563614b2e68be9790c7b6bb3205658de.tar.gz |
Merge pull request #5186 from hauleth/feat/allow-reconfiguration-of-logger/OTP-17375
Allow reconfiguration of logger
-rw-r--r-- | lib/kernel/doc/src/logger.xml | 12 | ||||
-rw-r--r-- | lib/kernel/src/logger.erl | 30 | ||||
-rw-r--r-- | lib/kernel/test/logger_SUITE.erl | 59 |
3 files changed, 62 insertions, 39 deletions
diff --git a/lib/kernel/doc/src/logger.xml b/lib/kernel/doc/src/logger.xml index 1c17004aa0..68d1984c7f 100644 --- a/lib/kernel/doc/src/logger.xml +++ b/lib/kernel/doc/src/logger.xml @@ -1189,6 +1189,18 @@ logger:set_proxy_config(maps:merge(Old, Config)). </desc> </func> + <func> + <name name="reconfigure" arity="0" since="OTP @OTP-17375@"/> + <fsummary>Reconfigure Logger.</fsummary> + <desc> + <p>Reconfigure Logger using updated <c>kernel</c> configuration + that was set after <c>kernel</c> application was loaded.</p> + <p>Beware, that this is meant to be run only by the build tools, + not manually during application lifetime, as this may cause + missing log entries.</p> + </desc> + </func> + </funcs> diff --git a/lib/kernel/src/logger.erl b/lib/kernel/src/logger.erl index ea75c8d720..9107bf0e61 100644 --- a/lib/kernel/src/logger.erl +++ b/lib/kernel/src/logger.erl @@ -51,9 +51,9 @@ get_primary_config/0, get_handler_config/1, get_handler_config/0, get_handler_ids/0, get_config/0, get_proxy_config/0, - add_handlers/1]). + add_handlers/1, + reconfigure/0]). -%% Private configuration -export([internal_init_logger/0]). %% Misc @@ -794,6 +794,31 @@ print_module_levels(Modules,M) -> [print_module_levels(Module,M) || Module <- Modules], ok. +-spec reconfigure() -> ok | {error,term()}. +%% This function is meant to be used by the build tools like Rebar3 or Mix +%% to ensure that the logger configuration is reset to the expected state +%% before running main application. +reconfigure() -> + try + [case logger:remove_handler(Id) of + ok -> ok; + {error, Reason} -> throw({remove, Id, Reason}) + end || #{id := Id} <- logger:get_handler_config()], + ok=logger:add_handler(simple,logger_simple_h, + #{filter_default=>stop, + filters=>?DEFAULT_HANDLER_FILTERS}), + logger:unset_module_level(), + internal_init_logger() + of + ok -> + logger:add_handlers(kernel); + Error -> + Error + catch + throw:Reason -> + {error, Reason} + end. + -spec internal_init_logger() -> ok | {error,term()}. %% This function is responsible for config of the logger %% This is done before add_handlers because we want the @@ -807,6 +832,7 @@ internal_init_logger() -> ok = logger:set_primary_config(metadata, get_primary_metadata()), ok = logger:set_primary_config(filter_default, get_primary_filter_default(Env)), + ok = logger:set_primary_config(filters, []), [case logger:add_primary_filter(Id, Filter) of ok -> ok; diff --git a/lib/kernel/test/logger_SUITE.erl b/lib/kernel/test/logger_SUITE.erl index 82533ab572..5545759b5d 100644 --- a/lib/kernel/test/logger_SUITE.erl +++ b/lib/kernel/test/logger_SUITE.erl @@ -24,6 +24,7 @@ -include_lib("common_test/include/ct.hrl"). -include_lib("kernel/include/logger.hrl"). -include_lib("kernel/src/logger_internal.hrl"). +-include_lib("stdlib/include/assert.hrl"). -define(str,"Log from "++atom_to_list(?FUNCTION_NAME)++ ":"++integer_to_list(?LINE)). @@ -1009,15 +1010,14 @@ app_config(Config) -> %% start, it is not possible to see code coverage in that test. kernel_config(Config) -> %% Start a node with simple handler only, then simulate kernel - %% start by calling internally exported - %% internal_init_logger(). This is to test all variants of kernel - %% config, including bad config, and see the code coverage. + %% start by calling logger:reconfigure(). This is to test all + %% variants of kernel config, including bad config, and see + %% the code coverage. {ok,#{handlers:=[#{id:=simple,filters:=DF}]}=LC,Node} = logger_test_lib:setup(Config,[{error_logger,false}]), %% Same once more, to get coverage ok = rpc:call(Node,logger,internal_init_logger,[]), - ok = rpc:call(Node,logger,add_handlers,[kernel]), LC = rpc:call(Node,logger,get_config,[]), %% This shall mean the same as above, but using 'logger' parameter @@ -1025,15 +1025,13 @@ kernel_config(Config) -> ok = rpc:call(Node,application,unset_env,[kernel,error_logger]), ok = rpc:call(Node,application,set_env, [kernel,logger,[{handler,default,undefined}]]), - ok = rpc:call(Node,logger,internal_init_logger,[]), - ok = rpc:call(Node,logger,add_handlers,[kernel]), - LC = rpc:call(Node,logger,get_config,[]), + ok = rpc:call(Node,logger,reconfigure,[]), + ?assertEqual(LC, rpc:call(Node,logger,get_config,[])), %% Silent ok = rpc:call(Node,application,unset_env,[kernel,logger]), ok = rpc:call(Node,application,set_env,[kernel,error_logger,silent]), - ok = rpc:call(Node,logger,internal_init_logger,[]), - ok = rpc:call(Node,logger,add_handlers,[kernel]), + ok = rpc:call(Node,logger,reconfigure,[]), #{primary:=#{filter_default:=log,filters:=[]}, handlers:=[], module_levels:=[]} = rpc:call(Node,logger,get_config,[]), @@ -1041,30 +1039,25 @@ kernel_config(Config) -> %% Default ok = rpc:call(Node,application,unset_env,[kernel,error_logger]), ok = rpc:call(Node,application,unset_env,[kernel,logger]), - ok = rpc:call(Node,logger,internal_init_logger,[]), - ok = rpc:call(Node,logger,add_handlers,[kernel]), + ok = rpc:call(Node,logger,reconfigure,[]), #{primary:=#{filter_default:=log,filters:=[]}, handlers:=[#{id:=default,filters:=DF,config:=#{type:=standard_io}}], module_levels:=[]} = rpc:call(Node,logger,get_config,[]), %% error_logger=tty (same as default) - ok = rpc:call(Node,logger,remove_handler,[default]),% so it can be added again ok = rpc:call(Node,application,set_env,[kernel,error_logger,tty]), ok = rpc:call(Node,application,unset_env,[kernel,logger]), - ok = rpc:call(Node,logger,internal_init_logger,[]), - ok = rpc:call(Node,logger,add_handlers,[kernel]), + ok = rpc:call(Node,logger,reconfigure,[]), #{primary:=#{filter_default:=log,filters:=[]}, handlers:=[#{id:=default,filters:=DF,config:=#{type:=standard_io}}], module_levels:=[]} = rpc:call(Node,logger,get_config,[]), %% error_logger={file,File} - ok = rpc:call(Node,logger,remove_handler,[default]),% so it can be added again F = filename:join(?config(priv_dir,Config), atom_to_list(?FUNCTION_NAME)++".log"), ok = rpc:call(Node,application,set_env,[kernel,error_logger,{file,F}]), ok = rpc:call(Node,application,unset_env,[kernel,logger]), - ok = rpc:call(Node,logger,internal_init_logger,[]), - ok = rpc:call(Node,logger,add_handlers,[kernel]), + ok = rpc:call(Node,logger,reconfigure,[]), #{primary:=#{filter_default:=log,filters:=[]}, handlers:=[#{id:=default,filters:=DF, config:=#{type:=file,file:=F,modes:=Modes}}], @@ -1073,55 +1066,47 @@ kernel_config(Config) -> %% Same, but using 'logger' parameter instead of 'error_logger' - ok = rpc:call(Node,logger,remove_handler,[default]),% so it can be added again ok = rpc:call(Node,application,unset_env,[kernel,error_logger]), ok = rpc:call(Node,application,set_env,[kernel,logger, [{handler,default,logger_std_h, #{config=>#{type=>{file,F}}}}]]), - ok = rpc:call(Node,logger,internal_init_logger,[]), - ok = rpc:call(Node,logger,add_handlers,[kernel]), + ok = rpc:call(Node,logger,reconfigure,[]), #{primary:=#{filter_default:=log,filters:=[]}, handlers:=[#{id:=default,filters:=DF, config:=#{type:=file,file:=F,modes:=Modes}}], module_levels:=[]} = rpc:call(Node,logger,get_config,[]), %% Same, but with type={file,File,Modes} - ok = rpc:call(Node,logger,remove_handler,[default]),% so it can be added again ok = rpc:call(Node,application,unset_env,[kernel,error_logger]), M = [raw,write], ok = rpc:call(Node,application,set_env,[kernel,logger, [{handler,default,logger_std_h, #{config=>#{type=>{file,F,M}}}}]]), - ok = rpc:call(Node,logger,internal_init_logger,[]), - ok = rpc:call(Node,logger,add_handlers,[kernel]), + ok = rpc:call(Node,logger,reconfigure,[]), #{primary:=#{filter_default:=log,filters:=[]}, handlers:=[#{id:=default,filters:=DF, config:=#{type:=file,file:=F,modes:=[delayed_write|M]}}], module_levels:=[]} = rpc:call(Node,logger,get_config,[]), %% Same, but with disk_log handler - ok = rpc:call(Node,logger,remove_handler,[default]),% so it can be added again ok = rpc:call(Node,application,unset_env,[kernel,error_logger]), ok = rpc:call(Node,application,set_env,[kernel,logger, [{handler,default,logger_disk_log_h, #{config=>#{file=>F}}}]]), - ok = rpc:call(Node,logger,internal_init_logger,[]), - ok = rpc:call(Node,logger,add_handlers,[kernel]), + ok = rpc:call(Node,logger,reconfigure,[]), #{primary:=#{filter_default:=log,filters:=[]}, handlers:=[#{id:=default,filters:=DF,config:=#{file:=F}}], module_levels:=[]} = rpc:call(Node,logger,get_config,[]), %% Set primary filters and module level. No default handler. - ok = rpc:call(Node,logger,remove_handler,[default]),% so it can be added again ok = rpc:call(Node,application,unset_env,[kernel,error_logger]), ok = rpc:call(Node,application,set_env, [kernel,logger,[{handler,default,undefined}, {filters,stop,[{f1,{fun(_,_) -> log end,ok}}]}, {module_level,debug,[?MODULE]}]]), - ok = rpc:call(Node,logger,internal_init_logger,[]), - ok = rpc:call(Node,logger,add_handlers,[kernel]), + ok = rpc:call(Node,logger,reconfigure,[]), #{primary:=#{filter_default:=stop,filters:=[_]}, - handlers:=[], + handlers:=[#{id:=simple}], module_levels:=[{?MODULE,debug}]} = rpc:call(Node,logger,get_config,[]), %% Bad config @@ -1129,38 +1114,38 @@ kernel_config(Config) -> ok = rpc:call(Node,application,set_env,[kernel,error_logger,bad]), {error,{bad_config,{kernel,{error_logger,bad}}}} = - rpc:call(Node,logger,internal_init_logger,[]), + rpc:call(Node,logger,reconfigure,[]), ok = rpc:call(Node,application,unset_env,[kernel,error_logger]), ok = rpc:call(Node,application,set_env,[kernel,logger_level,bad]), {error,{bad_config,{kernel,{logger_level,bad}}}} = - rpc:call(Node,logger,internal_init_logger,[]), + rpc:call(Node,logger,reconfigure,[]), ok = rpc:call(Node,application,unset_env,[kernel,logger_level]), ok = rpc:call(Node,application,set_env, [kernel,logger,[{filters,stop,[bad]}]]), {error,{bad_config,{kernel,{invalid_filters,[bad]}}}} = - rpc:call(Node,logger,internal_init_logger,[]), + rpc:call(Node,logger,reconfigure,[]), ok = rpc:call(Node,application,set_env, [kernel,logger,[{filters,stop,[bad]}]]), {error,{bad_config,{kernel,{invalid_filters,[bad]}}}} = - rpc:call(Node,logger,internal_init_logger,[]), + rpc:call(Node,logger,reconfigure,[]), ok = rpc:call(Node,application,set_env, [kernel,logger,[{filters,stop,[{f1,bad}]}]]), {error,{bad_config,{kernel,{invalid_filter,{f1,bad}}}}} = - rpc:call(Node,logger,internal_init_logger,[]), + rpc:call(Node,logger,reconfigure,[]), ok = rpc:call(Node,application,set_env, [kernel,logger,MF=[{filters,stop,[]},{filters,log,[]}]]), {error,{bad_config,{kernel,{multiple_filters,MF}}}} = - rpc:call(Node,logger,internal_init_logger,[]), + rpc:call(Node,logger,reconfigure,[]), ok = rpc:call(Node,application,set_env, [kernel,logger,[{module_level,bad,[?MODULE]}]]), {error,{bad_config,{kernel,{invalid_level,bad}}}} = - rpc:call(Node,logger,internal_init_logger,[]), + rpc:call(Node,logger,reconfigure,[]), ok. |