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