]> granicus.if.org Git - ejabberd/commitdiff
Replace lager with built-in new logging API
authorEvgeny Khramtsov <ekhramtsov@process-one.net>
Fri, 18 Oct 2019 16:12:32 +0000 (19:12 +0300)
committerEvgeny Khramtsov <ekhramtsov@process-one.net>
Fri, 18 Oct 2019 16:12:32 +0000 (19:12 +0300)
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.

18 files changed:
.travis.yml
README.md
configure.ac
ejabberd.yml.example
include/logger.hrl
rebar.config
src/ejabberd.app.src.in
src/ejabberd.erl
src/ejabberd_admin.erl
src/ejabberd_app.erl
src/ejabberd_config.erl
src/ejabberd_config_transformer.erl
src/ejabberd_ctl.erl
src/ejabberd_logger.erl
src/ejabberd_option.erl
src/ejabberd_options.erl
src/ejabberd_system_monitor.erl
src/mod_pubsub.erl

index 1228999c4efd950ae524ba7538e30a56ecc08136..b867cc4a6a18cd689697dede62ed09892aee013d 100644 (file)
@@ -1,9 +1,8 @@
 language: erlang
 
 otp_release:
-  - 19.3
-  - 20.3
-  - 21.2
+  - 21.0
+  - 22.1
 
 services:
   - redis-server
index 35411cf97b6d3646f20d787afdb4f7fcdb31d082..5f92d7a99ae5aa9943549b2e22ca1e05837a9e51 100644 (file)
--- a/README.md
+++ b/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).
index 6a294b081ef7c1e394870534f6c2c2f47fe89361..4fc8882b0f9819a439b71f60238ddf5fe22c9207 100644 (file)
@@ -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])
index ffeb7d73b105da7c00620ac92873894f63199f12..57f7fef1207a19868db1a9d2d67086460e4ea5e7 100644 (file)
 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:
index 2acd126b401d7276436a5cf78ac4a17898bc96ea..b0d1bd361458a8f5969d0fcfa45f30918b5d00c3 100644 (file)
 %%% 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),
index a55b0b8880dc7b9e467929fc6888fc7b9a4b1be5..2b5482a81765300f4de928b8dfac1b9e31e8f43c 100644 (file)
@@ -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"}}},
index f1d08b8c74e29c96e11807406c3bef2d90092ce8..7908ec101fcc2b3570fe3e0de09f711cd5433dde 100644 (file)
@@ -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, []}}]}.
 
index 7bc9004072b7f9f35826ddba43dfc1aeed70284c..4758fd2f9835dab01158ce2062d988acbe615530 100644 (file)
@@ -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()
index 3961c56cea5ed9177d27824b20b06eae197d4302..7776af3a11a95d0e4ce00f1a7783525dfb0b78d9 100644 (file)
@@ -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
index f7df1dd7f6942bc891ffc7f6f283e98e6dfb1b84..d777fd86ecdcb9b5ec7efc1d8497e27813df3501 100644 (file)
@@ -84,8 +84,6 @@ start_included_apps() ->
     lists:foreach(
        fun(mnesia) ->
               ok;
-          (lager)->
-              ok;
           (os_mon)->
               ok;
           (App) ->
index 9d0290f415cf10596b7d502efaa07a2222b63e3d..aa13dec8793e9b86e0545ca9154a6e1bf37464e7 100644 (file)
@@ -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).
 
index 18d79295b30d88752fe8e259525190ab32ce2df3..4dbb2a22fab90385d38d76f6f740270cd03cb40d 100644 (file)
@@ -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;
index 731b704e159bbb3ac6177444e0b3df8337092897..76a028389940fe24103a1132bfea776a66c06bf9 100644 (file)
@@ -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];
index fa415128379ccf650218352afca0cbfb6f9c29d3..c1abd19b7ee6798eb132357d7ce609d000610229 100644 (file)
 
 %%%-------------------------------------------------------------------
 -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()).
index 81b0f0c11e6a6e972297fb5a1da74943e54595a8..d9721ab1f36ca3405e3ad1ca3405a22ac0375cf9 100644 (file)
@@ -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}).
 
index 126891bc247d05e5d30ecba3d48103e7d6fe9110..e95ac878d65148bb98ece62c60cd9bf366d4f522 100644 (file)
@@ -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,
index ff9903b42e9921488bdda70e61b56b6023751e62..7e7e52b8ef982118a725d4a3d8d82d652a392920 100644 (file)
@@ -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 ->
index ca99a21efeac351ff0299e35a42ef4eb6f7bac1d..0063df8d9041b3c37d9e893c4de2a77d4b67a7da 100644 (file)
@@ -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,