From 761642eddb74b767cc334c1ef1aa2c3d64435caa Mon Sep 17 00:00:00 2001 From: Andrew Thompson Date: Fri, 24 Jun 2011 16:52:33 -0400 Subject: [PATCH] Add ability to adjust loglevel per handler at runtime --- src/lager.erl | 34 ++++++++++++++++++++++++++++++-- src/lager_console_backend.erl | 8 +++++--- src/lager_file_backend.erl | 17 +++++++++++++++- src/lager_transform.erl | 6 ++---- src/lager_util.erl | 37 +++++++++++++++++------------------ 5 files changed, 73 insertions(+), 29 deletions(-) diff --git a/src/lager.erl b/src/lager.erl index b434612..dfed77f 100644 --- a/src/lager.erl +++ b/src/lager.erl @@ -18,8 +18,10 @@ -behaviour(gen_server). --export([start_link/0,start/0,sasl_log/3, log/7, log/8]). +%% API +-export([start_link/0,start/0,sasl_log/3, log/7, log/8, get_loglevel/1, set_loglevel/2, set_loglevel/3]). +%% callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). @@ -70,6 +72,19 @@ log(Level, Module, Function, Line, Pid, {{Y, M, D}, {H, Mi, S}}, Format, Args) - Function, Line, io_lib:format(Format, Args)]), gen_event:notify(lager_event, {log, lager_util:level_to_num(Level), Time, Msg}). +set_loglevel(Handler, Level) when is_atom(Level) -> + gen_server:call(?MODULE, {set_loglevel, Handler, Level}). + +set_loglevel(Handler, Ident, Level) when is_atom(Level) -> + gen_server:call(?MODULE, {set_loglevel, Handler, Ident, Level}). + +get_loglevel(Handler) -> + case gen_server:call(?MODULE, {get_loglevel, Handler}) of + X when is_integer(X) -> + lager_util:num_to_level(X); + Y -> Y + end. + %% gen_server callbacks init([Handlers]) -> @@ -81,6 +96,21 @@ init([Handlers]) -> lager_mochiglobal:put(loglevel, MinLog), {ok, #state{}}. +handle_call({set_loglevel, Handler, Level}, _From, State) -> + Reply = gen_event:call(lager_event, Handler, {set_loglevel, Level}), + %% recalculate min log level + MinLog = minimum_log_level(get_log_levels()), + lager_mochiglobal:put(loglevel, MinLog), + {reply, Reply, State}; +handle_call({set_loglevel, Handler, Ident, Level}, _From, State) -> + Reply = gen_event:call(lager_event, Handler, {set_loglevel, Ident, Level}), + %% recalculate min log level + MinLog = minimum_log_level(get_log_levels()), + lager_mochiglobal:put(loglevel, MinLog), + {reply, Reply, State}; +handle_call({get_loglevel, Handler}, _From, State) -> + Reply = gen_event:call(lager_event, Handler, get_loglevel), + {reply, Reply, State}; handle_call(_Request, _From, State) -> {reply, ok, State}. @@ -108,4 +138,4 @@ get_log_levels() -> minimum_log_level([]) -> 9; %% higher than any log level, logging off minimum_log_level(Levels) -> - erlang:hd(lists:sort(lists:map(fun(Level) -> lager_util:level_to_num(Level) end, Levels))). + erlang:hd(lists:sort(Levels)). diff --git a/src/lager_console_backend.erl b/src/lager_console_backend.erl index 46a8e07..637451b 100644 --- a/src/lager_console_backend.erl +++ b/src/lager_console_backend.erl @@ -21,17 +21,19 @@ -export([init/1, handle_call/2, handle_event/2, handle_info/2, terminate/2, code_change/3]). --record(state, {level, nlevel}). +-record(state, {level}). init([Level]) -> - {ok, #state{level=Level, nlevel=lager_util:level_to_num(Level)}}. + {ok, #state{level=lager_util:level_to_num(Level)}}. handle_call(get_loglevel, #state{level=Level} = State) -> {ok, Level, State}; +handle_call({set_loglevel, Level}, State) -> + {ok, ok, State#state{level=lager_util:level_to_num(Level)}}; handle_call(_Request, State) -> {ok, ok, State}. -handle_event({log, Level, Time, Message}, #state{nlevel=LogLevel} = State) when Level >= LogLevel -> +handle_event({log, Level, Time, Message}, #state{level=LogLevel} = State) when Level >= LogLevel -> io:put_chars([Time, " ", Message, "\n"]), {ok, State}; handle_event(_Event, State) -> diff --git a/src/lager_file_backend.erl b/src/lager_file_backend.erl index e1e0c51..fc1163e 100644 --- a/src/lager_file_backend.erl +++ b/src/lager_file_backend.erl @@ -45,6 +45,22 @@ init(LogFiles) -> {Name, Level} <- LogFiles], {ok, #state{files=Files}}. +handle_call({set_loglevel, _}, State) -> + {ok, {error, missing_identifier}, State}; +handle_call({set_loglevel, Ident, Level}, #state{files=Files} = State) -> + case lists:keyfind(Ident, 1, Files) of + false -> + %% no such file exists + {ok, {error, bad_identifier}, State}; + _ -> + NewFiles = lists:map( + fun({Name, _, FD, Inode}) when Name == Ident -> + lager:notice("Changed loglevel of ~s to ~p", [Ident, Level]), + {Ident, lager_util:level_to_num(Level), FD, Inode}; + (X) -> X + end, Files), + {ok, ok, State#state{files=NewFiles}} + end; handle_call(get_loglevel, #state{files=Files} = State) -> Result = lists:foldl(fun({_, Level, _, _}, L) -> erlang:min(Level, L); (_, L) -> L end, 9, @@ -68,7 +84,6 @@ handle_info(_Info, State) -> {ok, State}. terminate(_Reason, State) -> - io:format("lager file handler exiting~n"), %% flush and close any file handles lists:foreach( fun({_, _, FD, _}) -> file:datasync(FD), file:close(FD); diff --git a/src/lager_transform.erl b/src/lager_transform.erl index ff74485..48c0c34 100644 --- a/src/lager_transform.erl +++ b/src/lager_transform.erl @@ -63,10 +63,8 @@ transform_statement({call, Line, {remote, Line1, {atom, Line2, lager}, {'case',Line, {op,Line,'=<', {call,Line, - {remote,Line,{atom,Line,lager_util},{atom,Line,level_to_num}}, - [{call,Line, - {remote,Line,{atom,Line,lager_mochiglobal},{atom,Line,get}}, - [{atom,Line,loglevel}]}]}, + {remote,Line,{atom,Line,lager_mochiglobal},{atom,Line,get}}, + [{atom,Line,loglevel},{integer,Line,0}]}, {call,Line, {remote,Line,{atom,Line,lager_util},{atom,Line,level_to_num}}, [{atom,Line,Severity}]}}, diff --git a/src/lager_util.erl b/src/lager_util.erl index 7460ba2..53a6c06 100644 --- a/src/lager_util.erl +++ b/src/lager_util.erl @@ -16,26 +16,25 @@ -module(lager_util). --export([levels/0, level_to_num/1]). +-export([levels/0, level_to_num/1, num_to_level/1]). levels() -> [debug, info, notice, warning, error, critical, alert, emergency]. -level_to_num(debug) -> - 0; -level_to_num(info) -> - 1; -level_to_num(notice) -> - 2; -level_to_num(warning) -> - 3; -level_to_num(error) -> - 4; -level_to_num(critical) -> - 5; -level_to_num(alert) -> - 6; -level_to_num(emergency) -> - 7; -level_to_num(_) -> - 0. +level_to_num(debug) -> 0; +level_to_num(info) -> 1; +level_to_num(notice) -> 2; +level_to_num(warning) -> 3; +level_to_num(error) -> 4; +level_to_num(critical) -> 5; +level_to_num(alert) -> 6; +level_to_num(emergency) -> 7. + +num_to_level(0) -> debug; +num_to_level(1) -> info; +num_to_level(2) -> notice; +num_to_level(3) -> warning; +num_to_level(4) -> error; +num_to_level(5) -> critical; +num_to_level(6) -> alert; +num_to_level(7) -> emergency.