Replace lager with built-in new logging API

This change requires Erlang/OTP-21.0 or higher.
The commit also deprecates the following options:
  - log_rotate_date
  - log_rate_limit

Furthermore, these options have no effect. The logger now fully
relies on log_rotate_size, that cannot be 0 anymore.

The loglevel option now accepts levels in literal formats.
Those are: none, emergency, alert, critical, error, warning, notice, info, debug.
Old integer values (0-5) are still supported and automatically converted
into literal format.
This commit is contained in:
Evgeny Khramtsov 2019-10-18 19:12:32 +03:00
parent b1d458999a
commit e4a8afb15d
18 changed files with 175 additions and 274 deletions

View File

@ -1,9 +1,8 @@
language: erlang language: erlang
otp_release: otp_release:
- 19.3 - 21.0
- 20.3 - 22.1
- 21.2
services: services:
- redis-server - redis-server

View File

@ -14,24 +14,24 @@ solutions very cost effectively.
Key Features Key Features
------------ ------------
- **Cross-platform** - **Cross-platform**
ejabberd runs under Microsoft Windows and Unix-derived systems such as ejabberd runs under Microsoft Windows and Unix-derived systems such as
Linux, FreeBSD and NetBSD. Linux, FreeBSD and NetBSD.
- **Distributed** - **Distributed**
You can run ejabberd on a cluster of machines and all of them will serve the You can run ejabberd on a cluster of machines and all of them will serve the
same XMPP domain(s). When you need more capacity you can simply add a new same XMPP domain(s). When you need more capacity you can simply add a new
cheap node to your cluster. Accordingly, you do not need to buy an expensive cheap node to your cluster. Accordingly, you do not need to buy an expensive
high-end machine to support tens of thousands concurrent users. high-end machine to support tens of thousands concurrent users.
- **Fault-tolerant** - **Fault-tolerant**
You can deploy an ejabberd cluster so that all the information required for You can deploy an ejabberd cluster so that all the information required for
a properly working service will be replicated permanently on all nodes. This a properly working service will be replicated permanently on all nodes. This
means that if one of the nodes crashes, the others will continue working means that if one of the nodes crashes, the others will continue working
without disruption. In addition, nodes also can be added or replaced on without disruption. In addition, nodes also can be added or replaced on
the fly. the fly.
- **Administrator-friendly** - **Administrator-friendly**
ejabberd is built on top of the Open Source Erlang. As a result you do not ejabberd is built on top of the Open Source Erlang. As a result you do not
need to install an external database, an external web server, amongst others need to install an external database, an external web server, amongst others
because everything is already included, and ready to run out of the box. because everything is already included, and ready to run out of the box.
@ -44,13 +44,13 @@ Key Features
- Can integrate with existing authentication mechanisms. - Can integrate with existing authentication mechanisms.
- Capability to send announce messages. - Capability to send announce messages.
- **Internationalized** - **Internationalized**
ejabberd leads in internationalization. Hence it is very well suited in a ejabberd leads in internationalization. Hence it is very well suited in a
globalized world. Related features are: globalized world. Related features are:
- Translated to 25 languages. - Translated to 25 languages.
- Support for IDNA. - Support for IDNA.
- **Open Standards** - **Open Standards**
ejabberd is the first Open Source Jabber server claiming to fully comply to ejabberd is the first Open Source Jabber server claiming to fully comply to
the XMPP standard. the XMPP standard.
- Fully XMPP-compliant. - Fully XMPP-compliant.
@ -107,7 +107,7 @@ To compile ejabberd you need:
- GCC. - GCC.
- Libexpat ≥ 1.95. - Libexpat ≥ 1.95.
- Libyaml ≥ 0.1.4. - Libyaml ≥ 0.1.4.
- Erlang/OTP ≥ 19.1. - Erlang/OTP ≥ 21.0.
- OpenSSL ≥ 1.0.0. - OpenSSL ≥ 1.0.0.
- Zlib ≥ 1.2.3, for Stream Compression support (XEP-0138). Optional. - Zlib ≥ 1.2.3, for Stream Compression support (XEP-0138). Optional.
- PAM library. Optional. For Pluggable Authentication Modules (PAM). - PAM library. Optional. For Pluggable Authentication Modules (PAM).

