summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFred Hebert <mononcqc@ferd.ca>2018-09-10 10:20:57 -0400
committerFred Hebert <mononcqc@ferd.ca>2018-09-10 10:20:57 -0400
commit0303567d95f0769f3d76df35d890458d9741cf4d (patch)
treed0358bf54cd748ce852f5e22027df3f420f5a7a5
parent30daae6591a8b042f1cbc69b1d0850c1ff239a40 (diff)
Reload logger config in shell
This requires some fancy dynamic work since the logger is started as part of the kernel and we lost the sys.config from users when working from there. We start conservatively by making it an optional thing, turning it on only where we know it to be safe. The changes are applied _after_ having loaded the rest of configs so if an inoffensive error happens, the shell works (with a bad error message) rather than plain exploding.
-rw-r--r--src/rebar_prv_shell.erl2
-rw-r--r--src/rebar_utils.erl53
2 files changed, 52 insertions, 3 deletions
diff --git a/src/rebar_prv_shell.erl b/src/rebar_prv_shell.erl
index af8d99f..5b8d789 100644
--- a/src/rebar_prv_shell.erl
+++ b/src/rebar_prv_shell.erl
@@ -385,7 +385,7 @@ reread_config(AppsToStart, State) ->
lists:member(App, Running),
lists:member(App, AppsToStart),
not lists:member(App, BlackList)],
- _ = rebar_utils:reread_config(ConfigList),
+ _ = rebar_utils:reread_config(ConfigList, [update_logger]),
ok
end.
diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl
index 2ded481..7e57d01 100644
--- a/src/rebar_utils.erl
+++ b/src/rebar_utils.erl
@@ -72,7 +72,7 @@
info_useless/2,
list_dir/1,
user_agent/0,
- reread_config/1,
+ reread_config/1, reread_config/2,
get_proxy_auth/0,
is_list_of_strings/1]).
@@ -436,6 +436,18 @@ user_agent() ->
?FMT("Rebar/~ts (OTP/~ts)", [Vsn, otp_release()]).
reread_config(ConfigList) ->
+ %% Default to not re-configuring the logger for now;
+ %% this can leak logs in CT redirection when setting up hooks
+ %% for example. If we want to turn it on by default, we may
+ %% want to disable it in CT at the same time or figure out a
+ %% way to silence it.
+ %% The same pattern may apply to other tasks, so let's enable
+ %% case-by-case.
+ reread_config(ConfigList, []).
+
+reread_config(ConfigList, Opts) ->
+ UpdateLoggerConfig = erlang:function_exported(logger, module_info, 0) andalso
+ proplists:get_value(update_logger, Opts, false),
%% NB: we attempt to mimic -config here, which survives app reload,
%% hence {persistent, true}.
SetEnv = case version_tuple(?MODULE:otp_release()) of
@@ -445,15 +457,52 @@ reread_config(ConfigList) ->
fun (App, Key, Val) -> application:set_env(App, Key, Val, [{persistent, true}]) end
end,
try
+ Res =
[SetEnv(Application, Key, Val)
|| Config <- ConfigList,
{Application, Items} <- Config,
- {Key, Val} <- Items]
+ {Key, Val} <- Items],
+ case UpdateLoggerConfig of
+ true -> reread_logger_config();
+ false -> ok
+ end,
+ Res
catch _:_ ->
?ERROR("The configuration file submitted could not be read "
"and will be ignored.", [])
end.
+%% @private since the kernel app is already booted, re-reading its config
+%% requires doing some magic to dynamically patch running handlers to
+%% deal with the current value.
+reread_logger_config() ->
+ KernelCfg = application:get_all_env(kernel),
+ LogCfg = proplists:get_value(logger, KernelCfg),
+ case LogCfg of
+ undefined ->
+ ok;
+ _ ->
+ %% Extract and apply settings related to primary configuration
+ %% -- primary config is used for settings shared across handlers
+ LogLvlPrimary = proplists:get_value(logger_info, KernelCfg, all),
+ {FilterDefault, Filters} =
+ case lists:keyfind(filters, 1, KernelCfg) of
+ false -> {log, []};
+ {filters, FoundDef, FoundFilter} -> {FoundDef, FoundFilter}
+ end,
+ Primary = #{level => LogLvlPrimary,
+ filter_default => FilterDefault,
+ filters => Filters},
+ %% Load the correct handlers based on their individual config.
+ [case Id of
+ default -> logger:update_handler_config(Id, Cfg);
+ _ -> logger:add_handler(Id, Mod, Cfg)
+ end || {handler, Id, Mod, Cfg} <- LogCfg],
+ logger:set_primary_config(Primary),
+ ok
+ end.
+
+
%% @doc Given env. variable `FOO' we want to expand all references to
%% it in `InStr'. References can have two forms: `$FOO' and `${FOO}'
%% The end of form `$FOO' is delimited with whitespace or EOL