Current section
Files
Jump to
Current section
Files
src/lager.erl
%% @copyright 2019-2022 Guilherme Andrade
%%
%% Permission is hereby granted, free of charge, to any person obtaining a
%% copy of this software and associated documentation files (the "Software"),
%% to deal in the Software without restriction, including without limitation
%% the rights to use, copy, modify, merge, publish, distribute, sublicense,
%% and/or sell copies of the Software, and to permit persons to whom the
%% Software is furnished to do so, subject to the following conditions:
%%
%% The above copyright notice and this permission notice shall be included in
%% all copies or substantial portions of the Software.
%%
%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
%% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
%% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
%% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
%% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
%% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
%% DEALINGS IN THE SOFTWARE.
-module(lager).
-include("lager.hrl").
%%-------------------------------------------------------------------
%% API Function Exports
%%-------------------------------------------------------------------
-export(
[clear_all_traces/0,
clear_trace_by_destination/1,
dispatch_log/5,
dispatch_log/7,
dispatch_log/9,
do_log/10,
do_log/9,
do_log_unsafe/10,
get_loglevel/1,
get_loglevel/2,
get_loglevels/1,
install_trace/2,
install_trace/3,
list_all_sinks/0,
log/3,
log/4,
log/5,
log_unsafe/4,
md/0,
md/1,
posix_error/1,
pr/2,
pr/3,
pr_stacktrace/1,
pr_stacktrace/2,
remove_trace/1,
rotate_all/0,
rotate_handler/1,
rotate_handler/2,
rotate_sink/1,
safe_format/3,
safe_format_chop/3,
set_loghwm/2,
set_loghwm/3,
set_loghwm/4,
set_loglevel/2,
set_loglevel/3,
set_loglevel/4,
start/0,
status/0,
stop_trace/1,
stop_trace/3,
trace/2,
trace/3,
trace_console/1,
trace_console/2,
trace_file/2,
trace_file/3,
trace_file/4,
trace_func/3,
trace_state/3,
unsafe_format/2,
update_loglevel_config/1
]).
-ignore_xref(
[clear_all_traces/0,
clear_trace_by_destination/1,
dispatch_log/5,
dispatch_log/7,
dispatch_log/9,
do_log/9,
do_log/10,
do_log_unsafe/10,
get_loglevel/1,
get_loglevel/2,
get_loglevels/1,
install_trace/2,
install_trace/3,
list_all_sinks/0,
log/3,
log/4,
log/5,
log_unsafe/4,
md/0,
md/1,
posix_error/1,
pr/2,
pr/3,
pr_stacktrace/1,
pr_stacktrace/2,
remove_trace/1,
rotate_all/0,
rotate_handler/1,
rotate_handler/2,
rotate_sink/1,
safe_format/3,
safe_format_chop/3,
set_loghwm/2,
set_loghwm/3,
set_loghwm/4,
set_loglevel/2,
set_loglevel/3,
set_loglevel/4,
start/0,
status/0,
stop_trace/1,
stop_trace/3,
trace/2,
trace/3,
trace_console/1,
trace_console/2,
trace_file/2,
trace_file/3,
trace_file/4,
trace_func/3,
trace_state/3,
unsafe_format/2,
update_loglevel_config/1
]).
%%-------------------------------------------------------------------
%% Record and Type Definitions
%%-------------------------------------------------------------------
-type log_level() :: none | logger:level().
-export_type([log_level/0]).
-type log_level_number() :: 0..7.
-export_type([log_level_number/0]).
%%-------------------------------------------------------------------
%% API Function Definitions
%%-------------------------------------------------------------------
-spec clear_all_traces() -> no_return().
%% @private
clear_all_traces() ->
error(notsup).
-spec clear_trace_by_destination(term()) -> no_return().
%% @private
clear_trace_by_destination(_Id) ->
error(notsup).
-spec dispatch_log(Severity, MetadataList, Format, Args, TruncSize) -> ok
when Severity :: log_level(),
MetadataList :: [{atom(),term()}],
Format :: string(),
Args :: list(),
TruncSize :: non_neg_integer().
%% @doc Backwards compatible with beams compiled with lager `2.x'
%% @deprecated
dispatch_log(Severity, MetadataList, Format, Args, TruncSize) ->
dispatch_log(?DEFAULT_SINK, Severity, MetadataList, Format, Args, TruncSize, safe).
-spec dispatch_log(Sink, Severity, MetadataList, Format, Args, TruncSize, Safety) -> ok | Error
when Sink :: atom(),
Severity :: log_level(),
MetadataList :: [{atom(),term()}],
Format :: string(),
Args :: list(),
TruncSize :: non_neg_integer(),
Safety :: safe | unsafe,
Error :: {error, Reason},
Reason :: {bad_sink, Sink}.
dispatch_log(Sink, Severity, MetadataList, Format, Args, TruncSize, _Safety)
when is_atom(Severity) ->
SeverityAsInt = -1,
LevelThreshold = -1,
Traces = [],
SinkPid = whereis(Sink),
do_log(Severity, MetadataList, Format, Args, TruncSize, SeverityAsInt,
LevelThreshold, Traces, Sink, SinkPid).
-spec dispatch_log(Severity, Module, Function, Line, Pid, MetadataList, Format, Args, TruncSize) -> ok
when Severity :: log_level(),
Module :: module(),
Function :: atom(),
Line :: pos_integer(),
Pid :: pid(),
MetadataList :: [{atom(),term()}],
Format :: string(),
Args :: list(),
TruncSize :: non_neg_integer().
%% @doc Backwards compatible with beams compiled with lager `1.x'
%% @deprecated
dispatch_log(Severity, _Module, _Function, _Line, _Pid, MetadataList, Format, Args, TruncSize) ->
dispatch_log(Severity, MetadataList, Format, Args, TruncSize).
-spec do_log(Severity, MetadataList, Format, Args, TruncSize, SeverityAsInt,
LevelThreshold, TraceFilters, SinkPid) -> ok
when Severity :: log_level(),
MetadataList :: [{atom(),term()}],
Format :: string(),
Args :: list(),
TruncSize :: non_neg_integer(),
SeverityAsInt :: integer(),
LevelThreshold :: integer(),
TraceFilters :: term(),
SinkPid :: pid().
%% @doc Backwards compatible with beams compiled with lager `2.x'
%% @private
%% @deprecated
do_log(Severity, MetadataList, Format, Args, TruncSize, SeverityAsInt, LevelThreshold, TraceFilters, SinkPid) ->
do_log(Severity, MetadataList, Format, Args, TruncSize, SeverityAsInt,
LevelThreshold, TraceFilters, ?DEFAULT_SINK, SinkPid).
-spec do_log(Severity, MetadataList, Format, Args, TruncSize, SeverityAsInt,
LevelThreshold, TraceFilters, Sink, SinkPid) -> ok | Error
when Severity :: log_level(),
MetadataList :: [{atom(),term()}],
Format :: string(),
Args :: list(),
TruncSize :: non_neg_integer(),
SeverityAsInt :: integer(),
LevelThreshold :: integer(),
TraceFilters :: term(),
Sink :: atom(),
SinkPid :: pid(),
Error :: {error, Reason},
Reason :: {bad_sink, Sink}.
%% @private Should only be called externally from code generated from the parse transform
do_log(Severity, MetadataList, Format, Args,
_Size, _SeverityAsInt, _LevelThreshold, _TraceFilters,
Sink, _SinkPid)
when is_atom(Severity) ->
redirect_to_logger(Severity, MetadataList, Format, Args, Sink).
-spec do_log_unsafe(Severity, MetadataList, Format, Args, TruncSize, SeverityAsInt,
LevelThreshold, TraceFilters, Sink, SinkPid) -> ok | Error
when Severity :: log_level(),
MetadataList :: [{atom(),term()}],
Format :: string(),
Args :: list(),
TruncSize :: non_neg_integer(),
SeverityAsInt :: integer(),
LevelThreshold :: integer(),
TraceFilters :: term(),
Sink :: atom(),
SinkPid :: pid(),
Error :: {error, Reason},
Reason :: {bad_sink, Sink}.
%% @private Should only be called externally from code generated from the parse transform
%% Specifically, it would be level ++ `_unsafe' as in `info_unsafe'.
do_log_unsafe(Severity, MetadataList, Format, Args,
_Size, _SeverityAsInt, _LevelThreshold, _TraceFilters,
Sink, _SinkPid)
when is_atom(Severity) ->
redirect_to_logger(Severity, MetadataList, Format, Args, Sink).
-spec get_loglevel(term()) -> no_return().
%% @private
get_loglevel(_Handler) ->
error(notsup).
-spec get_loglevel(term(), term()) -> no_return().
%% @private
get_loglevel(_Sink, _Handler) ->
error(notsup).
-spec get_loglevels(term()) -> no_return().
%% @private
get_loglevels(_Sink) ->
error(notsup).
-spec install_trace(term(), term()) -> no_return().
%% @private
install_trace(_Pid, _Level) ->
error(notsup).
-spec install_trace(term(), term(), term()) -> no_return().
%% @private
install_trace(_Pid, _Level, _Options) ->
error(notsup).
-spec list_all_sinks() -> no_return().
%% @private
list_all_sinks() ->
error(notsup).
-spec log(Level, Process | MetadataList, Message) -> ok
when Level :: log_level(),
Process :: pid() | atom(),
MetadataList :: [{atom(),term()}],
Message :: string().
%% @doc Manually log a message into lager without using the parse transform.
log(Level, Process, Message)
when is_pid(Process); is_atom(Process) ->
dispatch_log(Level, [{pid,Process}], Message, [], ?DEFAULT_TRUNCATION);
log(Level, MetadataList, Message)
when is_list(MetadataList) ->
dispatch_log(Level, MetadataList, Message, [], ?DEFAULT_TRUNCATION).
-spec log(Level, Process | MetadataList, Message, Args) -> ok
when Level :: log_level(),
Process :: pid() | atom(),
MetadataList :: [{atom(),term()}],
Message :: string(),
Args :: list().
%% @doc Manually log a message into lager without using the parse transform.
log(Level, Process, Format, Args)
when is_pid(Process); is_atom(Process) ->
dispatch_log(Level, [{pid,Process}], Format, Args, ?DEFAULT_TRUNCATION);
log(Level, MetadataList, Format, Args)
when is_list(MetadataList) ->
dispatch_log(Level, MetadataList, Format, Args, ?DEFAULT_TRUNCATION).
-spec log(Sink, Level, Process | MetadataList, Message, Args) -> ok | Error
when Sink :: atom(),
Level :: log_level(),
Process :: pid() | atom(),
MetadataList :: [{atom(),term()}],
Message :: string(),
Args :: list(),
Error :: {error, Reason},
Reason :: {bad_sink, Sink}.
%% @doc Manually log a message into lager without using the parse transform.
log(Sink, Level, Pid, Format, Args)
when is_pid(Pid); is_atom(Pid) ->
dispatch_log(Sink, Level, [{pid,Pid}], Format, Args, ?DEFAULT_TRUNCATION, safe);
log(Sink, Level, MetadataList, Format, Args) when is_list(MetadataList) ->
dispatch_log(Sink, Level, MetadataList, Format, Args, ?DEFAULT_TRUNCATION, safe).
-spec log_unsafe(Level, MetadataList, Message, Args) -> ok
when Level :: log_level(),
MetadataList :: [{atom(),term()}],
Message :: string(),
Args :: list().
log_unsafe(Level, MetadataList, Format, Args)
when is_list(MetadataList) ->
dispatch_log(?DEFAULT_SINK, Level, MetadataList, Format, Args, ?DEFAULT_TRUNCATION, unsafe).
%% @doc Get lager metadata for current process
-spec md() -> [{atom(), any()}].
md() ->
case logger:get_process_metadata() of
undefined -> [];
Metadata ->
maps:to_list(Metadata)
end.
%% @doc Set lager metadata for current process.
%% Will badarg if you don't supply a list of {key, value} tuples keyed by atoms.
-spec md([{atom(), any()},...]) -> ok.
md(MetadataList)
when length(MetadataList) >= 0 ->
Metadata = logger_metadata(MetadataList),
logger:set_process_metadata(Metadata);
md(_) ->
error(badarg).
-spec posix_error(term()) -> no_return().
%% @private
posix_error(_Error) ->
error(notsup).
-spec pr(term(), term()) -> no_return().
%% @TODO
%% @private
pr(Record, Module) when is_tuple(Record), is_atom(element(1, Record)) ->
pr(Record, Module, []);
pr(List, Module) when is_list(List) ->
pr(List, Module, []);
pr(_Record, _) ->
error(notsup).
-spec pr(term(), term(), term()) -> no_return().
%% @TODO
%% @private
pr(Record, _Module, Options) when is_tuple(Record), is_atom(element(1, Record)), is_list(Options) ->
error(notsup);
pr([_Head|_Tail], _Module, Options) when is_list(Options) ->
error(notsup);
pr(_Record, _, _) ->
error(notsup).
-spec pr_stacktrace(term()) -> no_return().
%% @TODO
%% @private
pr_stacktrace(_Stacktrace) ->
error(notsup).
-spec pr_stacktrace(term(), {atom(),term()}) -> no_return().
%% @TODO
%% @private
pr_stacktrace(_Stacktrace, {_Class, _Reason}) ->
error(notsup).
-spec remove_trace(term()) -> no_return().
%% @private
remove_trace(_Pid) ->
error(notsup).
-spec rotate_all() -> no_return().
%% @private
rotate_all() ->
error(notsup).
-spec rotate_handler(term()) -> no_return().
%% @private
rotate_handler(_Handler) ->
error(notsup).
-spec rotate_handler(term(), term()) -> no_return().
%% @private
rotate_handler(_Handler, _Sink) ->
error(notsup).
-spec rotate_sink(term()) -> no_return().
%% @private
rotate_sink(_Sink) ->
error(notsup).
-spec safe_format(term(), term(), term()) -> no_return().
%% @private
safe_format(_Fmt, _Args, _Limit) ->
error(notsup).
-spec safe_format_chop(term(), term(), term()) -> no_return().
%% @private
safe_format_chop(_Fmt, _Args, _Limit) ->
error(notsup).
-spec set_loghwm(term(), term()) -> no_return().
%% @private
set_loghwm(_Handler, _Hwm) ->
error(notsup).
-spec set_loghwm(term(), term(), term()) -> no_return().
%% @private
set_loghwm(_Sink, _Handler, _Hwm) ->
error(notsup).
-spec set_loghwm(term(), term(), term(), term()) -> no_return().
%% @private
set_loghwm(_Sink, _Handler, _Ident, _Hwm) ->
error(notsup).
-spec set_loglevel(term(), term()) -> no_return().
%% @private
set_loglevel(_Handler, _Level) ->
error(notsup).
-spec set_loglevel(term(), term(), term()) -> no_return().
%% @private
set_loglevel(_Handler, _Ident, _Level) ->
error(notsup).
-spec set_loglevel(term(), term(), term(), term()) -> no_return().
%% @private
set_loglevel(_Sink, _Handler, _Ident, _Level) ->
error(notsup).
-spec start() -> ok | {error,{atom(),term()}}.
start() ->
case application:ensure_all_started(lager) of
{ok, _} -> ok;
{error, Reason} -> {error, Reason}
end.
-spec status() -> no_return().
%% @private
status() ->
error(notsup).
-spec stop_trace({term(),term(),term()}) -> no_return().
%% @private
stop_trace({_Backend, _Filter, _Level}) ->
error(notsup).
-spec stop_trace(term(), term(), term()) -> no_return().
%% @private
stop_trace(_Backend, _Filter, _Level) ->
error(notsup).
-spec trace(term(), term()) -> no_return().
%% @private
trace(_Backend, _Filter) ->
error(notsup).
-spec trace(term(), term(), term()) -> no_return().
%% @private
trace(_Backend, _Filter, _Level) ->
error(notsup).
-spec trace_console(term()) -> no_return().
%% @private
trace_console(_Filter) ->
error(notsup).
-spec trace_console(term(), term()) -> no_return().
%% @private
trace_console(_Filter, _Level) ->
error(notsup).
-spec trace_file(term(), term()) -> no_return().
%% @private
trace_file(_File, _Filter) ->
error(notsup).
-spec trace_file(term(), term(), term()) -> no_return().
%% @private
trace_file(_File, _Filter, _LevelOrOptions) ->
error(notsup).
-spec trace_file(term(), term(), term(), term()) -> no_return().
%% @private
trace_file(_File, _Filter, _Level, _Options) ->
error(notsup).
-spec trace_func(term(), term(), term()) -> no_return().
%% @private
trace_func(_FuncState, _Event, _ProcState) ->
error(notsup).
-spec trace_state(term(), term(), term()) -> no_return().
%% @private
trace_state(_Pid, _Level, _Options) ->
error(notsup).
-spec unsafe_format(term(), term()) -> no_return().
%% @private
unsafe_format(_Fmt, _Args) ->
error(notsup).
-spec update_loglevel_config(term()) -> no_return().
%% @private
update_loglevel_config(_Sink) ->
error(notsup).
%%-------------------------------------------------------------------
%% Internal Function Definitions
%%-------------------------------------------------------------------
logger_metadata(MetadataList) ->
lists:foldl(
fun({Key,Value}, Acc) when is_atom(Key) ->
Acc#{ Key => Value };
(_, _) ->
error(badarg)
end,
#{}, MetadataList).
redirect_to_logger(Severity, MetadataList, Format, Args, Sink) ->
% TODO other sinks?
if Severity =:= none ->
ok;
Sink =:= ?DEFAULT_SINK ->
Metadata = logger_metadata(MetadataList),
logger:log(Severity, Format, Args, Metadata);
true ->
{error, {bad_sink, Sink}}
end.