View File

@ -3,7 +3,7 @@
AC_PREREQ(2.53) AC_PREREQ(2.53)
AC_INIT(ejabberd, m4_esyscmd([echo `git describe --tags 2>/dev/null || echo 0.0` | sed 's/-g.*//;s/-/./' | tr -d '\012']), [ejabberd@process-one.net], [ejabberd]) AC_INIT(ejabberd, m4_esyscmd([echo `git describe --tags 2>/dev/null || echo 0.0` | sed 's/-g.*//;s/-/./' | tr -d '\012']), [ejabberd@process-one.net], [ejabberd])
REQUIRE_ERLANG_MIN="8.1 (Erlang/OTP 19.1)" REQUIRE_ERLANG_MIN="10.0 (Erlang/OTP 21.0)"
REQUIRE_ERLANG_MAX="100.0.0 (No Max)" REQUIRE_ERLANG_MAX="100.0.0 (No Max)"
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])

View File

@ -17,11 +17,7 @@
hosts: hosts:
- localhost - localhost
loglevel: 4 loglevel: info
log_rotate_size: 10485760
log_rotate_date: ""
log_rotate_count: 1
log_rate_limit: 100
## If you already have certificates, list them here ## If you already have certificates, list them here
# certfiles: # certfiles:

View File

@ -17,24 +17,24 @@
%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. %%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
%%% %%%
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
-include_lib("kernel/include/logger.hrl").
-define(PRINT(Format, Args), io:format(Format, Args)). -define(PRINT(Format, Args), io:format(Format, Args)).
-compile([{parse_transform, lager_transform}]).
-define(DEBUG(Format, Args), -define(DEBUG(Format, Args),
begin lager:debug(Format, Args), ok end). begin ?LOG_DEBUG(Format, Args), ok end).
-define(INFO_MSG(Format, Args), -define(INFO_MSG(Format, Args),
begin lager:info(Format, Args), ok end). begin ?LOG_INFO(Format, Args), ok end).
-define(WARNING_MSG(Format, Args), -define(WARNING_MSG(Format, Args),
begin lager:warning(Format, Args), ok end). begin ?LOG_WARNING(Format, Args), ok end).
-define(ERROR_MSG(Format, Args), -define(ERROR_MSG(Format, Args),
begin lager:error(Format, Args), ok end). begin ?LOG_ERROR(Format, Args), ok end).
-define(CRITICAL_MSG(Format, Args), -define(CRITICAL_MSG(Format, Args),
begin lager:critical(Format, Args), ok end). begin ?LOG_CRITICAL(Format, Args), ok end).
%% Use only when trying to troubleshoot test problem with ExUnit %% Use only when trying to troubleshoot test problem with ExUnit
-define(EXUNIT_LOG(Format, Args), -define(EXUNIT_LOG(Format, Args),

View File

@ -18,8 +18,7 @@
%%% %%%
%%%---------------------------------------------------------------------- %%%----------------------------------------------------------------------
{deps, [{lager, ".*", {git, "https://github.com/erlang-lager/lager", "3.6.10"}}, {deps, [{p1_utils, ".*", {git, "https://github.com/processone/p1_utils", {tag, "1.0.16"}}},
{p1_utils, ".*", {git, "https://github.com/processone/p1_utils", {tag, "1.0.16"}}},
{cache_tab, ".*", {git, "https://github.com/processone/cache_tab", {tag, "1.0.20"}}}, {cache_tab, ".*", {git, "https://github.com/processone/cache_tab", {tag, "1.0.20"}}},
{fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.1.2"}}}, {fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.1.2"}}},
{stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.17"}}}, {stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.17"}}},

View File

@ -6,7 +6,7 @@
{modules, []}, {modules, []},
{registered, []}, {registered, []},
{applications, [kernel, stdlib, sasl, ssl]}, {applications, [kernel, stdlib, sasl, ssl]},
{included_applications, [os_mon, lager, mnesia, inets, p1_utils, fast_yaml, fast_tls, pkix, xmpp, cache_tab, eimp]}, {included_applications, [os_mon, mnesia, inets, p1_utils, fast_yaml, fast_tls, pkix, xmpp, cache_tab, eimp]},
{env, [{enabled_backends, [@enabled_backends@]}]}, {env, [{enabled_backends, [@enabled_backends@]}]},
{mod, {ejabberd_app, []}}]}. {mod, {ejabberd_app, []}}]}.

