aboutsummaryrefslogtreecommitdiff
path: root/src/ejabberd_logger.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/ejabberd_logger.erl')
-rw-r--r--src/ejabberd_logger.erl275
1 files changed, 99 insertions, 176 deletions
diff --git a/src/ejabberd_logger.erl b/src/ejabberd_logger.erl
index fa4151283..c1abd19b7 100644
--- a/src/ejabberd_logger.erl
+++ b/src/ejabberd_logger.erl
@@ -23,34 +23,30 @@
%%%-------------------------------------------------------------------
-module(ejabberd_logger).
+-compile({no_auto_import, [get/0]}).
+
+-include_lib("kernel/include/logger.hrl").
%% API
--export([start/0, restart/0, reopen_log/0, rotate_log/0, get/0, set/1,
- get_log_path/0]).
+-export([start/0, get/0, set/1, get_log_path/0, flush/0]).
+-export([convert_loglevel/1, loglevels/0]).
+%% Deprecated functions
+-export([restart/0, reopen_log/0, rotate_log/0]).
+-deprecated([{restart, 0},
+ {reopen_log, 0},
+ {rotate_log, 0}]).
+-type loglevel() :: none | logger:level().
--type loglevel() :: 0 | 1 | 2 | 3 | 4 | 5.
--type lager_level() :: none | emergency | alert | critical |
- error | warning | notice | info | debug.
-
--spec start() -> ok.
--spec get_log_path() -> string().
--spec reopen_log() -> ok.
--spec rotate_log() -> ok.
--spec get() -> {loglevel(), atom(), string()}.
--spec set(loglevel()) -> ok.
+-define(is_loglevel(L),
+ ((L == none) or (L == emergency) or (L == alert)
+ or (L == critical) or (L == error) or (L == warning)
+ or (L == notice) or (L == info) or (L == debug))).
%%%===================================================================
%%% API
%%%===================================================================
-%% @doc Returns the full path to the ejabberd log file.
-%% It first checks for application configuration parameter 'log_path'.
-%% If not defined it checks the environment variable EJABBERD_LOG_PATH.
-%% And if that one is neither defined, returns the default value:
-%% "ejabberd.log" in current directory.
-%% Note: If the directory where to place the ejabberd log file to not exist,
-%% it is not created and no log file will be generated.
-%% @spec () -> string()
+-spec get_log_path() -> string().
get_log_path() ->
case ejabberd_config:env_binary_to_list(ejabberd, log_path) of
{ok, Path} ->
@@ -64,186 +60,113 @@ get_log_path() ->
end
end.
+-spec get_integer_env(atom(), T) -> T.
get_integer_env(Name, Default) ->
case application:get_env(ejabberd, Name) of
- {ok, I} when is_integer(I), I>=0 ->
+ {ok, I} when is_integer(I), I>0 ->
I;
undefined ->
Default;
{ok, Junk} ->
- error_logger:error_msg("wrong value for ~ts: ~p; "
- "using ~p as a fallback~n",
- [Name, Junk, Default]),
- Default
- end.
-get_string_env(Name, Default) ->
- case application:get_env(ejabberd, Name) of
- {ok, L} when is_list(L) ->
- L;
- undefined ->
- Default;
- {ok, Junk} ->
- error_logger:error_msg("wrong value for ~ts: ~p; "
- "using ~p as a fallback~n",
- [Name, Junk, Default]),
+ ?LOG_ERROR("Wrong value for ~ts: ~p; "
+ "using ~p as a fallback",
+ [Name, Junk, Default]),
Default
end.
-%% @spec () -> ok
+-spec loglevels() -> [loglevel(), ...].
+loglevels() ->
+ [none, emergency, alert, critical, error, warning, notice, info, debug].
+
+-spec convert_loglevel(0..5) -> loglevel().
+convert_loglevel(0) -> none;
+convert_loglevel(1) -> critical;
+convert_loglevel(2) -> error;
+convert_loglevel(3) -> warning;
+convert_loglevel(4) -> info;
+convert_loglevel(5) -> debug.
+
+-spec start() -> ok.
start() ->
- start(4).
+ start(info).
-spec start(loglevel()) -> ok.
start(Level) ->
- LLevel = get_lager_loglevel(Level),
- StartedApps = application:which_applications(5000),
- case lists:keyfind(logger, 1, StartedApps) of
- %% Elixir logger is started. We assume everything is in place
- %% to use lager to Elixir logger bridge.
- {logger, _, _} ->
- error_logger:info_msg("Ignoring ejabberd logger options, using Elixir Logger.", []),
- %% Do not start lager, we rely on Elixir Logger
- do_start_for_logger(LLevel);
- _ ->
- do_start(LLevel)
- end.
-
-do_start_for_logger(Level) ->
- application:load(sasl),
- application:set_env(sasl, sasl_error_logger, false),
- application:load(lager),
- application:set_env(lager, error_logger_redirect, false),
- application:set_env(lager, error_logger_whitelist, ['Elixir.Logger.ErrorHandler']),
- application:set_env(lager, crash_log, false),
- application:set_env(lager, handlers, [{elixir_logger_backend, [{level, Level}]}]),
- ejabberd:start_app(lager),
- ok.
-
--spec do_start(atom()) -> ok.
-do_start(Level) ->
- application:load(sasl),
- application:set_env(sasl, sasl_error_logger, false),
- application:load(lager),
- ConsoleLog = get_log_path(),
- Dir = filename:dirname(ConsoleLog),
+ EjabberdLog = get_log_path(),
+ Dir = filename:dirname(EjabberdLog),
ErrorLog = filename:join([Dir, "error.log"]),
- CrashLog = filename:join([Dir, "crash.log"]),
- LogRotateDate = get_string_env(log_rotate_date, ""),
LogRotateSize = get_integer_env(log_rotate_size, 10*1024*1024),
LogRotateCount = get_integer_env(log_rotate_count, 1),
- LogRateLimit = get_integer_env(log_rate_limit, 100),
- ConsoleLevel = case get_lager_version() >= "3.6.0" of
- true -> [{level, Level}];
- false -> Level
- end,
- application:set_env(lager, error_logger_hwm, LogRateLimit),
- application:set_env(
- lager, handlers,
- [{lager_console_backend, ConsoleLevel},
- {lager_file_backend, [{file, ConsoleLog}, {level, Level}, {date, LogRotateDate},
- {count, LogRotateCount}, {size, LogRotateSize}]},
- {lager_file_backend, [{file, ErrorLog}, {level, error}, {date, LogRotateDate},
- {count, LogRotateCount}, {size, LogRotateSize}]}]),
- application:set_env(lager, crash_log, CrashLog),
- application:set_env(lager, crash_log_date, LogRotateDate),
- application:set_env(lager, crash_log_size, LogRotateSize),
- application:set_env(lager, crash_log_count, LogRotateCount),
- ejabberd:start_app(lager),
- lists:foreach(fun(Handler) ->
- lager:set_loghwm(Handler, LogRateLimit)
- end, gen_event:which_handlers(lager_event)).
+ Config = #{max_no_bytes => LogRotateSize,
+ max_no_files => LogRotateCount,
+ filesync_repeat_interval => no_repeat,
+ sync_mode_qlen => 1000,
+ drop_mode_qlen => 1000,
+ flush_qlen => 5000},
+ FmtConfig = #{legacy_header => false,
+ time_designator => $ ,
+ max_size => 100*1024,
+ single_line => false},
+ FileFmtConfig = FmtConfig#{template => file_template()},
+ ConsoleFmtConfig = FmtConfig#{template => console_template()},
+ logger:set_primary_config(level, Level),
+ logger:add_primary_filter(progress_report,
+ {fun logger_filters:progress/2, stop}),
+ logger:update_formatter_config(default, ConsoleFmtConfig),
+ logger:add_handler(ejabberd_log, logger_std_h,
+ #{level => all,
+ config => Config#{file => EjabberdLog},
+ formatter => {logger_formatter, FileFmtConfig}}),
+ logger:add_handler(error_log, logger_std_h,
+ #{level => error,
+ config => Config#{file => ErrorLog},
+ formatter => {logger_formatter, FileFmtConfig}}),
+ ok.
restart() ->
- Level = ejabberd_option:loglevel(),
- application:stop(lager),
- start(Level).
+ ok.
+
+console_template() ->
+ [time, " [", level, "] ", msg, io_lib:nl()].
+
+file_template() ->
+ [time, " [", level, "] ", pid,
+ {mfa, ["@", mfa, {line, [":", line], []}], []}, " ", msg, io_lib:nl()].
-%% @spec () -> ok
reopen_log() ->
- %% Lager detects external log rotation automatically.
ok.
-%% @spec () -> ok
rotate_log() ->
- catch lager_crash_log ! rotate,
- lists:foreach(
- fun({lager_file_backend, File}) ->
- whereis(lager_event) ! {rotate, File};
- (_) ->
- ok
- end, gen_event:which_handlers(lager_event)).
+ ok.
-%% @spec () -> {loglevel(), atom(), string()}
+-spec get() -> loglevel().
get() ->
- case get_lager_loglevel() of
- none -> {0, no_log, "No log"};
- emergency -> {1, critical, "Critical"};
- alert -> {1, critical, "Critical"};
- critical -> {1, critical, "Critical"};
- error -> {2, error, "Error"};
- warning -> {3, warning, "Warning"};
- notice -> {3, warning, "Warning"};
- info -> {4, info, "Info"};
- debug -> {5, debug, "Debug"}
- end.
-
-set(LogLevel) when is_integer(LogLevel) ->
- LagerLogLevel = get_lager_loglevel(LogLevel),
- case get_lager_loglevel() of
- LagerLogLevel ->
- ok;
- _ ->
- ConsoleLog = get_log_path(),
- lists:foreach(
- fun({lager_file_backend, File} = H) when File == ConsoleLog ->
- lager:set_loglevel(H, LagerLogLevel);
- (lager_console_backend = H) ->
- lager:set_loglevel(H, LagerLogLevel);
- (elixir_logger_backend = H) ->
- lager:set_loglevel(H, LagerLogLevel);
- (_) ->
- ok
- end, get_lager_handlers())
- end,
- case LogLevel of
- 5 -> xmpp:set_config([{debug, true}]);
- _ -> xmpp:set_config([{debug, false}])
- end.
-
-get_lager_loglevel() ->
- Handlers = get_lager_handlers(),
- lists:foldl(fun(lager_console_backend, _Acc) ->
- lager:get_loglevel(lager_console_backend);
- (elixir_logger_backend, _Acc) ->
- lager:get_loglevel(elixir_logger_backend);
- (_, Acc) ->
- Acc
- end,
- none, Handlers).
-
--spec get_lager_loglevel(loglevel()) -> lager_level().
-get_lager_loglevel(LogLevel) ->
- case LogLevel of
- 0 -> none;
- 1 -> critical;
- 2 -> error;
- 3 -> warning;
- 4 -> info;
- 5 -> debug
- end.
-
-get_lager_handlers() ->
- case catch gen_event:which_handlers(lager_event) of
- {'EXIT',noproc} ->
- [];
- Result ->
- Result
+ #{level := Level} = logger:get_primary_config(),
+ Level.
+
+-spec set(0..5 | loglevel()) -> ok.
+set(N) when is_integer(N), N>=0, N=<5 ->
+ set(convert_loglevel(N));
+set(Level) when ?is_loglevel(Level) ->
+ case get() of
+ Level -> ok;
+ PrevLevel ->
+ ?LOG_NOTICE("Changing loglevel from '~s' to '~s'",
+ [PrevLevel, Level]),
+ logger:set_primary_config(level, Level),
+ case Level of
+ debug -> xmpp:set_config([{debug, true}]);
+ _ -> xmpp:set_config([{debug, false}])
+ end
end.
--spec get_lager_version() -> string().
-get_lager_version() ->
- Apps = application:loaded_applications(),
- case lists:keyfind(lager, 1, Apps) of
- {_, _, Vsn} -> Vsn;
- false -> "0.0.0"
- end.
+-spec flush() -> ok.
+flush() ->
+ lists:foreach(
+ fun(#{id := HandlerId, module := logger_std_h}) ->
+ logger_std_h:filesync(HandlerId);
+ (#{id := HandlerId, module := logger_disk_log_h}) ->
+ logger_disk_log_h:filesync(HandlerId);
+ (_) ->
+ ok
+ end, logger:get_handler_config()).