From 224a42d658d3c08e3ce080fa8041c161e16f3863 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Thu, 20 Sep 2018 16:56:26 +0200 Subject: [logger] Add SetOrUpdate parameter to handler callback changing_config Since logger has now knowledge of the handler specific data ('config' field in the handler configuration map), it can not merge this data structure with default or old values upon configuration change. Instead, the handler callback changing_config must do this. Earlier, this callback did not reflect if the configuration change was initiated by a call to set_handler_config or update_handler_config, so the handler did not know if unspecified fields should get default values or the values from the existing configuration. To overcome this problem, the new parameter SetOrUpdate is added to this callback. If SetOrUpdate equals set, then default values should be used. If SetOrUpdate equals update, then existing configuration values should be used. --- lib/kernel/doc/src/logger.xml | 26 ++++++++++---- lib/kernel/doc/src/logger_chapter.xml | 6 ++-- lib/kernel/src/logger_server.erl | 64 ++++++++++++++++++++++++----------- 3 files changed, 67 insertions(+), 29 deletions(-) diff --git a/lib/kernel/doc/src/logger.xml b/lib/kernel/doc/src/logger.xml index 464c65ba76..8f54d0e54f 100644 --- a/lib/kernel/doc/src/logger.xml +++ b/lib/kernel/doc/src/logger.xml @@ -1041,10 +1041,11 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)). - HModule:changing_config(Config1, Config2) -> {ok, Config3} | {error, Reason} + HModule:changing_config(SetOrUpdate, OldConfig, NewConfig) -> {ok, Config} | {error, Reason} The configuration for this handler is about to change. - Config1 = Config2 = Config3 = + SetOrUpdate = set | update + OldConfig = NewConfig = Config = handler_config() Reason = term() @@ -1053,12 +1054,25 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)).

The function is called on a temporary process when the configuration for a handler is about to change. The purpose is to verify and act on the new configuration.

-

Config1 is the existing configuration - and Config2 is the new configuration.

+

OldConfig is the existing configuration + and NewConfig is the new configuration.

The handler identity is associated with the id key - in Config1.

+ in OldConfig.

+

SetOrUpdate has the value set if the + configuration change originates from a call to + + set_handler_config/2,3, and update + if it originates from + update_handler_config/2. The handler can + use this parameteter to decide how to update the value of + the config field, that is, the handler specific + configuration data. Typically, if SetOrUpdate + equals set, values that are not specified must be + given their default values. If SetOrUpdate + equals update, the values found in OldConfig + must be used instead.

If everything succeeds, the callback function must return a - possibly adjusted configuration in {ok,Config3}.

+ possibly adjusted configuration in {ok,Config}.

If the configuration is faulty, the callback function must return {error,Reason}.

