From 48cb63e5ba6ca42c180e6471f393254acfe322ec Mon Sep 17 00:00:00 2001
From: Siri Hansen <siri@erlang.org>
Date: Thu, 10 Jan 2019 16:33:04 +0100
Subject: [logger] Store proxy config in logger ets table

This is to ensure that logger_proxy gets the same config after a
restart.
---
 lib/kernel/src/logger.erl                | 14 +++++---------
 lib/kernel/src/logger_config.erl         |  8 ++++++++
 lib/kernel/src/logger_internal.hrl       |  1 +
 lib/kernel/src/logger_proxy.erl          |  2 +-
 lib/kernel/src/logger_server.erl         | 26 ++++++++++++++++++++++++--
 lib/kernel/test/logger_env_var_SUITE.erl |  1 +
 lib/kernel/test/logger_proxy_SUITE.erl   | 32 +++++++++++++++++++++++++++++++-
 7 files changed, 71 insertions(+), 13 deletions(-)

diff --git a/lib/kernel/src/logger.erl b/lib/kernel/src/logger.erl
index f05e756fd0..abdd9a9ceb 100644
--- a/lib/kernel/src/logger.erl
+++ b/lib/kernel/src/logger.erl
@@ -438,11 +438,8 @@ set_handler_config(HandlerId,Config) ->
 
 -spec set_proxy_config(Config) -> ok | {error,term()} when
       Config :: olp_config().
-set_proxy_config(Config) when is_map(Config) ->
-    Defaults = logger_proxy:get_default_config(),
-    logger_olp:set_opts(logger_proxy,maps:merge(Defaults,Config));
 set_proxy_config(Config) ->
-    {error,{invalid_config,Config}}.
+    logger_server:set_config(proxy,Config).
 
 -spec update_primary_config(Config) -> ok | {error,term()} when
       Config :: primary_config().
@@ -480,10 +477,8 @@ update_handler_config(HandlerId,Config) ->
 
 -spec update_proxy_config(Config) -> ok | {error,term()} when
       Config :: olp_config().
-update_proxy_config(Config) when is_map(Config) ->
-    logger_olp:set_opts(logger_proxy,Config);
 update_proxy_config(Config) ->
-    {error,{invalid_config,Config}}.
+    logger_server:update_config(proxy,Config).
 
 -spec get_primary_config() -> Config when
       Config :: primary_config().
@@ -521,7 +516,8 @@ get_handler_ids() ->
 -spec get_proxy_config() -> Config when
       Config :: olp_config().
 get_proxy_config() ->
-    logger_olp:get_opts(logger_proxy).
+    {ok,Config} = logger_config:get(?LOGGER_TABLE,proxy),
+    Config.
 
 -spec update_formatter_config(HandlerId,FormatterConfig) ->
                                      ok | {error,term()} when
@@ -717,7 +713,7 @@ add_handlers(kernel) ->
         undefined ->
             add_handlers(kernel,Env);
         Opts ->
-            case logger_olp:set_opts(logger_proxy,Opts) of
+            case set_proxy_config(Opts) of
                 ok -> add_handlers(kernel,Env);
                 {error, Reason} -> {error,{bad_proxy_config,Reason}}
             end
diff --git a/lib/kernel/src/logger_config.erl b/lib/kernel/src/logger_config.erl
index 5e9faf332c..5024d20cfe 100644
--- a/lib/kernel/src/logger_config.erl
+++ b/lib/kernel/src/logger_config.erl
@@ -66,6 +66,8 @@ get(Tid,What) ->
     case ets:lookup(Tid,table_key(What)) of
         [{_,_,Config}] ->
             {ok,Config};
+        [{_,Config}] when What=:=proxy ->
+            {ok,Config};
         [] ->
             {error,{not_found,What}}
     end.
@@ -79,10 +81,15 @@ get(Tid,What,Level) ->
         [Data] -> {ok,Data}
     end.
 
+create(Tid,proxy,Config) ->
+    ets:insert(Tid,{table_key(proxy),Config});
 create(Tid,What,Config) ->
     LevelInt = level_to_int(maps:get(level,Config)),
     ets:insert(Tid,{table_key(What),LevelInt,Config}).
 
+set(Tid,proxy,Config) ->
+    ets:insert(Tid,{table_key(proxy),Config}),
+    ok;
 set(Tid,What,Config) ->
     LevelInt = level_to_int(maps:get(level,Config)),
     %% Should do this only if the level has actually changed. Possibly
@@ -148,5 +155,6 @@ int_to_level(?LOG_ALL) -> all.
 %%%-----------------------------------------------------------------
 %%% Internal
 
