diff options
author | Mickael Remond <mremond@process-one.net> | 2016-03-09 19:12:56 +0100 |
---|---|---|
committer | Mickael Remond <mremond@process-one.net> | 2016-03-09 19:12:56 +0100 |
commit | f4ee8a25051a51b4fdd1318cb6918e05404a466b (patch) | |
tree | 03a4f77d5a9b82f376c9f83b7070dc21f41384ec /src/elixir_logger_backend.erl | |
parent | Fix escaping of argument in iexlive and iexdebug (diff) |
Add Elixir Logger Backend to bridge logs from lager
We will need to support loglevel bridging.
It should help with #966
Diffstat (limited to 'src/elixir_logger_backend.erl')
-rw-r--r-- | src/elixir_logger_backend.erl | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/src/elixir_logger_backend.erl b/src/elixir_logger_backend.erl new file mode 100644 index 00000000..6bd5b638 --- /dev/null +++ b/src/elixir_logger_backend.erl @@ -0,0 +1,115 @@ +%%%------------------------------------------------------------------- +%%% @author Mickael Remond <mremond@process-one.net> +%%% @doc +%%% This module bridges lager logs to Elixir Logger. +%%% @end +%%% Created : 9 March 2016 by Mickael Remond <mremond@process-one.net> +%%% +%%% ejabberd, Copyright (C) 2002-2016 ProcessOne +%%% +%%% This program is free software; you can redistribute it and/or +%%% modify it under the terms of the GNU General Public License as +%%% published by the Free Software Foundation; either version 2 of the +%%% License, or (at your option) any later version. +%%% +%%% This program is distributed in the hope that it will be useful, +%%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%%% General Public License for more details. +%%% +%%% You should have received a copy of the GNU General Public License along +%%% with this program; if not, write to the Free Software Foundation, Inc., +%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +%%% +%%%------------------------------------------------------------------- + +-module(elixir_logger_backend). + +-behaviour(gen_event). + +-export([init/1, handle_call/2, handle_event/2, handle_info/2, terminate/2, + code_change/3]). + +init(_Opts) -> + State = [], + {ok, State}. + +%% @private +handle_event({log, LagerMsg}, State) -> + #{mode := Mode, truncate := Truncate, level := MinLevel, utc_log := UTCLog} = 'Elixir.Logger.Config':'__data__'(), + MsgLevel = severity_to_level(lager_msg:severity(LagerMsg)), + case {lager_util:is_loggable(LagerMsg, debug, ?MODULE), 'Elixir.Logger':compare_levels(MsgLevel, MinLevel)} of + {_, lt}-> + {ok, State}; + {true, _} -> + Metadata = normalize_pid(lager_msg:metadata(LagerMsg)), + Message = 'Elixir.Logger.Utils':truncate(lager_msg:message(LagerMsg), Truncate), + Timestamp = timestamp(lager_msg:timestamp(LagerMsg), UTCLog), + GroupLeader = case proplists:get_value(pid, Metadata, self()) of + Pid when is_pid(Pid) -> + erlang:process_info(self(), group_leader); + _ -> {group_leader, self()} + end, + notify(Mode, {MsgLevel, GroupLeader, {'Elixir.Logger', Message, Timestamp, Metadata}}), + {ok, State}; + _ -> + {ok, State} + end; +handle_event(_, State) -> + {ok, State}. + +%% @private +%% TODO Handle loglevels +handle_call(_Msg, State) -> + {ok, ok, State}. + +%% @private +handle_info(_Msg, State) -> + {ok, State}. + +%% @private +terminate(_Reason, _State) -> + ok. + +%% @private +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +notify(sync, Msg) -> + gen_event:sync_notify('Elixir.Logger', Msg); +notify(async, Msg) -> gen_event:notify('Elixir.Logger', Msg). + +normalize_pid(Metadata) -> + case proplists:get_value(pid, Metadata) of + Pid when is_pid(Pid) -> Metadata; + Pid when is_list(Pid) -> + M1 = proplists:delete(pid, Metadata), + case catch erlang:list_to_pid(Pid) of + {'EXIT', _} -> + M1; + PidAsPid -> + [{pid, PidAsPid}|M1] + end; + _ -> + proplists:delete(pid, Metadata) + end. + +%% Return timestamp with milliseconds +timestamp(Time, UTCLog) -> + {_, _, Micro} = erlang:timestamp(), + {Date, {Hours, Minutes, Seconds}} = + case UTCLog of + true -> calendar:now_to_universal_time(Time); + false -> calendar:now_to_local_time(Time) + end, + {Date, {Hours, Minutes, Seconds, Micro div 1000}}. + + +severity_to_level(debug) -> debug; +severity_to_level(info) -> info; +severity_to_level(notice) -> info; +severity_to_level(warning) -> warn; +severity_to_level(error) -> error; +severity_to_level(critical) -> error; +severity_to_level(alert) -> error; +severity_to_level(emergency) -> error. |