View File

@ -49,8 +49,7 @@ stop() ->
application:stop(ejabberd). application:stop(ejabberd).
halt() -> halt() ->
_ = application:stop(lager), ejabberd_logger:flush(),
_ = application:stop(sasl),
erlang:halt(1, [{flush, true}]). erlang:halt(1, [{flush, true}]).
%% @spec () -> false | string() %% @spec () -> false | string()

View File

@ -142,20 +142,16 @@ get_commands_spec() ->
desc = "Get the current loglevel", desc = "Get the current loglevel",
module = ejabberd_logger, function = get, module = ejabberd_logger, function = get,
result_desc = "Tuple with the log level number, its keyword and description", result_desc = "Tuple with the log level number, its keyword and description",
result_example = {4, info, <<"Info">>}, result_example = warning,
args = [], args = [],
result = {leveltuple, {tuple, [{levelnumber, integer}, result = {levelatom, atom}},
{levelatom, atom},
{leveldesc, string}
]}}},
#ejabberd_commands{name = set_loglevel, tags = [logs, server], #ejabberd_commands{name = set_loglevel, tags = [logs, server],
desc = "Set the loglevel (0 to 5)", desc = "Set the loglevel",
module = ?MODULE, function = set_loglevel, module = ?MODULE, function = set_loglevel,
args_desc = ["Integer of the desired logging level, between 1 and 5"], args_desc = ["Desired logging level: none | emergency | alert | critical "
args_example = [5], "| error | warning | notice | info | debug"],
result_desc = "The type of logger module used", args_example = [debug],
result_example = lager, args = [{loglevel, string}],
args = [{loglevel, integer}],
result = {res, rescode}}, result = {res, rescode}},
#ejabberd_commands{name = update_list, tags = [server], #ejabberd_commands{name = update_list, tags = [server],
@ -410,15 +406,23 @@ status() ->
{Is_running, String1 ++ String2}. {Is_running, String1 ++ String2}.
reopen_log() -> reopen_log() ->
ejabberd_hooks:run(reopen_log_hook, []), ejabberd_hooks:run(reopen_log_hook, []).
ejabberd_logger:reopen_log().
rotate_log() -> rotate_log() ->
ejabberd_hooks:run(rotate_log_hook, []), ejabberd_hooks:run(rotate_log_hook, []).
ejabberd_logger:rotate_log().
set_loglevel(LogLevel) -> set_loglevel(LogLevel) ->
ejabberd_logger:set(LogLevel). try binary_to_existing_atom(iolist_to_binary(LogLevel), latin1) of
Level ->
case lists:member(Level, ejabberd_logger:loglevels()) of
true ->
ejabberd_logger:set(Level);
false ->
{error, "Invalid log level"}
end
catch _:_ ->
{error, "Invalid log level"}
end.
%%% %%%
%%% Stop Kindly %%% Stop Kindly

View File