+table_key(proxy) -> ?PROXY_KEY;
 table_key(primary) -> ?PRIMARY_KEY;
 table_key(HandlerId) -> {?HANDLER_KEY,HandlerId}.
diff --git a/lib/kernel/src/logger_internal.hrl b/lib/kernel/src/logger_internal.hrl
index 318fe6b037..e53922e5d3 100644
--- a/lib/kernel/src/logger_internal.hrl
+++ b/lib/kernel/src/logger_internal.hrl
@@ -19,6 +19,7 @@
 %%
 -include_lib("kernel/include/logger.hrl").
 -define(LOGGER_TABLE,logger).
+-define(PROXY_KEY,'$proxy_config$').
 -define(PRIMARY_KEY,'$primary_config$').
 -define(HANDLER_KEY,'$handler_config$').
 -define(LOGGER_META_KEY,'$logger_metadata$').
diff --git a/lib/kernel/src/logger_proxy.erl b/lib/kernel/src/logger_proxy.erl
index 8ac86f17e9..24b293805c 100644
--- a/lib/kernel/src/logger_proxy.erl
+++ b/lib/kernel/src/logger_proxy.erl
@@ -69,7 +69,7 @@ start_link() ->
     %%
     %% Burst limit is disabled, since this is only a proxy and we
     %% don't want to limit bursts twice (here and in the handler).
-    logger_olp:start_link(?SERVER,?MODULE,[],get_default_config()).
+    logger_olp:start_link(?SERVER,?MODULE,[],logger:get_proxy_config()).
 
 %% Fun used for restarting this process after it has been killed due
 %% to overload (must set overload_kill_enable=>true in opts)
diff --git a/lib/kernel/src/logger_server.erl b/lib/kernel/src/logger_server.erl
index f123eec8dd..722246e82c 100644
--- a/lib/kernel/src/logger_server.erl
+++ b/lib/kernel/src/logger_server.erl
@@ -154,6 +154,8 @@ init([]) ->
     process_flag(trap_exit, true),
     put(?LOGGER_SERVER_TAG,true),
     Tid = logger_config:new(?LOGGER_TABLE),
+    %% Store initial proxy config. logger_proxy reads config from here at startup.
+    logger_config:create(Tid,proxy,logger_proxy:get_default_config()),
     PrimaryConfig = maps:merge(default_config(primary),
                               #{handlers=>[simple]}),
     logger_config:create(Tid,primary,PrimaryConfig),
@@ -220,6 +222,24 @@ 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({change_config,SetOrUpd,proxy,Config0},_From,#state{tid=Tid}=State) ->
+    Default =
+        case SetOrUpd of
+            set ->
+                logger_proxy:get_default_config();
+            update ->
+                {ok,OldConfig} = logger_config:get(Tid,proxy),
+                OldConfig
+        end,
+    Config = maps:merge(Default,Config0),
+    Reply =
+        case logger_olp:set_opts(logger_proxy,Config) of
+            ok ->
+                logger_config:set(Tid,proxy,Config);
+            Error ->
+                Error
+        end,
+    {reply,Reply,State};
 handle_call({change_config,SetOrUpd,primary,Config0}, _From,
             #state{tid=Tid}=State) ->
     {ok,#{handlers:=Handlers}=OldConfig} = logger_config:get(Tid,primary),
@@ -413,11 +433,13 @@ default_config(Id,Module) ->
 sanity_check(Owner,Key,Value) ->
     sanity_check_1(Owner,[{Key,Value}]).
 
-sanity_check(HandlerId,Config) when is_map(Config) ->
-    sanity_check_1(HandlerId,maps:to_list(Config));
+sanity_check(Owner,Config) when is_map(Config) ->
+    sanity_check_1(Owner,maps:to_list(Config));
 sanity_check(_,Config) ->
     {error,{invalid_config,Config}}.
 
+sanity_check_1(proxy,_Config) ->
+    ok; % Details are checked by logger_olp:set_opts/2
 sanity_check_1(Owner,Config) when is_list(Config) ->
     try
         Type = get_type(Owner),
diff --git a/lib/kernel/test/logger_env_var_SUITE.erl b/lib/kernel/test/logger_env_var_SUITE.erl
index 1c073b4fce..9d2ad11be8 100644
--- a/lib/kernel/test/logger_env_var_SUITE.erl
+++ b/lib/kernel/test/logger_env_var_SUITE.erl
@@ -551,6 +551,7 @@ logger_proxy(Config) ->
     Expected = DefOpts#{sync_mode_qlen:=0,
                         drop_mode_qlen:=2},
     Expected = rpc:call(Node,logger_olp,get_opts,[logger_proxy]),
+    Expected = rpc:call(Node,logger,get_proxy_config,[]),
 
     ok.
 
diff --git a/lib/kernel/test/logger_proxy_SUITE.erl b/lib/kernel/test/logger_proxy_SUITE.erl
index 92a41eb255..3b952656dc 100644
--- a/lib/kernel/test/logger_proxy_SUITE.erl
+++ b/lib/kernel/test/logger_proxy_SUITE.erl
@@ -130,13 +130,15 @@ remote_emulator(cleanup,_Config) ->
 config(_Config) ->
     C1 = #{sync_mode_qlen:=SQ,
            drop_mode_qlen:=DQ} = logger:get_proxy_config(),
+    C1 = logger_olp:get_opts(logger_proxy),
 
     %% Update the existing config with these two values
     SQ1 = SQ+1,
     DQ1 = DQ+1,
     ok = logger:update_proxy_config(#{sync_mode_qlen=>SQ1,
                                       drop_mode_qlen=>DQ1}),
-    C2 = logger:get_proxy_config(),
+    C2 = logger:get_proxy_config(), % reads from ets table
+    C2 = logger_olp:get_opts(logger_proxy), % ensure consistency with process opts
     C2 = C1#{sync_mode_qlen:=SQ1,
              drop_mode_qlen:=DQ1},
 
