aboutsummaryrefslogblamecommitdiffstats
path: root/lib/kernel/test/logger_proxy_SUITE.erl
blob: 777531e4ed3fb12e91372b6301aafb8996223c16 (plain) (tree)










































































                                                                           


                   








                                                                                  
                                                



                                                            
                                                




































                                                                                                    

                                                           
                                           





                                                            

                                                                                  






                                                            
                                           




                                                         
                                           




                                      
                                           














                                                                 


                                           
       
                          
                                                                   

       
                         





                                                                               


                                                    




                                                               
                                                                  








                                                          






                                                    
                                 
                                                                   



                                                            
                     


                                              


                                                    









                                                       





                                                    

       


                                                                    






                                 
               


              








                                                                         
                                                                         


                                                                  
%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%%     http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%
%% %CopyrightEnd%
%%
-module(logger_proxy_SUITE).

-compile(export_all).

%% -include_lib("common_test/include/ct.hrl").
%% -include_lib("kernel/include/logger.hrl").
%% -include_lib("kernel/src/logger_internal.hrl").

%% -define(str,"Log from "++atom_to_list(?FUNCTION_NAME)++
%%             ":"++integer_to_list(?LINE)).
%% -define(map_rep,#{function=>?FUNCTION_NAME, line=>?LINE}).
%% -define(keyval_rep,[{function,?FUNCTION_NAME}, {line,?LINE}]).

%% -define(MY_LOC(N),#{mfa=>{?MODULE,?FUNCTION_NAME,?FUNCTION_ARITY},
%%                     file=>?FILE, line=>?LINE-N}).

%% -define(TRY(X), my_try(fun() -> X end)).


-define(HNAME,list_to_atom(lists:concat([?MODULE,"_",?FUNCTION_NAME]))).
-define(LOC,#{mfa=>{?MODULE,?FUNCTION_NAME,?FUNCTION_ARITY},line=>?LINE}).
-define(ENSURE_TIME,5000).

suite() ->
    [{timetrap,{seconds,30}},
     {ct_hooks,[logger_test_lib]}].

init_per_suite(Config) ->
    Config.

end_per_suite(_Config) ->
    ok.

init_per_group(_Group, Config) ->
    Config.

end_per_group(_Group, _Config) ->
    ok.

init_per_testcase(_TestCase, Config) ->
    Config.

end_per_testcase(Case, Config) ->
    try apply(?MODULE,Case,[cleanup,Config])
    catch error:undef -> ok
    end,
    ok.

groups() ->
    [].

all() -> 
    [basic,
     emulator,
     remote,
     remote_emulator,
     config,
     restart_after,
     terminate].

%%%-----------------------------------------------------------------
%%% Test cases
basic(_Config) ->
    ok = logger:add_handler(?HNAME,?MODULE,#{config=>self()}),
    logger_proxy ! {log,notice,"Log from: ~p; ~p",[?FUNCTION_NAME,?LINE],L1=?LOC},
    ok = ensure(L1),
    logger_proxy ! {log,notice,[{test_case,?FUNCTION_NAME},{line,?LINE}],L2=?LOC},
    ok = ensure(L2),
    logger_proxy:log({remote,node(),{log,notice,
                                     "Log from: ~p; ~p",
                                     [?FUNCTION_NAME,?LINE],
                                     L3=?LOC}}),
    ok = ensure(L3),
    logger_proxy:log({remote,node(),{log,notice,
                                     [{test_case,?FUNCTION_NAME},
                                      {line,?LINE}],
                                     L4=?LOC}}),
    ok = ensure(L4),
    ok.
basic(cleanup,_Config) ->
    ok = logger:remove_handler(?HNAME).

emulator(_Config) ->
    ok = logger:add_handler(?HNAME,?MODULE,#{config=>self()}),
    Pid = spawn(fun() -> erlang:error(some_reason) end),
    ok = ensure(#{pid=>Pid}),
    ok.
emulator(cleanup,_Config) ->
    ok = logger:remove_handler(?HNAME).

remote(Config) ->
    {ok,_,Node} = logger_test_lib:setup(Config,[{logger,[{proxy,#{}}]}]),
    ok = logger:add_handler(?HNAME,?MODULE,#{config=>self()}),
    L1 = ?LOC, spawn(Node,fun() -> logger:notice("Log from ~p; ~p",[?FUNCTION_NAME,?LINE],L1) end),
    ok = ensure(L1),
    L2 = ?LOC, spawn(Node,fun() -> logger:notice([{test_case,?FUNCTION_NAME},{line,?LINE}],L2) end),
    ok = ensure(L2),
    ok.
remote(cleanup,_Config) ->
    ok = logger:remove_handler(?HNAME).

remote_emulator(Config) ->
    {ok,_,Node} = logger_test_lib:setup(Config,[{logger,[{proxy,#{}}]}]),
    ok = logger:add_handler(?HNAME,?MODULE,#{config=>self()}),
    Pid = spawn(Node,fun() -> erlang:error(some_reason) end),
    ok = ensure(#{pid=>Pid}),
    ok.
remote_emulator(cleanup,_Config) ->
    ok = logger:remove_handler(?HNAME).

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(), % 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},

    %% Update the existing again with only one value
    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
    {error,{invalid_olp_config,_}} =
        logger:set_proxy_config(#{faulty_key=>1}),
    {error,{invalid_olp_config,_}} =
        logger:set_proxy_config(#{sync_mode_qlen=>infinity}),
    {error,{invalid_config,[]}} = logger:set_proxy_config([]),

    {error,{invalid_olp_config,_}} =
        logger:update_proxy_config(#{faulty_key=>1}),
    {error,{invalid_olp_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) ->
    Restart = 3000,
    ok = logger:update_proxy_config(#{overload_kill_enable => true,
                                      overload_kill_qlen => 10,
                                      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,
                                   [{test_case,?FUNCTION_NAME},
                                    {line,?LINE}],
                                   ?LOC} || _ <- lists:seq(1,100)]
          end),
    receive
        {'DOWN',Ref,_,_,_Reason} ->
            undefined = erlang:system_info(system_logger),
            timer:sleep(Restart),
            poll_restarted(10)
    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
%% logger_proxy terminates for other reason than overloaded.
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
        {'DOWN',Ref,_,_,_Reason} ->
            Logger = erlang:system_info(system_logger),
            logger_proxy:restart(),
            poll_restarted(10)
    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.

%%%-----------------------------------------------------------------
%%% Internal functions

poll_restarted(0) ->
    ct:fail(proxy_not_restarted);
poll_restarted(N) ->
    timer:sleep(1000),
    case whereis(logger_proxy) of
        undefined ->
            poll_restarted(N-1);
        _Pid ->
            ok
    end.

%% Logger handler callback
log(#{meta:=Meta},#{config:=Pid}) ->
    Pid ! {logged,Meta}.

%% Check that the log from the logger callback function log/2 is received
ensure(Match) ->
    receive {logged,Meta} ->
            case maps:with(maps:keys(Match),Meta) of
                Match -> ok;
                _NoMatch -> {error,Match,Meta,test_server:messages_get()}
            end
    after ?ENSURE_TIME -> {error,Match,test_server:messages_get()}
    end.