From 1b8acdb05bfda6b435e85200afa0f56ee2a9300e Mon Sep 17 00:00:00 2001 From: Joe DeVivo Date: Tue, 22 Jul 2014 13:53:38 -0700 Subject: [PATCH 1/4] lager_backend for use with common_test --- src/lager_common_test_backend.erl | 133 ++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 src/lager_common_test_backend.erl diff --git a/src/lager_common_test_backend.erl b/src/lager_common_test_backend.erl new file mode 100644 index 0000000..156eef3 --- /dev/null +++ b/src/lager_common_test_backend.erl @@ -0,0 +1,133 @@ +-module(lager_common_test_backend). + +-behavior(gen_event). + +%% gen_event callbacks +-export([init/1, + handle_call/2, + handle_event/2, + handle_info/2, + terminate/2, + code_change/3]). +-export([get_logs/0, + bounce/0, + bounce/1]). + +%% holds the log messages for retreival on terminate +-record(state, {level :: {mask, integer()}, + verbose :: boolean(), + log = [] :: list()}). + +-include_lib("lager/include/lager.hrl"). + +-spec get_logs() -> [iolist()] | {error, term()}. +get_logs() -> + gen_event:call(lager_event, ?MODULE, get_logs, infinity). + +bounce() -> + bounce(error). + +bounce(Level) -> + application:stop(lager), + lager:start(), + gen_event:add_handler(lager_event, lager_common_test_backend, [error, false]), + lager:set_loglevel(lager_common_test_backend, Level), + ok. + +-spec(init(integer()|atom()|[term()]) -> {ok, #state{}} | {error, atom()}). +%% @private +%% @doc Initializes the event handler +init(Level) when is_atom(Level) -> + case lists:member(Level, ?LEVELS) of + true -> + {ok, #state{level=lager_util:level_to_num(Level), verbose=false}}; + _ -> + {error, bad_log_level} + end; +init([Level, Verbose]) -> + case lists:member(Level, ?LEVELS) of + true -> + {ok, #state{level=lager_util:level_to_num(Level), verbose=Verbose}}; + _ -> + {error, bad_log_level} + end. + +-spec(handle_event(tuple(), #state{}) -> {ok, #state{}}). +%% @private +%% @doc handles the event, adding the log message to the gen_event's state. +%% this function attempts to handle logging events in both the simple tuple +%% and new record (introduced after lager 1.2.1) formats. +handle_event({log, Dest, Level, {Date, Time}, [LevelStr, Location, Message]}, %% lager 1.2.1 + #state{level=L, verbose=Verbose, log = Logs} = State) when Level > L -> + case lists:member(lager_common_test_backend, Dest) of + true -> + Log = case Verbose of + true -> + [Date, " ", Time, " ", LevelStr, Location, Message]; + _ -> + [Time, " ", LevelStr, Message] + end, + ct:pal(Log), + {ok, State#state{log=[Log|Logs]}}; + false -> + {ok, State} + end; +handle_event({log, Level, {Date, Time}, [LevelStr, Location, Message]}, %% lager 1.2.1 + #state{level=LogLevel, verbose=Verbose, log = Logs} = State) when Level =< LogLevel -> + Log = case Verbose of + true -> + [Date, " ", Time, " ", LevelStr, Location, Message]; + _ -> + [Time, " ", LevelStr, Message] + end, + ct:pal(Log), + {ok, State#state{log=[Log|Logs]}}; +handle_event({log, {lager_msg, Dest, _Meta, Level, DateTime, _Timestamp, Message}}, + State) -> %% lager 2.0.0 + case lager_util:level_to_num(Level) of + L when L =< State#state.level -> + handle_event({log, L, DateTime, + [["[",atom_to_list(Level),"] "], " ", Message]}, + State); + L -> + handle_event({log, Dest, L, DateTime, + [["[",atom_to_list(Level),"] "], " ", Message]}, + State) + end; +handle_event(Event, State) -> + ct:pal(Event), + {ok, State#state{log = [Event|State#state.log]}}. + +-spec(handle_call(any(), #state{}) -> {ok, any(), #state{}}). +%% @private +%% @doc gets and sets loglevel. This is part of the lager backend api. +handle_call(get_loglevel, #state{level=Level} = State) -> + {ok, Level, State}; +handle_call({set_loglevel, Level}, State) -> + case lists:member(Level, ?LEVELS) of + true -> + {ok, ok, State#state{level=lager_util:level_to_num(Level)}}; + _ -> + {ok, {error, bad_log_level}, State} + end; +handle_call(get_logs, #state{log = Logs} = State) -> + {ok, lists:reverse(Logs), State}; +handle_call(_, State) -> + {ok, ok, State}. + +-spec(handle_info(any(), #state{}) -> {ok, #state{}}). +%% @private +%% @doc gen_event callback, does nothing. +handle_info(_, State) -> + {ok, State}. + +-spec(code_change(any(), #state{}, any()) -> {ok, #state{}}). +%% @private +%% @doc gen_event callback, does nothing. +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +-spec(terminate(any(), #state{}) -> {ok, list()}). +%% @doc gen_event callback, does nothing. +terminate(_Reason, #state{log=Logs}) -> + {ok, lists:reverse(Logs)}. From d7f60e2c72b17e5fa29d6748b631f73477c869a8 Mon Sep 17 00:00:00 2001 From: Joe DeVivo Date: Tue, 22 Jul 2014 13:57:10 -0700 Subject: [PATCH 2/4] @doc for lager_common_test_backend --- src/lager_common_test_backend.erl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/lager_common_test_backend.erl b/src/lager_common_test_backend.erl index 156eef3..ccf06f0 100644 --- a/src/lager_common_test_backend.erl +++ b/src/lager_common_test_backend.erl @@ -20,6 +20,15 @@ -include_lib("lager/include/lager.hrl"). +%% @doc Before every test, just +%% lager_common_test_backend:bounce(Level) with the log level of your +%% choice. Every message will be passed along to ct:pal for your +%% viewing in the common_test reports. Also, you can call +%% lager_common_test_backend:get_logs/0 to get a list of all log +%% messages this backend has received during your test. You can then +%% search that list for expected log messages. + + -spec get_logs() -> [iolist()] | {error, term()}. get_logs() -> gen_event:call(lager_event, ?MODULE, get_logs, infinity). From 28239b887ec2f7c6166e93cee53bd7646b036b20 Mon Sep 17 00:00:00 2001 From: Joe DeVivo Date: Tue, 22 Jul 2014 14:45:37 -0700 Subject: [PATCH 3/4] Removed 1.X support --- src/lager_common_test_backend.erl | 63 +++++++++---------------------- 1 file changed, 18 insertions(+), 45 deletions(-) diff --git a/src/lager_common_test_backend.erl b/src/lager_common_test_backend.erl index ccf06f0..f8f95da 100644 --- a/src/lager_common_test_backend.erl +++ b/src/lager_common_test_backend.erl @@ -15,10 +15,12 @@ %% holds the log messages for retreival on terminate -record(state, {level :: {mask, integer()}, - verbose :: boolean(), + formatter :: atom(), + format_config :: any(), log = [] :: list()}). --include_lib("lager/include/lager.hrl"). +-include("lager.hrl"). +-define(TERSE_FORMAT,[time, " ", color, "[", severity,"] ", message]). %% @doc Before every test, just %% lager_common_test_backend:bounce(Level) with the log level of your @@ -46,63 +48,34 @@ bounce(Level) -> -spec(init(integer()|atom()|[term()]) -> {ok, #state{}} | {error, atom()}). %% @private %% @doc Initializes the event handler -init(Level) when is_atom(Level) -> +init([Level, true]) -> % for backwards compatibility + init([Level,{lager_default_formatter,[{eol, "\n"}]}]); +init([Level,false]) -> % for backwards compatibility + init([Level,{lager_default_formatter,?TERSE_FORMAT ++ ["\n"]}]); +init([Level,{Formatter,FormatterConfig}]) when is_atom(Formatter) -> case lists:member(Level, ?LEVELS) of true -> - {ok, #state{level=lager_util:level_to_num(Level), verbose=false}}; + {ok, #state{level=lager_util:config_to_mask(Level), + formatter=Formatter, + format_config=FormatterConfig}}; _ -> {error, bad_log_level} end; -init([Level, Verbose]) -> - case lists:member(Level, ?LEVELS) of - true -> - {ok, #state{level=lager_util:level_to_num(Level), verbose=Verbose}}; - _ -> - {error, bad_log_level} - end. +init(Level) -> + init([Level,{lager_default_formatter,?TERSE_FORMAT ++ ["\n"]}]). -spec(handle_event(tuple(), #state{}) -> {ok, #state{}}). %% @private -%% @doc handles the event, adding the log message to the gen_event's state. -%% this function attempts to handle logging events in both the simple tuple -%% and new record (introduced after lager 1.2.1) formats. -handle_event({log, Dest, Level, {Date, Time}, [LevelStr, Location, Message]}, %% lager 1.2.1 - #state{level=L, verbose=Verbose, log = Logs} = State) when Level > L -> - case lists:member(lager_common_test_backend, Dest) of +handle_event({log, Message}, + #state{level=L,formatter=Formatter,format_config=FormatConfig,log=Logs} = State) -> + case lager_util:is_loggable(Message,L,?MODULE) of true -> - Log = case Verbose of - true -> - [Date, " ", Time, " ", LevelStr, Location, Message]; - _ -> - [Time, " ", LevelStr, Message] - end, + Log = Formatter:format(Message,FormatConfig), ct:pal(Log), {ok, State#state{log=[Log|Logs]}}; false -> {ok, State} end; -handle_event({log, Level, {Date, Time}, [LevelStr, Location, Message]}, %% lager 1.2.1 - #state{level=LogLevel, verbose=Verbose, log = Logs} = State) when Level =< LogLevel -> - Log = case Verbose of - true -> - [Date, " ", Time, " ", LevelStr, Location, Message]; - _ -> - [Time, " ", LevelStr, Message] - end, - ct:pal(Log), - {ok, State#state{log=[Log|Logs]}}; -handle_event({log, {lager_msg, Dest, _Meta, Level, DateTime, _Timestamp, Message}}, - State) -> %% lager 2.0.0 - case lager_util:level_to_num(Level) of - L when L =< State#state.level -> - handle_event({log, L, DateTime, - [["[",atom_to_list(Level),"] "], " ", Message]}, - State); - L -> - handle_event({log, Dest, L, DateTime, - [["[",atom_to_list(Level),"] "], " ", Message]}, - State) - end; handle_event(Event, State) -> ct:pal(Event), {ok, State#state{log = [Event|State#state.log]}}. From d29d6c706209cae3e1d2d0e327263116e55845f0 Mon Sep 17 00:00:00 2001 From: Joe DeVivo Date: Tue, 22 Jul 2014 14:52:40 -0700 Subject: [PATCH 4/4] cleaned up lager_common_test_backend:bounce for log level --- src/lager_common_test_backend.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lager_common_test_backend.erl b/src/lager_common_test_backend.erl index f8f95da..9ed0dfc 100644 --- a/src/lager_common_test_backend.erl +++ b/src/lager_common_test_backend.erl @@ -41,8 +41,8 @@ bounce() -> bounce(Level) -> application:stop(lager), lager:start(), - gen_event:add_handler(lager_event, lager_common_test_backend, [error, false]), - lager:set_loglevel(lager_common_test_backend, Level), + gen_event:add_handler(lager_event, lager_common_test_backend, [Level, false]), + %lager:set_loglevel(lager_common_test_backend, Level), ok. -spec(init(integer()|atom()|[term()]) -> {ok, #state{}} | {error, atom()}).