@@ -144,16 +146,19 @@ config(_Config) ->
     SQ2 = SQ+2,
     ok = logger:update_proxy_config(#{sync_mode_qlen=>SQ2}),
     C3 = logger:get_proxy_config(),
+    C3 = logger_olp:get_opts(logger_proxy),
     C3 = C2#{sync_mode_qlen:=SQ2},
 
     %% Set the config, i.e. merge with defaults
     ok = logger:set_proxy_config(#{sync_mode_qlen=>SQ1}),
     C4 = logger:get_proxy_config(),
+    C4 = logger_olp:get_opts(logger_proxy),
     C4 = C1#{sync_mode_qlen:=SQ1},
 
     %% Reset to default
     ok = logger:set_proxy_config(#{}),
     C5 = logger:get_proxy_config(),
+    C5 = logger_olp:get_opts(logger_proxy),
     C5 = logger_proxy:get_default_config(),
 
     %% Errors
@@ -169,8 +174,12 @@ config(_Config) ->
         logger:update_proxy_config(#{sync_mode_qlen=>infinity}),
     {error,{invalid_config,[]}} = logger:update_proxy_config([]),
 
+    C5 = logger:get_proxy_config(),
+    C5 = logger_olp:get_opts(logger_proxy),
+
     ok.
 config(cleanup,_Config) ->
+    _ = logger:set_logger_proxy(logger_proxy:get_default_config()),
     ok.
 
 restart_after(Config) ->
@@ -180,6 +189,9 @@ restart_after(Config) ->
                                       overload_kill_restart_after => Restart}),
     Proxy = whereis(logger_proxy),
     Proxy = erlang:system_info(system_logger),
+    ProxyConfig = logger:get_proxy_config(),
+    ProxyConfig = logger_olp:get_opts(logger_proxy),
+
     Ref = erlang:monitor(process,Proxy),
     spawn(fun() ->
                   [logger_proxy ! {log,debug,
@@ -195,6 +207,15 @@ restart_after(Config) ->
     after 5000 ->
             ct:fail(proxy_not_terminated)
     end,
+
+    Proxy1 = whereis(logger_proxy),
+    Proxy1 = erlang:system_info(system_logger),
+    ProxyConfig = logger:get_proxy_config(),
+    ProxyConfig = logger_olp:get_opts(logger_proxy),
+
+    ok.
+restart_after(cleanup,Config) ->
+    _ = logger:set_logger_proxy(logger_proxy:get_default_config()),
     ok.
 
 %% Test that system_logger flag is set to logger process if
@@ -203,6 +224,9 @@ terminate(Config) ->
     Logger = whereis(logger),
     Proxy = whereis(logger_proxy),
     Proxy = erlang:system_info(system_logger),
+    ProxyConfig = logger:get_proxy_config(),
+    ProxyConfig = logger_olp:get_opts(logger_proxy),
+
     Ref = erlang:monitor(process,Proxy),
     ok = logger_olp:stop(Proxy),
     receive
@@ -213,6 +237,12 @@ terminate(Config) ->
     after 5000 ->
             ct:fail(proxy_not_terminated)
     end,
+
+    Proxy1 = whereis(logger_proxy),
+    Proxy1 = erlang:system_info(system_logger),
+    ProxyConfig = logger:get_proxy_config(),
+    ProxyConfig = logger_olp:get_opts(logger_proxy),
+
     ok.
 
 %%%-----------------------------------------------------------------
-- 
cgit v1.2.3