diff --git a/lib/kernel/doc/src/logger_chapter.xml b/lib/kernel/doc/src/logger_chapter.xml index 4a81cfa34a..7e88f82dad 100644 --- a/lib/kernel/doc/src/logger_chapter.xml +++ b/lib/kernel/doc/src/logger_chapter.xml @@ -384,7 +384,7 @@ logger:debug(#{got => connection_request, id => Id, state => State},

In addition to the mandatory callback function log/2, a handler module can export the optional callback - functions adding_handler/1, changing_config/2 + functions adding_handler/1, changing_config/3 and removing_handler/1. See section Handler Callback Functions in the logger(3) manual page for @@ -1024,7 +1024,7 @@ ok adding_handler(Config) removing_handler(Config) - changing_config(OldConfig, NewConfig) + changing_config(SetOrUpdate, OldConfig, NewConfig)

When a handler is added, by for example a call to @@ -1045,7 +1045,7 @@ ok or logger:update_handler_config/2 is called, Logger - calls HModule:changing_config(OldConfig, NewConfig). If + calls HModule:changing_config(SetOrUpdate, OldConfig, NewConfig). If this function returns {ok,NewConfig1}, Logger writes NewConfig1 to the configuration database.

diff --git a/lib/kernel/src/logger_server.erl b/lib/kernel/src/logger_server.erl index a1d40f1123..a14de2664e 100644 --- a/lib/kernel/src/logger_server.erl +++ b/lib/kernel/src/logger_server.erl @@ -105,12 +105,17 @@ cache_module_level(Module) -> gen_server:cast(?SERVER,{cache_module_level,Module}). set_config(Owner,Key,Value) -> - update_config(Owner,#{Key=>Value}). + case sanity_check(Owner,Key,Value) of + ok -> + call({change_config,set,Owner,Key,Value}); + Error -> + Error + end. set_config(Owner,Config) -> case sanity_check(Owner,Config) of ok -> - call({set_config,Owner,Config}); + call({change_config,set,Owner,Config}); Error -> Error end. @@ -118,7 +123,7 @@ set_config(Owner,Config) -> update_config(Owner, Config) -> case sanity_check(Owner,Config) of ok -> - call({update_config,Owner,Config}); + call({change_config,update,Owner,Config}); Error -> Error end. @@ -204,17 +209,35 @@ handle_call({add_filter,Id,Filter}, _From,#state{tid=Tid}=State) -> handle_call({remove_filter,Id,FilterId}, _From, #state{tid=Tid}=State) -> Reply = do_remove_filter(Tid,Id,FilterId), {reply,Reply,State}; -handle_call({update_config,primary,NewConfig}, _From, #state{tid=Tid}=State) -> +handle_call({change_config,SetOrUpd,primary,Config0}, _From, + #state{tid=Tid}=State) -> + {ok,#{handlers:=Handlers}=OldConfig} = logger_config:get(Tid,primary), + Default = + case SetOrUpd of + set -> default_config(primary); + update -> OldConfig + end, + Config = maps:merge(Default,Config0), + Reply = logger_config:set(Tid,primary,Config#{handlers=>Handlers}), + {reply,Reply,State}; +handle_call({change_config,_SetOrUpd,primary,Key,Value}, _From, + #state{tid=Tid}=State) -> {ok,OldConfig} = logger_config:get(Tid,primary), - Config = maps:merge(OldConfig,NewConfig), - {reply,logger_config:set(Tid,primary,Config),State}; -handle_call({update_config,HandlerId,NewConfig}, From, #state{tid=Tid}=State) -> + Reply = logger_config:set(Tid,primary,OldConfig#{Key=>Value}), + {reply,Reply,State}; +handle_call({change_config,SetOrUpd,HandlerId,Config0}, From, + #state{tid=Tid}=State) -> case logger_config:get(Tid,HandlerId) of {ok,#{module:=Module}=OldConfig} -> - Config = maps:merge(OldConfig,NewConfig), + Default = + case SetOrUpd of + set -> default_config(HandlerId,Module); + update -> OldConfig + end, + Config = maps:merge(Default,Config0), call_h_async( fun() -> - call_h(Module,changing_config,[OldConfig,Config], + call_h(Module,changing_config,[SetOrUpd,OldConfig,Config], {ok,Config}) end, fun({ok,Config1}) -> @@ -222,21 +245,17 @@ handle_call({update_config,HandlerId,NewConfig}, From, #state{tid=Tid}=State) -> (Error) -> Error end,From,State); - Error -> - {reply,Error,State} + _ -> + {reply,{error,{not_found,HandlerId}},State} end; -handle_call({set_config,primary,Config0}, _From, #state{tid=Tid}=State) -> - Config = maps:merge(default_config(primary),Config0), - {ok,#{handlers:=Handlers}} = logger_config:get(Tid,primary), - Reply = logger_config:set(Tid,primary,Config#{handlers=>Handlers}), - {reply,Reply,State}; -handle_call({set_config,HandlerId,Config0}, From, #state{tid=Tid}=State) -> +handle_call({change_config,SetOrUpd,HandlerId,Key,Value}, From, + #state{tid=Tid}=State) -> case logger_config:get(Tid,HandlerId) of {ok,#{module:=Module}=OldConfig} -> - Config = maps:merge(default_config(HandlerId,Module),Config0), + Config = OldConfig#{Key=>Value}, call_h_async( fun() -> - call_h(Module,changing_config,[OldConfig,Config], + call_h(Module,changing_config,[SetOrUpd,OldConfig,Config], {ok,Config}) end, fun({ok,Config1}) -> @@ -320,7 +339,7 @@ call(Request) -> true when Action == add_handler; Action == remove_handler; Action == add_filter; Action == remove_filter; - Action == update_config; Action == set_config -> + Action == change_config -> {error,{attempting_syncronous_call_to_self,Request}}; _ -> gen_server:call(?SERVER,Request,?DEFAULT_LOGGER_CALL_TIMEOUT) @@ -466,6 +485,11 @@ call_h(Module, Function, Args, DefRet) -> catch C:R:S -> case {C,R,S} of + {error,undef,[{Module,Function=changing_config,Args,_}|_]} + when length(Args)=:=3 -> + %% Backwards compatible call, if changing_config/3 + %% did not exist. + call_h(Module, Function, tl(Args), DefRet); {error,undef,[{Module,Function,Args,_}|_]} -> DefRet; _ -> -- cgit v1.2.3