@ -84,8 +84,6 @@ start_included_apps() ->
lists:foreach( lists:foreach(
fun(mnesia) -> fun(mnesia) ->
ok; ok;
(lager)->
ok;
(os_mon)-> (os_mon)->
ok; ok;
(App) -> (App) ->

View File

@ -522,7 +522,7 @@ read_erlang_file(File, _) ->
validate(Y1) -> validate(Y1) ->
case pre_validate(Y1) of case pre_validate(Y1) of
{ok, Y2} -> {ok, Y2} ->
set_loglevel(proplists:get_value(loglevel, Y2, 4)), set_loglevel(proplists:get_value(loglevel, Y2, info)),
case ejabberd_config_transformer:map_reduce(Y2) of case ejabberd_config_transformer:map_reduce(Y2) of
{ok, Y3} -> {ok, Y3} ->
Hosts = proplists:get_value(hosts, Y3), Hosts = proplists:get_value(hosts, Y3),
@ -763,7 +763,7 @@ set_shared_key() ->
set_node_start(UnixTime) -> set_node_start(UnixTime) ->
set_option(node_start, UnixTime). set_option(node_start, UnixTime).
-spec set_loglevel(0..5) -> ok. -spec set_loglevel(logger:level()) -> ok.
set_loglevel(Level) -> set_loglevel(Level) ->
ejabberd_logger:set(Level). ejabberd_logger:set(Level).

View File

@ -30,12 +30,6 @@ map_reduce(Y) ->
F = fun(Y1) -> F = fun(Y1) ->
Y2 = (validator())(Y1), Y2 = (validator())(Y1),
Y3 = transform(Y2), Y3 = transform(Y2),
if Y2 /= Y3 ->
?DEBUG("Transformed configuration:~ts~n",
[misc:format_val({yaml, Y3})]);
true ->
ok
end,
Y3 Y3
end, end,
econf:validate(F, Y). econf:validate(F, Y).
@ -148,6 +142,12 @@ filter(Host, Y, Acc) ->
filter(Host, Opt, Val, Acc) filter(Host, Opt, Val, Acc)
end, Y). end, Y).
filter(_Host, log_rotate_date, _, _) ->
warn_removed_option(log_rotate_date),
false;
filter(_Host, log_rate_limit, _, _) ->
warn_removed_option(log_rate_limit),
false;
filter(_Host, ca_path, _, _) -> filter(_Host, ca_path, _, _) ->
warn_removed_option(ca_path, ca_file), warn_removed_option(ca_path, ca_file),
false; false;

View File

@ -68,6 +68,7 @@
%%----------------------------- %%-----------------------------
start() -> start() ->
logger:set_primary_config(level, none),
[SNode, Timeout, Args] = case init:get_plain_arguments() of [SNode, Timeout, Args] = case init:get_plain_arguments() of
[SNode2, "--no-timeout" | Args2] -> [SNode2, "--no-timeout" | Args2] ->
[SNode2, infinity, Args2]; [SNode2, infinity, Args2];

View File

