mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-20 16:15:59 +01:00
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:
parent
b1d458999a
commit
e4a8afb15d
@ -1,9 +1,8 @@
|
||||
language: erlang
|
||||
|
||||
otp_release:
|
||||
- 19.3
|
||||
- 20.3
|
||||
- 21.2
|
||||
- 21.0
|
||||
- 22.1
|
||||
|
||||
services:
|
||||
- redis-server
|
||||
|
14
README.md
14
README.md
@ -14,24 +14,24 @@ solutions very cost effectively.
|
||||
Key Features
|
||||
------------
|
||||
|
||||
- **Cross-platform**
|
||||
- **Cross-platform**
|
||||
ejabberd runs under Microsoft Windows and Unix-derived systems such as
|
||||
Linux, FreeBSD and NetBSD.
|
||||
|
||||
- **Distributed**
|
||||
- **Distributed**
|
||||
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
|
||||
cheap node to your cluster. Accordingly, you do not need to buy an expensive
|
||||
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
|
||||
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
|
||||
without disruption. In addition, nodes also can be added or replaced ‘on
|
||||
the fly’.
|
||||
|
||||
- **Administrator-friendly**
|
||||
- **Administrator-friendly**
|
||||
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
|
||||
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.
|
||||
- Capability to send announce messages.
|
||||
|
||||
- **Internationalized**
|
||||
- **Internationalized**
|
||||
ejabberd leads in internationalization. Hence it is very well suited in a
|
||||
globalized world. Related features are:
|
||||
- Translated to 25 languages.
|
||||
- Support for IDNA.
|
||||
|
||||
- **Open Standards**
|
||||
- **Open Standards**
|
||||
ejabberd is the first Open Source Jabber server claiming to fully comply to
|
||||
the XMPP standard.
|
||||
- Fully XMPP-compliant.
|
||||
@ -107,7 +107,7 @@ To compile ejabberd you need:
|
||||
- GCC.
|
||||
- Libexpat ≥ 1.95.
|
||||
- Libyaml ≥ 0.1.4.
|
||||
- Erlang/OTP ≥ 19.1.
|
||||
- Erlang/OTP ≥ 21.0.
|
||||
- OpenSSL ≥ 1.0.0.
|
||||
- Zlib ≥ 1.2.3, for Stream Compression support (XEP-0138). Optional.
|
||||
- PAM library. Optional. For Pluggable Authentication Modules (PAM).
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
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])
|
||||
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)"
|
||||
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
@ -17,11 +17,7 @@
|
||||
hosts:
|
||||
- localhost
|
||||
|
||||
loglevel: 4
|
||||
log_rotate_size: 10485760
|
||||
log_rotate_date: ""
|
||||
log_rotate_count: 1
|
||||
log_rate_limit: 100
|
||||
loglevel: info
|
||||
|
||||
## If you already have certificates, list them here
|
||||
# certfiles:
|
||||
|
@ -17,24 +17,24 @@
|
||||
%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
-include_lib("kernel/include/logger.hrl").
|
||||
|
||||
-define(PRINT(Format, Args), io:format(Format, Args)).
|
||||
-compile([{parse_transform, lager_transform}]).
|
||||
|
||||
-define(DEBUG(Format, Args),
|
||||
begin lager:debug(Format, Args), ok end).
|
||||
begin ?LOG_DEBUG(Format, Args), ok end).
|
||||
|
||||
-define(INFO_MSG(Format, Args),
|
||||
begin lager:info(Format, Args), ok end).
|
||||
begin ?LOG_INFO(Format, Args), ok end).
|
||||
|
||||
-define(WARNING_MSG(Format, Args),
|
||||
begin lager:warning(Format, Args), ok end).
|
||||
begin ?LOG_WARNING(Format, Args), ok end).
|
||||
|
||||
-define(ERROR_MSG(Format, Args),
|
||||
begin lager:error(Format, Args), ok end).
|
||||
begin ?LOG_ERROR(Format, Args), ok end).
|
||||
|
||||
-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
|
||||
-define(EXUNIT_LOG(Format, Args),
|
||||
|
@ -18,8 +18,7 @@
|
||||
%%%
|
||||
%%%----------------------------------------------------------------------
|
||||
|
||||
{deps, [{lager, ".*", {git, "https://github.com/erlang-lager/lager", "3.6.10"}},
|
||||
{p1_utils, ".*", {git, "https://github.com/processone/p1_utils", {tag, "1.0.16"}}},
|
||||
{deps, [{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"}}},
|
||||
{fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.1.2"}}},
|
||||
{stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.17"}}},
|
||||
|
@ -6,7 +6,7 @@
|
||||
{modules, []},
|
||||
{registered, []},
|
||||
{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@]}]},
|
||||
{mod, {ejabberd_app, []}}]}.
|
||||
|
||||
|
@ -49,8 +49,7 @@ stop() ->
|
||||
application:stop(ejabberd).
|
||||
|
||||
halt() ->
|
||||
_ = application:stop(lager),
|
||||
_ = application:stop(sasl),
|
||||
ejabberd_logger:flush(),
|
||||
erlang:halt(1, [{flush, true}]).
|
||||
|
||||
%% @spec () -> false | string()
|
||||
|
@ -142,20 +142,16 @@ get_commands_spec() ->
|
||||
desc = "Get the current loglevel",
|
||||
module = ejabberd_logger, function = get,
|
||||
result_desc = "Tuple with the log level number, its keyword and description",
|
||||
result_example = {4, info, <<"Info">>},
|
||||
result_example = warning,
|
||||
args = [],
|
||||
result = {leveltuple, {tuple, [{levelnumber, integer},
|
||||
{levelatom, atom},
|
||||
{leveldesc, string}
|
||||
]}}},
|
||||
result = {levelatom, atom}},
|
||||
#ejabberd_commands{name = set_loglevel, tags = [logs, server],
|
||||
desc = "Set the loglevel (0 to 5)",
|
||||
desc = "Set the loglevel",
|
||||
module = ?MODULE, function = set_loglevel,
|
||||
args_desc = ["Integer of the desired logging level, between 1 and 5"],
|
||||
args_example = [5],
|
||||
result_desc = "The type of logger module used",
|
||||
result_example = lager,
|
||||
args = [{loglevel, integer}],
|
||||
args_desc = ["Desired logging level: none | emergency | alert | critical "
|
||||
"| error | warning | notice | info | debug"],
|
||||
args_example = [debug],
|
||||
args = [{loglevel, string}],
|
||||
result = {res, rescode}},
|
||||
|
||||
#ejabberd_commands{name = update_list, tags = [server],
|
||||
@ -410,15 +406,23 @@ status() ->
|
||||
{Is_running, String1 ++ String2}.
|
||||
|
||||
reopen_log() ->
|
||||
ejabberd_hooks:run(reopen_log_hook, []),
|
||||
ejabberd_logger:reopen_log().
|
||||
ejabberd_hooks:run(reopen_log_hook, []).
|
||||
|
||||
rotate_log() ->
|
||||
ejabberd_hooks:run(rotate_log_hook, []),
|
||||
ejabberd_logger:rotate_log().
|
||||
ejabberd_hooks:run(rotate_log_hook, []).
|
||||
|
||||
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
|
||||
|
@ -84,8 +84,6 @@ start_included_apps() ->
|
||||
lists:foreach(
|
||||
fun(mnesia) ->
|
||||
ok;
|
||||
(lager)->
|
||||
ok;
|
||||
(os_mon)->
|
||||
ok;
|
||||
(App) ->
|
||||
|
@ -522,7 +522,7 @@ read_erlang_file(File, _) ->
|
||||
validate(Y1) ->
|
||||
case pre_validate(Y1) of
|
||||
{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
|
||||
{ok, Y3} ->
|
||||
Hosts = proplists:get_value(hosts, Y3),
|
||||
@ -763,7 +763,7 @@ set_shared_key() ->
|
||||
set_node_start(UnixTime) ->
|
||||
set_option(node_start, UnixTime).
|
||||
|
||||
-spec set_loglevel(0..5) -> ok.
|
||||
-spec set_loglevel(logger:level()) -> ok.
|
||||
set_loglevel(Level) ->
|
||||
ejabberd_logger:set(Level).
|
||||
|
||||
|
@ -30,12 +30,6 @@ map_reduce(Y) ->
|
||||
F = fun(Y1) ->
|
||||
Y2 = (validator())(Y1),
|
||||
Y3 = transform(Y2),
|
||||
if Y2 /= Y3 ->
|
||||
?DEBUG("Transformed configuration:~ts~n",
|
||||
[misc:format_val({yaml, Y3})]);
|
||||
true ->
|
||||
ok
|
||||
end,
|
||||
Y3
|
||||
end,
|
||||
econf:validate(F, Y).
|
||||
@ -148,6 +142,12 @@ filter(Host, Y, Acc) ->
|
||||
filter(Host, Opt, Val, Acc)
|
||||
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, _, _) ->
|
||||
warn_removed_option(ca_path, ca_file),
|
||||
false;
|
||||
|
@ -68,6 +68,7 @@
|
||||
%%-----------------------------
|
||||
|
||||
start() ->
|
||||
logger:set_primary_config(level, none),
|
||||
[SNode, Timeout, Args] = case init:get_plain_arguments() of
|
||||
[SNode2, "--no-timeout" | Args2] ->
|
||||
[SNode2, infinity, Args2];
|
||||
|
@ -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)).
|
||||
|
||||
restart() ->
|
||||
Level = ejabberd_option:loglevel(),
|
||||
application:stop(lager),
|
||||
start(Level).
|
||||
|
||||
%% @spec () -> ok
|
||||
reopen_log() ->
|
||||
%% Lager detects external log rotation automatically.
|
||||
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() ->
|
||||
ok.
|
||||
|
||||
console_template() ->
|
||||
[time, " [", level, "] ", msg, io_lib:nl()].
|
||||
|
||||
file_template() ->
|
||||
[time, " [", level, "] ", pid,
|
||||
{mfa, ["@", mfa, {line, [":", line], []}], []}, " ", msg, io_lib:nl()].
|
||||
|
||||
reopen_log() ->
|
||||
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"}
|
||||
#{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.
|
||||
|
||||
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
|
||||
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()).
|
||||
|
@ -69,9 +69,7 @@
|
||||
-export([ldap_tls_verify/0, ldap_tls_verify/1]).
|
||||
-export([ldap_uids/0, ldap_uids/1]).
|
||||
-export([listen/0]).
|
||||
-export([log_rate_limit/0]).
|
||||
-export([log_rotate_count/0]).
|
||||
-export([log_rotate_date/0]).
|
||||
-export([log_rotate_size/0]).
|
||||
-export([loglevel/0]).
|
||||
-export([max_fsm_queue/0, max_fsm_queue/1]).
|
||||
@ -556,23 +554,15 @@ ldap_uids(Host) ->
|
||||
listen() ->
|
||||
ejabberd_config:get_option({listen, global}).
|
||||
|
||||
-spec log_rate_limit() -> 'undefined' | non_neg_integer().
|
||||
log_rate_limit() ->
|
||||
ejabberd_config:get_option({log_rate_limit, global}).
|
||||
|
||||
-spec log_rotate_count() -> 'undefined' | non_neg_integer().
|
||||
-spec log_rotate_count() -> non_neg_integer().
|
||||
log_rotate_count() ->
|
||||
ejabberd_config:get_option({log_rotate_count, global}).
|
||||
|
||||
-spec log_rotate_date() -> 'undefined' | string().
|
||||
log_rotate_date() ->
|
||||
ejabberd_config:get_option({log_rotate_date, global}).
|
||||
|
||||
-spec log_rotate_size() -> 'undefined' | non_neg_integer().
|
||||
-spec log_rotate_size() -> 'infinity' | pos_integer().
|
||||
log_rotate_size() ->
|
||||
ejabberd_config:get_option({log_rotate_size, global}).
|
||||
|
||||
-spec loglevel() -> 0 | 1 | 2 | 3 | 4 | 5.
|
||||
-spec loglevel() -> 'none' | logger:level().
|
||||
loglevel() ->
|
||||
ejabberd_config:get_option({loglevel, global}).
|
||||
|
||||
|
@ -198,18 +198,19 @@ opt_type(ldap_uids) ->
|
||||
econf:map(econf:binary(), econf:binary(), [unique]));
|
||||
opt_type(listen) ->
|
||||
ejabberd_listener:validator();
|
||||
opt_type(log_rate_limit) ->
|
||||
econf:non_neg_int();
|
||||
opt_type(log_rotate_count) ->
|
||||
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) ->
|
||||
econf:non_neg_int();
|
||||
econf:pos_int(infinity);
|
||||
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) ->
|
||||
econf:pos_int();
|
||||
opt_type(modules) ->
|
||||
@ -424,6 +425,7 @@ opt_type(jwt_auth_only_rule) ->
|
||||
{websocket_origin, [binary()]} |
|
||||
{disable_sasl_mechanisms, [binary()]} |
|
||||
{s2s_zlib, boolean()} |
|
||||
{loglevel, none | logger:level()} |
|
||||
{listen, [ejabberd_listener:listener()]} |
|
||||
{modules, [{module(), gen_mod:opts(), integer()}]} |
|
||||
{ldap_uids, [{binary(), binary()}]} |
|
||||
@ -443,7 +445,7 @@ opt_type(jwt_auth_only_rule) ->
|
||||
options() ->
|
||||
[%% Top-priority options
|
||||
hosts,
|
||||
{loglevel, 4},
|
||||
{loglevel, info},
|
||||
{cache_life_time, timer:seconds(3600)},
|
||||
{cache_missed, true},
|
||||
{cache_size, 1000},
|
||||
@ -527,10 +529,8 @@ options() ->
|
||||
{ldap_tls_verify, false},
|
||||
{ldap_uids, [{<<"uid">>, <<"%u">>}]},
|
||||
{listen, []},
|
||||
{log_rate_limit, undefined},
|
||||
{log_rotate_count, undefined},
|
||||
{log_rotate_date, undefined},
|
||||
{log_rotate_size, undefined},
|
||||
{log_rotate_count, 1},
|
||||
{log_rotate_size, 10*1024*1024},
|
||||
{max_fsm_queue, undefined},
|
||||
{modules, []},
|
||||
{negotiation_timeout, timer:seconds(30)},
|
||||
@ -669,9 +669,7 @@ globals() ->
|
||||
host_config,
|
||||
listen,
|
||||
loglevel,
|
||||
log_rate_limit,
|
||||
log_rotate_count,
|
||||
log_rotate_date,
|
||||
log_rotate_size,
|
||||
negotiation_timeout,
|
||||
net_ticktime,
|
||||
|
@ -36,9 +36,7 @@
|
||||
-export([init/1, handle_event/2, handle_call/2,
|
||||
handle_info/2, terminate/2, code_change/3]).
|
||||
|
||||
%% We don't use ejabberd logger because lager can be overloaded
|
||||
%% too and alarm_handler may get stuck.
|
||||
%%-include("logger.hrl").
|
||||
-include("logger.hrl").
|
||||
|
||||
-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) ->
|
||||
case proc_stat(Pid, get_app_pids()) of
|
||||
#proc_stat{name = Name} = ProcStat ->
|
||||
error_logger:warning_msg(
|
||||
?WARNING_MSG(
|
||||
"Process ~p consumes more than 5% of OS memory (~ts)~n",
|
||||
[Name, format_proc(ProcStat)]),
|
||||
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) ->
|
||||
{ok, State};
|
||||
handle_event(Event, State) ->
|
||||
error_logger:warning_msg("unexpected event: ~p~n", [Event]),
|
||||
?WARNING_MSG("unexpected event: ~p~n", [Event]),
|
||||
{ok, State}.
|
||||
|
||||
handle_call(_Request, State) ->
|
||||
@ -114,7 +112,7 @@ handle_info({timeout, _TRef, handle_overload}, State) ->
|
||||
handle_overload(State),
|
||||
{ok, restart_timer(State)};
|
||||
handle_info(Info, State) ->
|
||||
error_logger:warning_msg("unexpected info: ~p~n", [Info]),
|
||||
?WARNING_MSG("unexpected info: ~p~n", [Info]),
|
||||
{ok, State}.
|
||||
|
||||
terminate(_Reason, _State) ->
|
||||
@ -137,7 +135,7 @@ handle_overload(_State, Procs) ->
|
||||
MaxMsgs = ejabberd_option:oom_queue(),
|
||||
if TotalMsgs >= MaxMsgs ->
|
||||
SortedStats = lists:reverse(lists:keysort(#proc_stat.qlen, Stats)),
|
||||
error_logger:warning_msg(
|
||||
?WARNING_MSG(
|
||||
"The system is overloaded with ~b messages "
|
||||
"queued by ~b process(es) (~b%) "
|
||||
"from the following applications: ~ts; "
|
||||
@ -272,7 +270,7 @@ do_kill(Stats, Threshold) ->
|
||||
when Len >= Threshold ->
|
||||
case lists:member(App, excluded_apps()) of
|
||||
true ->
|
||||
error_logger:warning_msg(
|
||||
?WARNING_MSG(
|
||||
"Unable to kill process ~p from whitelisted "
|
||||
"application ~p~n", [Name, App]),
|
||||
false;
|
||||
@ -289,7 +287,7 @@ do_kill(Stats, Threshold) ->
|
||||
end, Stats),
|
||||
TotalKilled = length(Killed),
|
||||
if TotalKilled > 0 ->
|
||||
error_logger:error_msg(
|
||||
?ERROR_MSG(
|
||||
"Killed ~b process(es) consuming more than ~b message(s) each~n",
|
||||
[TotalKilled, Threshold]);
|
||||
true ->
|
||||
|
@ -367,16 +367,13 @@ depends(ServerHost, Opts) ->
|
||||
%% <p>See {@link node_hometree:init/1} for an example implementation.</p>
|
||||
init_plugins(Host, ServerHost, Opts) ->
|
||||
TreePlugin = tree(Host, mod_pubsub_opt:nodetree(Opts)),
|
||||
?DEBUG("** tree plugin is ~p", [TreePlugin]),
|
||||
TreePlugin:init(Host, ServerHost, Opts),
|
||||
Plugins = mod_pubsub_opt:plugins(Opts),
|
||||
PepMapping = mod_pubsub_opt:pep_mapping(Opts),
|
||||
?DEBUG("** PEP Mapping : ~p~n", [PepMapping]),
|
||||
PluginsOK = lists:foldl(
|
||||
fun (Name, Acc) ->
|
||||
Plugin = plugin(Host, Name),
|
||||
apply(Plugin, init, [Host, ServerHost, Opts]),
|
||||
?DEBUG("** init ~ts plugin", [Name]),
|
||||
[Name | Acc]
|
||||
end,
|
||||
[], Plugins),
|
||||
@ -385,7 +382,6 @@ init_plugins(Host, ServerHost, Opts) ->
|
||||
terminate_plugins(Host, ServerHost, Plugins, TreePlugin) ->
|
||||
lists:foreach(
|
||||
fun (Name) ->
|
||||
?DEBUG("** terminate ~ts plugin", [Name]),
|
||||
Plugin = plugin(Host, Name),
|
||||
Plugin:terminate(Host, ServerHost)
|
||||
end,
|
||||
|
Loading…
Reference in New Issue
Block a user