From 597934637c61e4ec86923fe5db6af5ded2b62dbd Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Thu, 27 Jun 2013 18:58:56 +1000 Subject: [PATCH] Logger improvements. lager: * It is now possible to change the loglevel. * Log rotation is now supported as well. p1_logger: * When rotating a log file, add suffix ".0" to the renamed file. This is needed in order to be consistent with lager rotation mechanism. --- include/logger.hrl | 10 +-- src/ejabberd_app.erl | 43 +------------ src/ejabberd_ctl.erl | 2 +- src/ejabberd_logger.erl | 138 +++++++++++++++++++++++++++++++--------- 4 files changed, 117 insertions(+), 76 deletions(-) diff --git a/include/logger.hrl b/include/logger.hrl index 32e2348c7..17fad8d38 100644 --- a/include/logger.hrl +++ b/include/logger.hrl @@ -41,17 +41,17 @@ -else. -define(DEBUG(Format, Args), - ejabberd_logger:debug_msg(?MODULE, ?LINE, Format, Args)). + p1_logger:debug_msg(?MODULE, ?LINE, Format, Args)). -define(INFO_MSG(Format, Args), - ejabberd_logger:info_msg(?MODULE, ?LINE, Format, Args)). + p1_logger:info_msg(?MODULE, ?LINE, Format, Args)). -define(WARNING_MSG(Format, Args), - ejabberd_logger:warning_msg(?MODULE, ?LINE, Format, Args)). + p1_logger:warning_msg(?MODULE, ?LINE, Format, Args)). -define(ERROR_MSG(Format, Args), - ejabberd_logger:error_msg(?MODULE, ?LINE, Format, Args)). + p1_logger:error_msg(?MODULE, ?LINE, Format, Args)). -define(CRITICAL_MSG(Format, Args), - ejabberd_logger:critical_msg(?MODULE, ?LINE, Format, Args)). + p1_logger:critical_msg(?MODULE, ?LINE, Format, Args)). -endif. diff --git a/src/ejabberd_app.erl b/src/ejabberd_app.erl index b9a48bc42..4a95a11f8 100644 --- a/src/ejabberd_app.erl +++ b/src/ejabberd_app.erl @@ -29,7 +29,7 @@ -behaviour(application). --export([start_modules/0,start/2, get_log_path/0, prep_stop/1, stop/1, init/0]). +-export([start_modules/0,start/2, prep_stop/1, stop/1, init/0]). -include("ejabberd.hrl"). -include("logger.hrl"). @@ -39,8 +39,7 @@ %%% start(normal, _Args) -> - maybe_start_lager(), - ejabberd_logger:set(4), + ejabberd_logger:start(), write_pid_file(), start_apps(), randoms:start(), @@ -98,10 +97,6 @@ start() -> init() -> register(ejabberd, self()), - %erlang:system_flag(fullsweep_after, 0), - %error_logger:logfile({open, ?LOG_PATH}), - LogPath = get_log_path(), - ejabberd_logger:set_logfile(LogPath), loop(). loop() -> @@ -167,26 +162,6 @@ connect_nodes() -> net_kernel:connect_node(Node) end, Nodes). -%% @spec () -> string() -%% @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. -get_log_path() -> - case application:get_env(log_path) of - {ok, Path} -> - Path; - undefined -> - case os:getenv("EJABBERD_LOG_PATH") of - false -> - ?LOG_PATH; - Path -> - Path - end - end. - - %% If ejabberd is running on some Windows machine, get nameservers and add to Erlang maybe_add_nameservers() -> case os:type() of @@ -237,20 +212,6 @@ delete_pid_file() -> file:delete(PidFilename) end. - --ifdef(LAGER). - -maybe_start_lager() -> - lager:start(). - --else. - -maybe_start_lager() -> - ok. - --endif. - - start_apps() -> ejabberd:start_app(sasl), ejabberd:start_app(ssl), diff --git a/src/ejabberd_ctl.erl b/src/ejabberd_ctl.erl index a9a6f6725..38b94ef4d 100644 --- a/src/ejabberd_ctl.erl +++ b/src/ejabberd_ctl.erl @@ -135,7 +135,7 @@ process(["status"]) -> [node(), InternalStatus, ProvidedStatus]), case lists:keysearch(ejabberd, 1, application:which_applications()) of false -> - EjabberdLogPath = ejabberd_app:get_log_path(), + EjabberdLogPath = ejabberd_logger:get_log_path(), ?PRINT("ejabberd is not running in that node~n" "Check for error messages: ~s~n" "or other files in that directory.~n", [EjabberdLogPath]), diff --git a/src/ejabberd_logger.erl b/src/ejabberd_logger.erl index 5d29c99e1..01daa6250 100644 --- a/src/ejabberd_logger.erl +++ b/src/ejabberd_logger.erl @@ -27,22 +27,126 @@ -module(ejabberd_logger). %% API --export([start/0, set_logfile/1, reopen_log/0, get/0, set/1, - debug_msg/4, info_msg/4, warning_msg/4, error_msg/4, - critical_msg/4]). +-export([start/0, reopen_log/0, get/0, set/1, get_log_path/0]). + +-include("ejabberd.hrl"). + +-type loglevel() :: 0 | 1 | 2 | 3 | 4 | 5. + +-spec start() -> ok. +-spec get_log_path() -> string(). +-spec reopen_log() -> ok. +-spec get() -> {loglevel(), atom(), string()}. +-spec set(loglevel()) -> {module, module()}. %%%=================================================================== %%% 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. +get_log_path() -> + case application:get_env(ejabberd, log_path) of + {ok, Path} -> + Path; + undefined -> + case os:getenv("EJABBERD_LOG_PATH") of + false -> + ?LOG_PATH; + Path -> + Path + end + end. + +-ifdef(LAGER). + start() -> + application:load(lager), + ConsoleLog = get_log_path(), + Dir = filename:dirname(ConsoleLog), + ErrorLog = filename:join([Dir, "error.log"]), + application:set_env( + lager, handlers, + [{lager_console_backend, info}, + {lager_file_backend, [{file, ConsoleLog}, {level, info}, {count, 1}]}, + {lager_file_backend, [{file, ErrorLog}, {level, error}, {count, 1}]}]), + ejabberd:start_app(lager), ok. -set_logfile(FileName) -> - error_logger:add_report_handler(p1_logger_h, FileName). +reopen_log() -> + lists:foreach( + fun({lager_file_backend, File}) -> + whereis(lager_event) ! {rotate, File}; + (_) -> + ok + end, gen_event:which_handlers(lager_event)), + reopen_sasl_log(). + +get() -> + case lager:get_loglevel(lager_console_backend) 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) -> + LagerLogLevel = case LogLevel of + 0 -> none; + 1 -> critical; + 2 -> error; + 3 -> warning; + 4 -> info; + 5 -> debug + end, + case lager:get_loglevel(lager_console_backend) 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); + (_) -> + ok + end, gen_event:which_handlers(lager_event)) + end, + {module, lager}. + +-else. + +start() -> + set(4), + LogPath = get_log_path(), + error_logger:add_report_handler(p1_logger_h, LogPath), + ok. reopen_log() -> %% TODO: Use the Reopen log API for logger_h ? p1_logger_h:reopen_log(), + reopen_sasl_log(). + +get() -> + p1_loglevel:get(). + +set(LogLevel) -> + p1_loglevel:set(LogLevel). + +-endif. + +%%%=================================================================== +%%% Internal functions +%%%=================================================================== +reopen_sasl_log() -> case application:get_env(sasl,sasl_error_logger) of {ok, {file, SASLfile}} -> error_logger:delete_report_handler(sasl_report_file_h), @@ -53,30 +157,6 @@ reopen_log() -> end, ok. -get() -> - p1_loglevel:get(). - -set(LogLevel) -> - p1_loglevel:set(LogLevel). - -debug_msg(Mod, Line, Format, Args) -> - p1_logger:debug_msg(Mod, Line, Format, Args). - -info_msg(Mod, Line, Format, Args) -> - p1_logger:info_msg(Mod, Line, Format, Args). - -warning_msg(Mod, Line, Format, Args) -> - p1_logger:warning_msg(Mod, Line, Format, Args). - -error_msg(Mod, Line, Format, Args) -> - p1_logger:error_msg(Mod, Line, Format, Args). - -critical_msg(Mod, Line, Format, Args) -> - p1_logger:critical_msg(Mod, Line, Format, Args). - -%%%=================================================================== -%%% Internal functions -%%%=================================================================== %% Function copied from Erlang/OTP lib/sasl/src/sasl.erl which doesn't export it get_sasl_error_logger_type () -> case application:get_env (sasl, errlog_type) of