@ -23,34 +23,30 @@
%%%------------------------------------------------------------------- %%%-------------------------------------------------------------------
-module(ejabberd_logger). -module(ejabberd_logger).
-compile({no_auto_import, [get/0]}).
-include_lib("kernel/include/logger.hrl").
%% API %% API
-export([start/0, restart/0, reopen_log/0, rotate_log/0, get/0, set/1, -export([start/0, get/0, set/1, get_log_path/0, flush/0]).
get_log_path/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. -define(is_loglevel(L),
-type lager_level() :: none | emergency | alert | critical | ((L == none) or (L == emergency) or (L == alert)
error | warning | notice | info | debug. or (L == critical) or (L == error) or (L == warning)
or (L == notice) or (L == info) or (L == 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.
%%%=================================================================== %%%===================================================================
%%% API %%% API
%%%=================================================================== %%%===================================================================
%% @doc Returns the full path to the ejabberd log file. -spec get_log_path() -> string().
%% 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()
get_log_path() -> get_log_path() ->
case ejabberd_config:env_binary_to_list(ejabberd, log_path) of case ejabberd_config:env_binary_to_list(ejabberd, log_path) of
{ok, Path} -> {ok, Path} ->
@ -64,186 +60,113 @@ get_log_path() ->
end end
end. end.
-spec get_integer_env(atom(), T) -> T.
get_integer_env(Name, Default) -> get_integer_env(Name, Default) ->
case application:get_env(ejabberd, Name) of case application:get_env(ejabberd, Name) of
{ok, I} when is_integer(I), I>=0 -> {ok, I} when is_integer(I), I>0 ->
I; I;
undefined -> undefined ->
Default; Default;
{ok, Junk} -> {ok, Junk} ->
error_logger:error_msg("wrong value for ~ts: ~p; " ?LOG_ERROR("Wrong value for ~ts: ~p; "
"using ~p as a fallback~n", "using ~p as a fallback",
[Name, Junk, Default]), [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]),
Default Default
end. 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() ->
start(4). start(info).
-spec start(loglevel()) -> ok. -spec start(loglevel()) -> ok.
start(Level) -> start(Level) ->
LLevel = get_lager_loglevel(Level), EjabberdLog = get_log_path(),
StartedApps = application:which_applications(5000), Dir = filename:dirname(EjabberdLog),
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),
ErrorLog = filename:join([Dir, "error.log"]), 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), LogRotateSize = get_integer_env(log_rotate_size, 10*1024*1024),
LogRotateCount = get_integer_env(log_rotate_count, 1), LogRotateCount = get_integer_env(log_rotate_count, 1),
LogRateLimit = get_integer_env(log_rate_limit, 100), Config = #{max_no_bytes => LogRotateSize,
ConsoleLevel = case get_lager_version() >= "3.6.0" of max_no_files => LogRotateCount,
true -> [{level, Level}]; filesync_repeat_interval => no_repeat,
false -> Level sync_mode_qlen => 1000,
end, drop_mode_qlen => 1000,
application:set_env(lager, error_logger_hwm, LogRateLimit), flush_qlen => 5000},
application:set_env( FmtConfig = #{legacy_header => false,
lager, handlers, time_designator => $ ,
[{lager_console_backend, ConsoleLevel}, max_size => 100*1024,
{lager_file_backend, [{file, ConsoleLog}, {level, Level}, {date, LogRotateDate}, single_line => false},
{count, LogRotateCount}, {size, LogRotateSize}]}, FileFmtConfig = FmtConfig#{template => file_template()},
{lager_file_backend, [{file, ErrorLog}, {level, error}, {date, LogRotateDate}, ConsoleFmtConfig = FmtConfig#{template => console_template()},
{count, LogRotateCount}, {size, LogRotateSize}]}]), logger:set_primary_config(level, Level),
application:set_env(lager, crash_log, CrashLog), logger:add_primary_filter(progress_report,
application:set_env(lager, crash_log_date, LogRotateDate), {fun logger_filters:progress/2, stop}),
application:set_env(lager, crash_log_size, LogRotateSize), logger:update_formatter_config(default, ConsoleFmtConfig),
application:set_env(lager, crash_log_count, LogRotateCount), logger:add_handler(ejabberd_log, logger_std_h,
ejabberd:start_app(lager), #{level => all,
lists:foreach(fun(Handler) -> config => Config#{file => EjabberdLog},
lager:set_loghwm(Handler, LogRateLimit) formatter => {logger_formatter, FileFmtConfig}}),
end, gen_event:which_handlers(lager_event)). logger:add_handler(error_log, logger_std_h,
#{level => error,
restart() -> config => Config#{file => ErrorLog},
Level = ejabberd_option:loglevel(), formatter => {logger_formatter, FileFmtConfig}}),
application:stop(lager), ok.
start(Level).
restart() ->
%% @spec () -> ok ok.
reopen_log() ->
%% Lager detects external log rotation automatically. console_template() ->
[time, " [", level, "] ", msg, io_lib:nl()].
file_template() ->
[time, " [", level, "] ", pid,
{mfa, ["@", mfa, {line, [":", line], []}], []}, " ", msg, io_lib:nl()].
reopen_log() ->
ok. ok.
%% @spec () -> ok
rotate_log() -> rotate_log() ->
catch lager_crash_log ! rotate, ok.
lists:foreach(
fun({lager_file_backend, File}) ->
whereis(lager_event) ! {rotate, File};
(_) ->
ok
end, gen_event:which_handlers(lager_event)).
%% @spec () -> {loglevel(), atom(), string()} -spec get() -> loglevel().
get() -> get() ->
case get_lager_loglevel() of #{level := Level} = logger:get_primary_config(),
none -> {0, no_log, "No log"}; Level.
emergency -> {1, critical, "Critical"};
alert -> {1, critical, "Critical"}; -spec set(0..5 | loglevel()) -> ok.
critical -> {1, critical, "Critical"}; set(N) when is_integer(N), N>=0, N=<5 ->
error -> {2, error, "Error"}; set(convert_loglevel(N));
warning -> {3, warning, "Warning"}; set(Level) when ?is_loglevel(Level) ->
notice -> {3, warning, "Warning"}; case get() of
info -> {4, info, "Info"}; Level -> ok;
debug -> {5, debug, "Debug"} 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. end.
set(LogLevel) when is_integer(LogLevel) -> -spec flush() -> ok.
LagerLogLevel = get_lager_loglevel(LogLevel), flush() ->
case get_lager_loglevel() of lists:foreach(
LagerLogLevel -> fun(#{id := HandlerId, module := logger_std_h}) ->
ok; logger_std_h:filesync(HandlerId);
_ -> (#{id := HandlerId, module := logger_disk_log_h}) ->
ConsoleLog = get_log_path(), logger_disk_log_h:filesync(HandlerId);
lists:foreach( (_) ->
fun({lager_file_backend, File} = H) when File == ConsoleLog -> ok
lager:set_loglevel(H, LagerLogLevel); end, logger:get_handler_config()).
(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
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.

View File

@ -69,9 +69,7 @@
-export([ldap_tls_verify/0, ldap_tls_verify/1]). -export([ldap_tls_verify/0, ldap_tls_verify/1]).
-export([ldap_uids/0, ldap_uids/1]). -export([ldap_uids/0, ldap_uids/1]).
-export([listen/0]). -export([listen/0]).
-export([log_rate_limit/0]).
-export([log_rotate_count/0]). -export([log_rotate_count/0]).
-export([log_rotate_date/0]).
-export([log_rotate_size/0]). -export([log_rotate_size/0]).
-export([loglevel/0]). -export([loglevel/0]).
-export([max_fsm_queue/0, max_fsm_queue/1]). -export([max_fsm_queue/0, max_fsm_queue/1]).
@ -556,23 +554,15 @@ ldap_uids(Host) ->
listen() -> listen() ->
ejabberd_config:get_option({listen, global}). ejabberd_config:get_option({listen, global}).
-spec log_rate_limit() -> 'undefined' | non_neg_integer(). -spec log_rotate_count() -> non_neg_integer().
log_rate_limit() ->
ejabberd_config:get_option({log_rate_limit, global}).
-spec log_rotate_count() -> 'undefined' | non_neg_integer().
log_rotate_count() -> log_rotate_count() ->
ejabberd_config:get_option({log_rotate_count, global}). ejabberd_config:get_option({log_rotate_count, global}).
-spec log_rotate_date() -> 'undefined' | string(). -spec log_rotate_size() -> 'infinity' | pos_integer().
log_rotate_date() ->
ejabberd_config:get_option({log_rotate_date, global}).
-spec log_rotate_size() -> 'undefined' | non_neg_integer().
log_rotate_size() -> log_rotate_size() ->
ejabberd_config:get_option({log_rotate_size, global}). ejabberd_config:get_option({log_rotate_size, global}).
-spec loglevel() -> 0 | 1 | 2 | 3 | 4 | 5. -spec loglevel() -> 'none' | logger:level().
loglevel() -> loglevel() ->
ejabberd_config:get_option({loglevel, global}). ejabberd_config:get_option({loglevel, global}).

View File

@ -198,18 +198,19 @@ opt_type(ldap_uids) ->
econf:map(econf:binary(), econf:binary(), [unique])); econf:map(econf:binary(), econf:binary(), [unique]));
opt_type(listen) -> opt_type(listen) ->
ejabberd_listener:validator(); ejabberd_listener:validator();
opt_type(log_rate_limit) ->
econf:non_neg_int();
opt_type(log_rotate_count) -> opt_type(log_rotate_count) ->
econf:non_neg_int(); econf:non_neg_int();
opt_type(log_rotate_date) ->
econf:string("^(\\$((D(([0-9])|(1[0-9])|(2[0-3])))|"
"(((W[0-6])|(M(([1-2][0-9])|(3[0-1])|([1-9]))))"
"(D(([0-9])|(1[0-9])|(2[0-3])))?)))?$");
opt_type(log_rotate_size) -> opt_type(log_rotate_size) ->
econf:non_neg_int(); econf:pos_int(infinity);
opt_type(loglevel) -> opt_type(loglevel) ->
econf:int(0, 5); fun(N) when is_integer(N) ->
(econf:and_then(
econf:int(0, 5),
fun ejabberd_logger:convert_loglevel/1))(N);
(Level) ->
(econf:enum([none, emergency, alert, critical,
error, warning, notice, info, debug]))(Level)
end;
opt_type(max_fsm_queue) -> opt_type(max_fsm_queue) ->
econf:pos_int(); econf:pos_int();
opt_type(modules) -> opt_type(modules) ->
@ -424,6 +425,7 @@ opt_type(jwt_auth_only_rule) ->
{websocket_origin, [binary()]} | {websocket_origin, [binary()]} |
{disable_sasl_mechanisms, [binary()]} | {disable_sasl_mechanisms, [binary()]} |
{s2s_zlib, boolean()} | {s2s_zlib, boolean()} |
{loglevel, none | logger:level()} |
{listen, [ejabberd_listener:listener()]} | {listen, [ejabberd_listener:listener()]} |
{modules, [{module(), gen_mod:opts(), integer()}]} | {modules, [{module(), gen_mod:opts(), integer()}]} |
{ldap_uids, [{binary(), binary()}]} | {ldap_uids, [{binary(), binary()}]} |
@ -443,7 +445,7 @@ opt_type(jwt_auth_only_rule) ->
options() -> options() ->
[%% Top-priority options [%% Top-priority options
hosts, hosts,
{loglevel, 4}, {loglevel, info},
{cache_life_time, timer:seconds(3600)}, {cache_life_time, timer:seconds(3600)},
{cache_missed, true}, {cache_missed, true},
{cache_size, 1000}, {cache_size, 1000},
@ -527,10 +529,8 @@ options() ->
{ldap_tls_verify, false}, {ldap_tls_verify, false},
{ldap_uids, [{<<"uid">>, <<"%u">>}]}, {ldap_uids, [{<<"uid">>, <<"%u">>}]},
{listen, []}, {listen, []},
{log_rate_limit, undefined}, {log_rotate_count, 1},
{log_rotate_count, undefined}, {log_rotate_size, 10*1024*1024},
{log_rotate_date, undefined},
{log_rotate_size, undefined},
{max_fsm_queue, undefined}, {max_fsm_queue, undefined},
{modules, []}, {modules, []},
{negotiation_timeout, timer:seconds(30)}, {negotiation_timeout, timer:seconds(30)},
@ -669,9 +669,7 @@ globals() ->
host_config, host_config,
listen, listen,
loglevel, loglevel,
log_rate_limit,
log_rotate_count, log_rotate_count,
log_rotate_date,
log_rotate_size, log_rotate_size,
negotiation_timeout, negotiation_timeout,
net_ticktime, net_ticktime,

View File

@ -36,9 +36,7 @@
-export([init/1, handle_event/2, handle_call/2, -export([init/1, handle_event/2, handle_call/2,
handle_info/2, terminate/2, code_change/3]). handle_info/2, terminate/2, code_change/3]).
%% We don't use ejabberd logger because lager can be overloaded -include("logger.hrl").
%% too and alarm_handler may get stuck.
%%-include("logger.hrl").
-define(CHECK_INTERVAL, timer:seconds(30)). -define(CHECK_INTERVAL, timer:seconds(30)).
@ -93,7 +91,7 @@ handle_event({clear_alarm, system_memory_high_watermark}, State) ->
handle_event({set_alarm, {process_memory_high_watermark, Pid}}, State) -> handle_event({set_alarm, {process_memory_high_watermark, Pid}}, State) ->
case proc_stat(Pid, get_app_pids()) of case proc_stat(Pid, get_app_pids()) of
#proc_stat{name = Name} = ProcStat -> #proc_stat{name = Name} = ProcStat ->
error_logger:warning_msg( ?WARNING_MSG(
"Process ~p consumes more than 5% of OS memory (~ts)~n", "Process ~p consumes more than 5% of OS memory (~ts)~n",
[Name, format_proc(ProcStat)]), [Name, format_proc(ProcStat)]),
handle_overload(State), handle_overload(State),
@ -104,7 +102,7 @@ handle_event({set_alarm, {process_memory_high_watermark, Pid}}, State) ->
handle_event({clear_alarm, process_memory_high_watermark}, State) -> handle_event({clear_alarm, process_memory_high_watermark}, State) ->
{ok, State}; {ok, State};
handle_event(Event, State) -> handle_event(Event, State) ->
error_logger:warning_msg("unexpected event: ~p~n", [Event]), ?WARNING_MSG("unexpected event: ~p~n", [Event]),
{ok, State}. {ok, State}.
handle_call(_Request, State) -> handle_call(_Request, State) ->
@ -114,7 +112,7 @@ handle_info({timeout, _TRef, handle_overload}, State) ->
handle_overload(State), handle_overload(State),
{ok, restart_timer(State)}; {ok, restart_timer(State)};
handle_info(Info, State) -> handle_info(Info, State) ->
error_logger:warning_msg("unexpected info: ~p~n", [Info]), ?WARNING_MSG("unexpected info: ~p~n", [Info]),
{ok, State}. {ok, State}.
terminate(_Reason, _State) -> terminate(_Reason, _State) ->
@ -137,7 +135,7 @@ handle_overload(_State, Procs) ->
MaxMsgs = ejabberd_option:oom_queue(), MaxMsgs = ejabberd_option:oom_queue(),
if TotalMsgs >= MaxMsgs -> if TotalMsgs >= MaxMsgs ->
SortedStats = lists:reverse(lists:keysort(#proc_stat.qlen, Stats)), SortedStats = lists:reverse(lists:keysort(#proc_stat.qlen, Stats)),
error_logger:warning_msg( ?WARNING_MSG(
"The system is overloaded with ~b messages " "The system is overloaded with ~b messages "
"queued by ~b process(es) (~b%) " "queued by ~b process(es) (~b%) "
"from the following applications: ~ts; " "from the following applications: ~ts; "
@ -272,7 +270,7 @@ do_kill(Stats, Threshold) ->
when Len >= Threshold -> when Len >= Threshold ->
case lists:member(App, excluded_apps()) of case lists:member(App, excluded_apps()) of
true -> true ->
error_logger:warning_msg( ?WARNING_MSG(
"Unable to kill process ~p from whitelisted " "Unable to kill process ~p from whitelisted "
"application ~p~n", [Name, App]), "application ~p~n", [Name, App]),
false; false;
@ -289,7 +287,7 @@ do_kill(Stats, Threshold) ->
end, Stats), end, Stats),
TotalKilled = length(Killed), TotalKilled = length(Killed),
if TotalKilled > 0 -> if TotalKilled > 0 ->
error_logger:error_msg( ?ERROR_MSG(
"Killed ~b process(es) consuming more than ~b message(s) each~n", "Killed ~b process(es) consuming more than ~b message(s) each~n",
[TotalKilled, Threshold]); [TotalKilled, Threshold]);
true -> true ->

View File

@ -367,16 +367,13 @@ depends(ServerHost, Opts) ->
%% <p>See {@link node_hometree:init/1} for an example implementation.</p> %% <p>See {@link node_hometree:init/1} for an example implementation.</p>
init_plugins(Host, ServerHost, Opts) -> init_plugins(Host, ServerHost, Opts) ->
TreePlugin = tree(Host, mod_pubsub_opt:nodetree(Opts)), TreePlugin = tree(Host, mod_pubsub_opt:nodetree(Opts)),
?DEBUG("** tree plugin is ~p", [TreePlugin]),
TreePlugin:init(Host, ServerHost, Opts), TreePlugin:init(Host, ServerHost, Opts),
Plugins = mod_pubsub_opt:plugins(Opts), Plugins = mod_pubsub_opt:plugins(Opts),
PepMapping = mod_pubsub_opt:pep_mapping(Opts), PepMapping = mod_pubsub_opt:pep_mapping(Opts),
?DEBUG("** PEP Mapping : ~p~n", [PepMapping]),
PluginsOK = lists:foldl( PluginsOK = lists:foldl(
fun (Name, Acc) -> fun (Name, Acc) ->
Plugin = plugin(Host, Name), Plugin = plugin(Host, Name),
apply(Plugin, init, [Host, ServerHost, Opts]), apply(Plugin, init, [Host, ServerHost, Opts]),
?DEBUG("** init ~ts plugin", [Name]),
[Name | Acc] [Name | Acc]
end, end,
[], Plugins), [], Plugins),
@ -385,7 +382,6 @@ init_plugins(Host, ServerHost, Opts) ->
terminate_plugins(Host, ServerHost, Plugins, TreePlugin) -> terminate_plugins(Host, ServerHost, Plugins, TreePlugin) ->
lists:foreach( lists:foreach(
fun (Name) -> fun (Name) ->
?DEBUG("** terminate ~ts plugin", [Name]),
Plugin = plugin(Host, Name), Plugin = plugin(Host, Name),
Plugin:terminate(Host, ServerHost) Plugin:terminate(Host, ServerHost)
end, end,