rebar3/_build/default/lib/cth_readable/src/cth_readable_lager_backend.erl

148 lines
5.1 KiB
Erlang

%% Copyright (c) 2011-2012, 2014 Basho Technologies, Inc. All Rights Reserved.
%%
%% This file is provided to you 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.
%% @doc Console backend for lager that mutes logs to the shell when
%% CT runs succeed. Configured with a single option, the loglevel
%% desired.
-module(cth_readable_lager_backend).
-behaviour(gen_event).
-export([init/1, handle_call/2, handle_event/2, handle_info/2, terminate/2,
code_change/3]).
-record(state, {level :: {'mask', integer()},
out = user :: user | standard_error,
formatter :: atom(),
format_config :: any(),
colors=[] :: list()}).
%-include("lager.hrl").
-define(TERSE_FORMAT,[time, " ", color, "[", severity,"] ", message]).
-define(DEFAULT_FORMAT_CONFIG, ?TERSE_FORMAT ++ [eol()]).
-define(FORMAT_CONFIG_OFF, [{eol, eol()}]).
%% @private
init([Level]) when is_atom(Level) ->
init([{level, Level}]);
init([Level, true]) when is_atom(Level) -> % for backwards compatibility
init([{level, Level}, {formatter_config, ?FORMAT_CONFIG_OFF}]);
init([Level, false]) when is_atom(Level) -> % for backwards compatibility
init([{level, Level}]);
init(Options) when is_list(Options) ->
Colors = case application:get_env(lager, colored) of
{ok, true} ->
{ok, LagerColors} = application:get_env(lager, colors),
LagerColors;
_ -> []
end,
Level = get_option(level, Options, undefined),
%% edited out a bunch of console detection stuff, hopefully not breaking
try lager_util:config_to_mask(Level) of
L ->
[UseErr, Formatter, Config] =
[get_option(K, Options, Default) || {K, Default} <- [{use_stderr, false},
{formatter, lager_default_formatter},
{formatter_config, ?DEFAULT_FORMAT_CONFIG}]
],
Out = case UseErr of
false -> user;
true -> standard_error
end,
{ok, #state{level=L,
out=Out,
formatter=Formatter,
format_config=Config,
colors=Colors}}
catch
_:_ ->
{error, {fatal, bad_log_level}}
end;
init(Level) ->
init([Level,{lager_default_formatter,?TERSE_FORMAT ++ [eol()]}]).
get_option(K, Options, Default) ->
case lists:keyfind(K, 1, Options) of
{K, V} -> V;
false -> Default
end.
%% @private
handle_call(get_loglevel, #state{level=Level} = State) ->
{ok, Level, State};
handle_call({set_loglevel, Level}, State) ->
try lager_util:config_to_mask(Level) of
Levels ->
{ok, ok, State#state{level=Levels}}
catch
_:_ ->
{ok, {error, bad_log_level}, State}
end;
handle_call(_Request, State) ->
{ok, ok, State}.
%% @private
handle_event({log, Message},
#state{level=L,formatter=Formatter,format_config=FormatConfig,colors=Colors} = State) ->
case lager_util:is_loggable(Message, L, lager_console_backend) of
true ->
%% Handle multiple possible functions -- older lagers didn't
%% support colors, and we depend on the currently running lib.
Formatted = case erlang:function_exported(Formatter, format, 3) of
true ->
Formatter:format(Message,FormatConfig,Colors);
false ->
Formatter:format(Message,FormatConfig)
end,
%% lagger forwards in sync mode, and a call to error_logger makes
%% everything deadlock, so we gotta go async on the logging call.
%% We also need to do a call so that lager doesn't reforward the
%% event in an infinite loop.
Name = case erlang:function_exported(logger, module_info, 0) of
true -> cth_readable_logger;
false -> error_logger
end,
spawn(fun() -> gen_event:call(Name, cth_readable_failonly, {lager, Formatted}) end),
ct_logs:tc_log(default, Formatted, []),
{ok, State};
false ->
{ok, State}
end;
handle_event(_Event, State) ->
{ok, State}.
%% @private
handle_info(_Info, State) ->
{ok, State}.
%% @private
terminate(_Reason, _State) ->
ok.
%% @private
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
eol() ->
case application:get_env(lager, colored) of
{ok, true} ->
"\e[0m\r\n";
_ ->
"\r\n"
end.