@ -1,21 +1,27 @@
% % @ doc A error_logger backend for redirecting events into lager .
% % Error messages and crash logs are also optionally written to a crash log .
% % @ see lager_crash_log
% % @ private
- module ( rumErrLoggerH ) .
- module ( rumErrLoggerH ) .
% % 一 个 error_logger后端 , 用 于 将 事 件 重 定 向 到 eRum 。
% % 错 误 消 息 和 崩 溃 日 志 也 可 以 选 择 写 入 崩 溃 日 志 。 @ see lager_crash_log
- include ( " eRum.hrl " ) .
- include ( " eRum.hrl " ) .
- behaviour ( gen_event ) .
- behaviour ( gen_event ) .
- export ( [ set_high_water / 1 ] ) .
- export ( [ init / 1 , handle_call / 2 , handle_event / 2 , handle_info / 2 , terminate / 2 ,
code_change / 3 ] ) .
- export ( [ format_reason / 1 , format_mfa / 1 , format_args / 3 ] ) .
- export ( [
setHighWater / 1
, format_reason / 1
, format_mfa / 1
, format_args / 3
] ) .
- export ( [
init / 1
, handle_call / 2
, handle_event / 2
, handle_info / 2
, terminate / 2 ,
code_change / 3
] ) .
- record ( state , {
- record ( state , {
sink : : atom ( ) ,
sink : : atom ( ) ,
@ -50,34 +56,36 @@
gen_srv : send ( rumCrashLog , { mWriteLog , Event } ) ) .
gen_srv : send ( rumCrashLog , { mWriteLog , Event } ) ) .
- endif .
- endif .
set_high_w ater ( N ) - >
gen_event : call ( error_logger , ? MODULE , { set_high_w ater, N } , infinity ) .
setHighW ater ( N ) - >
gen_event : call ( error_logger , ? MODULE , { mSetHighW ater, N } , infinity ) .
- spec init ( any ( ) ) - > { ok , #state { } } .
- spec init ( any ( ) ) - > { ok , #state { } } .
init ( [ HighWaterMark , GlStrategy ] ) - >
init ( [ HighWaterMark , GlStrategy ] ) - >
Flush = application : get_env ( lager , error_logger_flush_q ueue, true ) ,
FlushThr = application : get_env ( lager , error_logger_flush_t hreshold, 0 ) ,
Shaper = #rumShaper { hwm = HighWaterMark , flushQueue = Flush , flushThreshold = FlushThr , filter = shaper_f un ( ) , id = ? MODULE } ,
Raw = application : get_env ( lager , error_logger_format_r aw, false ) ,
Sink = configured_s ink ( ) ,
Flush = rumUtil : get_env ( errLoggerFlushQ ueue, true ) ,
FlushThr = rumUtil : get_env ( errLoggerFlushT hreshold, 0 ) ,
Shaper = #rumShaper { hwm = HighWaterMark , flushQueue = Flush , flushThreshold = FlushThr , filter = shaperF un ( ) , id = ? MODULE } ,
Raw = rumUtil : get_env ( errLoggerFormatR aw, false ) ,
Sink = configS ink ( ) ,
{ ok , #state { sink = Sink , shaper = Shaper , groupleader_strategy = GlStrategy , raw = Raw } } .
{ ok , #state { sink = Sink , shaper = Shaper , groupleader_strategy = GlStrategy , raw = Raw } } .
handle_call ( { set_high_w ater, N } , #state { shaper = Shaper } = State ) - >
handle_call ( { mSetHighW ater, N } , #state { shaper = Shaper } = State ) - >
NewShaper = Shaper #rumShaper { hwm = N } ,
NewShaper = Shaper #rumShaper { hwm = N } ,
{ ok , ok , State #state { shaper = NewShaper } } ;
{ ok , ok , State #state { shaper = NewShaper } } ;
handle_call ( _ Request , State ) - >
handle_call ( _ Request , State ) - >
{ ok , unknown_call , State } .
{ ok , unknown_call , State } .
shaper_f un ( ) - >
case { application : get_env ( lager , suppress_supervisor_start_stop, false ) , application : get_env ( lager , suppress_application_start_stop , false ) } of
{ false , false } - >
fun ( _ ) - > false end ;
{ true , true } - >
shaperF un ( ) - >
SupSS = rumUtil : get_env ( suppress_supervisor_start_stop , false ) ,
AppSS = rumUtil : get_env ( suppress_application_start_stop , false ) ,
i f
SupSS andalso AppSS - >
fun suppress_supervisor_start_and_application_start / 1 ;
fun suppress_supervisor_start_and_application_start / 1 ;
{ false , true } - >
SupSS - >
fun suppress_supervisor_start / 1 ;
AppSS - >
fun suppress_application_start / 1 ;
fun suppress_application_start / 1 ;
{ true , false } - >
fun suppress_supervisor_start / 1
true - >
fun ( _ ) - > false end
end .
end .
suppress_supervisor_start_and_application_start ( E ) - >
suppress_supervisor_start_and_application_start ( E ) - >
@ -97,182 +105,194 @@ suppress_supervisor_start(_) ->
handle_event ( Event , #state { sink = Sink , shaper = Shaper } = State ) - >
handle_event ( Event , #state { sink = Sink , shaper = Shaper } = State ) - >
case rumUtil : checkHwm ( Shaper , Event ) of
case rumUtil : checkHwm ( Shaper , Event ) of
{ true , 0 , NewShaper } - >
eval_gl ( Event , State #state { shaper = NewShaper } ) ;
{ true , Drop , #rumShaper { hwm = Hwm } = NewShaper } when Drop > 0 - >
? LOGFMT ( Sink , warning , self ( ) ,
" lager_error_logger_h dropped ~p messages in the last second that exceeded the limit of ~p messages/sec " ,
[ Drop , Hwm ] ) ,
eval_gl ( Event , State #state { shaper = NewShaper } ) ;
{ false , _ , #rumShaper { dropped = D } = NewShaper } - >
{ ok , State #state { shaper = NewShaper #rumShaper { dropped = D + 1 } } }
{ true , _ Drop , NewShaper } - >
evalGl ( Event , State #state { shaper = NewShaper } ) ;
{ drop , Drop , NewShaper } - >
case Drop =< 0 of
true - >
{ ok , State #state { shaper = NewShaper } } ;
_ - >
? LOGFMT ( Sink , warning , self ( ) , " lager_error_logger_h dropped ~p messages in the last second that exceeded the limit of ~p messages/sec " , [ Drop , NewShaper #rumShaper.hwm ] ) ,
evalGl ( Event , State #state { shaper = NewShaper } )
end ;
{ false , _ , NewShaper } - >
{ ok , State #state { shaper = NewShaper } }
end .
end .
handle_info ( { mShaperExpired , ? MODULE } , #state { sink = Sink , shaper = Shaper } = State ) - >
handle_info ( { mShaperExpired , ? MODULE } , #state { sink = Sink , shaper = Shaper } = State ) - >
case Shaper #rumShaper.dropped of
case Shaper #rumShaper.dropped of
0 - >
0 - >
ok ;
ignore ;
Dropped - >
Dropped - >
? LOGFMT ( Sink , warning , self ( ) ,
" lager_error_logger_h dropped ~p messages in the last second that exceeded the limit of ~p messages/sec " ,
[ Dropped , Shaper #rumShaper.hwm ] )
? LOGFMT ( Sink , warning , self ( ) , " lager_error_logger_h dropped ~p messages in the last second that exceeded the limit of ~p messages/sec " , [ Dropped , Shaper #rumShaper.hwm ] )
end ,
end ,
{ ok , State #state { shaper = Shaper #rumShaper { dropped = 0 , mps = 0 , lastTime = os : timestamp ( ) } } } ;
{ ok , State #state { shaper = Shaper #rumShaper { dropped = 0 , mps = 0 , lastTime = rumTime : now ( ) } } } ;
handle_info ( _ Info , State ) - >
handle_info ( _ Info , State ) - >
{ ok , State } .
{ ok , State } .
terminate ( _ Reason , _ State ) - >
terminate ( _ Reason , _ State ) - >
ok .
ok .
code_change ( _ OldVsn , { state , Shaper , GLStrategy } , _ Extra ) - >
code_change ( _ OldVsn , { state , Shaper , GLStrategy } , _ Extra ) - >
Raw = application : get_env ( lager , error_logger_format_r aw, false ) ,
Raw = rumUtil : get_env ( errLoggerFormatR aw, false ) ,
{ ok , #state {
{ ok , #state {
sink = configured_s ink ( ) ,
sink = configS ink ( ) ,
shaper = Shaper ,
shaper = Shaper ,
groupleader_strategy = GLStrategy ,
groupleader_strategy = GLStrategy ,
raw = Raw
raw = Raw
} } ;
} } ;
code_change ( _ OldVsn , { state , Sink , Shaper , GLS } , _ Extra ) - >
code_change ( _ OldVsn , { state , Sink , Shaper , GLS } , _ Extra ) - >
Raw = application : get_env ( lager , error_logger_format_r aw, false ) ,
Raw = rumUtil : get_env ( errLoggerFormatR aw, false ) ,
{ ok , #state { sink = Sink , shaper = Shaper , groupleader_strategy = GLS , raw = Raw } } ;
{ ok , #state { sink = Sink , shaper = Shaper , groupleader_strategy = GLS , raw = Raw } } ;
code_change ( _ OldVsn , State , _ Extra ) - >
code_change ( _ OldVsn , State , _ Extra ) - >
{ ok , State } .
{ ok , State } .
% % internal functions
configured_sink ( ) - >
case proplists : get_value ( ? RumErrLogSink , application : get_env ( lager , extraSinks , [ ] ) ) of
configSink ( ) - >
case rumUtil : get_opt ( ? RumErrLogSink , rumUtil : get_env ( extraSinks , [ ] ) , undefined ) of
undefined - > ? RumDefSink ;
undefined - > ? RumDefSink ;
_ - > ? RumErrLogSink
_ - > ? RumErrLogSink
end .
end .
eval_gl ( Event , #state { groupleader_strategy = GlStrategy0 } = State ) when is_pid ( element ( 2 , Event ) ) - >
case element ( 2 , Event ) of
GL when node ( GL ) =/= node ( ) , GlStrategy0 =:= ignore - >
gen_event : notify ( { error_logger , node ( GL ) } , Event ) ,
{ ok , State } ;
GL when node ( GL ) =/= node ( ) , GlStrategy0 =:= mirror - >
gen_event : notify ( { error_logger , node ( GL ) } , Event ) ,
log_event ( Event , State ) ;
evalGl ( Event , #state { groupleader_strategy = GlStrategy0 } = State ) - >
GL = element ( 2 , Event ) ,
case is_pid ( GL ) andalso node ( GL ) =/= node ( ) of
true - >
case GlStrategy0 of
ignore - >
gen_event : notify ( { error_logger , node ( GL ) } , Event ) ,
{ ok , State } ;
mirror - >
gen_event : notify ( { error_logger , node ( GL ) } , Event ) ,
logEvent ( Event , State ) ;
_ - >
logEvent ( Event , State )
end ;
_ - >
_ - >
log_event ( Event , State )
end ;
eval_gl ( Event , State ) - >
log_event ( Event , State ) .
logEvent ( Event , State )
end .
log_e vent ( Event , #state { sink = Sink } = State ) - >
logEvent ( Event , #state { sink = Sink , raw = FormatRaw } = State ) - >
DidLog =
DidLog =
case Event of
case Event of
{ error , _ GL , { Pid , Fmt , Args } } - >
{ error , _ GL , { Pid , Fmt , Args } } - >
FormatRaw = State #state.raw ,
case { FormatRaw , Fmt } of
{ false , " ** Generic server " ++ _ } - >
% % gen_server terminate
{ Reason , Name } = case Args of
[ N , _ Msg , _ State , R ] - >
{ R , N } ;
[ N , _ Msg , _ State , R , _ Client ] - >
% % OTP 20 crash reports where the client pid is dead don ' t include the stacktrace
{ R , N } ;
[ N , _ Msg , _ State , R , _ Client , _ Stacktrace ] - >
% % OTP 20 crash reports contain the pid of the client and stacktrace
% % TODO do something with them
{ R , N }
end ,
? CRASH_LOG ( Event ) ,
{ Md , Formatted } = format_reason_md ( Reason ) ,
? LOGFMT ( Sink , error , [ { pid , Pid } , { name , Name } | Md ] , " gen_server ~w terminated with reason: ~s " ,
[ Name , Formatted ] ) ;
{ false , " ** State machine " ++ _ } - >
% % Check if the terminated process is gen_fsm or gen_statem
% % since they generate the same exit message
{ Type , Name , StateName , Reason } =
case Args of
[ TName , _ Msg , TStateName , _ StateData , TReason ] - >
{ gen_fsm , TName , TStateName , TReason } ;
% % Handle changed logging in gen_fsm stdlib - 3 . 9 ( TPid , ClientArgs )
[ TName , _ Msg , TPid , TStateName , _ StateData , TReason | _ ClientArgs ] when is_pid ( TPid ) , is_atom ( TStateName ) - >
{ gen_fsm , TName , TStateName , TReason } ;
% % Handle changed logging in gen_statem stdlib - 3 . 9 ( ClientArgs )
[ TName , _ Msg , { TStateName , _ StateData } , _ ExitType , TReason , _ CallbackMode , Stacktrace | _ ClientArgs ] - >
{ gen_statem , TName , TStateName , { TReason , Stacktrace } } ;
% % Handle changed logging in gen_statem stdlib - 3 . 9 ( ClientArgs )
[ TName , { TStateName , _ StateData } , _ ExitType , TReason , _ CallbackMode , Stacktrace | _ ClientArgs ] - >
{ gen_statem , TName , TStateName , { TReason , Stacktrace } } ;
[ TName , _ Msg , [ { TStateName , _ StateData } ] , _ ExitType , TReason , _ CallbackMode , Stacktrace | _ ClientArgs ] - >
% % sometimes gen_statem wraps its statename / data in a list for some reason ? ? ?
{ gen_statem , TName , TStateName , { TReason , Stacktrace } }
end ,
{ Md , Formatted } = format_reason_md ( Reason ) ,
? CRASH_LOG ( Event ) ,
? LOGFMT ( Sink , error , [ { pid , Pid } , { name , Name } | Md ] , " ~s ~w in state ~w terminated with reason: ~s " ,
[ Type , Name , StateName , Formatted ] ) ;
{ false , " ** gen_event handler " ++ _ } - >
% % gen_event handler terminate
[ ID , Name , _ Msg , _ State , Reason ] = Args ,
{ Md , Formatted } = format_reason_md ( Reason ) ,
? CRASH_LOG ( Event ) ,
? LOGFMT ( Sink , error , [ { pid , Pid } , { name , Name } | Md ] , " gen_event ~w installed in ~w terminated with reason: ~s " ,
[ ID , Name , Formatted ] ) ;
{ false , " ** Cowboy handler " ++ _ } - >
% % Cowboy HTTP server error
? CRASH_LOG ( Event ) ,
case Args of
[ Module , Function , Arity , _ Request , _ State ] - >
% % we only get the 5 - element list when its a non - exported function
? LOGFMT ( Sink , error , Pid ,
" Cowboy handler ~p terminated with reason: call to undefined function ~p : ~p / ~p " ,
[ Module , Module , Function , Arity ] ) ;
[ Module , Function , Arity , _ Class , Reason | Tail ] - >
% % any other cowboy error_format list * always * ends with the stacktrace
StackTrace = lists : last ( Tail ) ,
{ Md , Formatted } = format_reason_md ( { Reason , StackTrace } ) ,
? LOGFMT ( Sink , error , [ { pid , Pid } | Md ] ,
" Cowboy handler ~p terminated in ~p : ~p / ~p with reason: ~s " ,
[ Module , Module , Function , Arity , Formatted ] )
end ;
{ false , " Ranch listener " ++ _ } - >
% % Ranch errors
? CRASH_LOG ( Event ) ,
case Args of
% % Error logged by cowboy , which starts as ranch error
[ Ref , ConnectionPid , StreamID , RequestPid , Reason , StackTrace ] - >
{ Md , Formatted } = format_reason_md ( { Reason , StackTrace } ) ,
? LOGFMT ( Sink , error , [ { pid , RequestPid } | Md ] ,
" Cowboy stream ~p with ranch listener ~p and connection process ~p "
" had its request process exit with reason: ~s " ,
[ StreamID , Ref , ConnectionPid , Formatted ] ) ;
[ Ref , _ Protocol , Worker , { [ { reason , Reason } , { mfa , { Module , Function , Arity } } , { stacktrace , StackTrace } | _ ] , _ } ] - >
{ Md , Formatted } = format_reason_md ( { Reason , StackTrace } ) ,
? LOGFMT ( Sink , error , [ { pid , Worker } | Md ] ,
" Ranch listener ~p terminated in ~p : ~p / ~p with reason: ~s " ,
[ Ref , Module , Function , Arity , Formatted ] ) ;
[ Ref , _ Protocol , Worker , Reason ] - >
case FormatRaw of
false - >
case Fmt of
" ** Generic server " ++ _ - >
% % gen_server terminate
{ Reason , Name } =
case Args of
[ N , _ Msg , _ State , R ] - >
{ R , N } ;
[ N , _ Msg , _ State , R , _ Client ] - >
% % OTP 20 crash reports where the client pid is dead don ' t include the stacktrace
{ R , N } ;
[ N , _ Msg , _ State , R , _ Client , _ Stacktrace ] - >
% % OTP 20 crash reports contain the pid of the client and stacktrace
% % TODO do something with them
{ R , N }
end ,
? CRASH_LOG ( Event ) ,
{ Md , Formatted } = format_reason_md ( Reason ) ,
? LOGFMT ( Sink , error , [ { pid , Pid } , { name , Name } | Md ] , " gen_server ~w terminated with reason: ~s " , [ Name , Formatted ] ) ;
" ** gen_ipc State machine " ++ _ - >
% % gen_server terminate
{ Reason , Name } =
case Args of
[ N , _ Msg , _ State , R ] - >
{ R , N } ;
[ N , _ Msg , _ State , R , _ Client ] - >
% % OTP 20 crash reports where the client pid is dead don ' t include the stacktrace
{ R , N } ;
[ N , _ Msg , _ State , R , _ Client , _ Stacktrace ] - >
% % OTP 20 crash reports contain the pid of the client and stacktrace
% % TODO do something with them
{ R , N }
end ,
? CRASH_LOG ( Event ) ,
{ Md , Formatted } = format_reason_md ( Reason ) ,
? LOGFMT ( Sink , error , [ { pid , Pid } , { name , Name } | Md ] , " gen_ipc ~w terminated with reason: ~s " , [ Name , Formatted ] ) ;
" ** State machine " ++ _ - >
% % Check if the terminated process is gen_fsm or gen_statem
% % since they generate the same exit message
{ Type , Name , StateName , Reason } =
case Args of
[ TName , _ Msg , TStateName , _ StateData , TReason ] - >
{ gen_fsm , TName , TStateName , TReason } ;
% % Handle changed logging in gen_fsm stdlib - 3 . 9 ( TPid , ClientArgs )
[ TName , _ Msg , TPid , TStateName , _ StateData , TReason | _ ClientArgs ] when is_pid ( TPid ) , is_atom ( TStateName ) - >
{ gen_fsm , TName , TStateName , TReason } ;
% % Handle changed logging in gen_statem stdlib - 3 . 9 ( ClientArgs )
[ TName , _ Msg , { TStateName , _ StateData } , _ ExitType , TReason , _ CallbackMode , Stacktrace | _ ClientArgs ] - >
{ gen_statem , TName , TStateName , { TReason , Stacktrace } } ;
% % Handle changed logging in gen_statem stdlib - 3 . 9 ( ClientArgs )
[ TName , { TStateName , _ StateData } , _ ExitType , TReason , _ CallbackMode , Stacktrace | _ ClientArgs ] - >
{ gen_statem , TName , TStateName , { TReason , Stacktrace } } ;
[ TName , _ Msg , [ { TStateName , _ StateData } ] , _ ExitType , TReason , _ CallbackMode , Stacktrace | _ ClientArgs ] - >
% % sometimes gen_statem wraps its statename / data in a list for some reason ? ? ?
{ gen_statem , TName , TStateName , { TReason , Stacktrace } }
end ,
{ Md , Formatted } = format_reason_md ( Reason ) ,
? CRASH_LOG ( Event ) ,
? LOGFMT ( Sink , error , [ { pid , Pid } , { name , Name } | Md ] , " ~s ~w in state ~w terminated with reason: ~s " , [ Type , Name , StateName , Formatted ] ) ;
" ** gen_event handler " ++ _ - >
% % gen_event handler terminate
[ ID , Name , _ Msg , _ State , Reason ] = Args ,
{ Md , Formatted } = format_reason_md ( Reason ) ,
{ Md , Formatted } = format_reason_md ( Reason ) ,
? LOGFMT ( Sink , error , [ { pid , Worker } | Md ] ,
" Ranch listener ~p terminated with reason: ~s " ,
[ Ref , Formatted ] ) ;
[ Ref , Protocol , Ret ] - >
% % ranch_conns_sup . erl module line 119 - 123 has three parameters error msg , log it .
{ Md , Formatted } = format_reason_md ( Ret ) ,
? LOGFMT ( Sink , error , [ { pid , Protocol } | Md ] ,
" Ranch listener ~p terminated with result: ~s " ,
[ Ref , Formatted ] )
? CRASH_LOG ( Event ) ,
? LOGFMT ( Sink , error , [ { pid , Pid } , { name , Name } | Md ] , " gen_event ~w installed in ~w terminated with reason: ~s " , [ ID , Name , Formatted ] ) ;
" ** Cowboy handler " ++ _ - >
% % Cowboy HTTP server error
? CRASH_LOG ( Event ) ,
case Args of
[ Module , Function , Arity , _ Request , _ State ] - >
% % we only get the 5 - element list when its a non - exported function
? LOGFMT ( Sink , error , Pid ,
" Cowboy handler ~p terminated with reason: call to undefined function ~p : ~p / ~p " ,
[ Module , Module , Function , Arity ] ) ;
[ Module , Function , Arity , _ Class , Reason | Tail ] - >
% % any other cowboy error_format list * always * ends with the stacktrace
StackTrace = lists : last ( Tail ) ,
{ Md , Formatted } = format_reason_md ( { Reason , StackTrace } ) ,
? LOGFMT ( Sink , error , [ { pid , Pid } | Md ] ,
" Cowboy handler ~p terminated in ~p : ~p / ~p with reason: ~s " , [ Module , Module , Function , Arity , Formatted ] )
end ;
" Ranch listener " ++ _ - >
% % Ranch errors
? CRASH_LOG ( Event ) ,
case Args of
% % Error logged by cowboy , which starts as ranch error
[ Ref , ConnectionPid , StreamID , RequestPid , Reason , StackTrace ] - >
{ Md , Formatted } = format_reason_md ( { Reason , StackTrace } ) ,
? LOGFMT ( Sink , error , [ { pid , RequestPid } | Md ] ,
" Cowboy stream ~p with ranch listener ~p and connection process ~p "
" had its request process exit with reason: ~s " , [ StreamID , Ref , ConnectionPid , Formatted ] ) ;
[ Ref , _ Protocol , Worker , { [ { reason , Reason } , { mfa , { Module , Function , Arity } } , { stacktrace , StackTrace } | _ ] , _ } ] - >
{ Md , Formatted } = format_reason_md ( { Reason , StackTrace } ) ,
? LOGFMT ( Sink , error , [ { pid , Worker } | Md ] , " Ranch listener ~p terminated in ~p : ~p / ~p with reason: ~s " , [ Ref , Module , Function , Arity , Formatted ] ) ;
[ Ref , _ Protocol , Worker , Reason ] - >
{ Md , Formatted } = format_reason_md ( Reason ) ,
? LOGFMT ( Sink , error , [ { pid , Worker } | Md ] , " Ranch listener ~p terminated with reason: ~s " , [ Ref , Formatted ] ) ;
[ Ref , Protocol , Ret ] - >
% % ranch_conns_sup . erl module line 119 - 123 has three parameters error msg , log it .
{ Md , Formatted } = format_reason_md ( Ret ) ,
? LOGFMT ( Sink , error , [ { pid , Protocol } | Md ] , " Ranch listener ~p terminated with result: ~s " , [ Ref , Formatted ] )
end ;
" webmachine error " ++ _ - >
% % Webmachine HTTP server error
? CRASH_LOG ( Event ) ,
[ Path , Error ] = Args ,
% % webmachine likes to mangle the stack , for some reason
StackTrace =
case Error of
{ error , { error , Reason , Stack } } - >
{ Reason , Stack } ;
_ - >
Error
end ,
{ Md , Formatted } = format_reason_md ( StackTrace ) ,
? LOGFMT ( Sink , error , [ { pid , Pid } | Md ] , " Webmachine error at path ~p : ~s " , [ Path , Formatted ] )
end ;
end ;
{ false , " webmachine error " ++ _ } - >
% % Webmachine HTTP server error
? CRASH_LOG ( Event ) ,
[ Path , Error ] = Args ,
% % webmachine likes to mangle the stack , for some reason
StackTrace = case Error of
{ error , { error , Reason , Stack } } - >
{ Reason , Stack } ;
_ - >
Error
end ,
{ Md , Formatted } = format_reason_md ( StackTrace ) ,
? LOGFMT ( Sink , error , [ { pid , Pid } | Md ] , " Webmachine error at path ~p : ~s " , [ Path , Formatted ] ) ;
_ - >
_ - >
? CRASH_LOG ( Event ) ,
? CRASH_LOG ( Event ) ,
? LOGFMT ( Sink , error , Pid , Fmt , Args )
? LOGFMT ( Sink , error , Pid , Fmt , Args )
@ -306,7 +326,7 @@ log_event(Event, #state{sink = Sink} = State) ->
Details = lists : sort ( D ) ,
Details = lists : sort ( D ) ,
case Details of
case Details of
[ { application , App } , { exited , Reason } , { type , _ Type } ] - >
[ { application , App } , { exited , Reason } , { type , _ Type } ] - >
case application : get_env ( lager , suppress_application_start_stop , false ) of
case rumUtil : get_env ( suppress_application_start_stop , false ) of
true when Reason == stopped - >
true when Reason == stopped - >
no_log ;
no_log ;
_ - >
_ - >
@ -323,7 +343,7 @@ log_event(Event, #state{sink = Sink} = State) ->
Details = lists : sort ( D ) ,
Details = lists : sort ( D ) ,
case Details of
case Details of
[ { application , App } , { started_at , Node } ] - >
[ { application , App } , { started_at , Node } ] - >
case application : get_env ( lager , suppress_application_start_stop , false ) of
case rumUtil : get_env ( suppress_application_start_stop , false ) of
true - >
true - >
no_log ;
no_log ;
_ - >
_ - >
@ -331,7 +351,7 @@ log_event(Event, #state{sink = Sink} = State) ->
[ App , Node ] )
[ App , Node ] )
end ;
end ;
[ { started , Started } , { supervisor , Name } ] - >
[ { started , Started } , { supervisor , Name } ] - >
case application : get_env ( lager , suppress_supervisor_start_stop , false ) of
case rumUtil : get_env ( suppress_supervisor_start_stop , false ) of
true - >
true - >
no_log ;
no_log ;
_ - >
_ - >
@ -351,12 +371,7 @@ log_event(Event, #state{sink = Sink} = State) ->
{ ok , State } ;
{ ok , State } ;
no_log - >
no_log - >
Shaper = State #state.shaper ,
Shaper = State #state.shaper ,
{ ok , State #state {
shaper = Shaper #rumShaper {
mps = Shaper #rumShaper.mps - 1
}
}
}
{ ok , State #state { shaper = Shaper #rumShaper { mps = Shaper #rumShaper.mps - 1 } } }
end .
end .
format_crash_report ( Report , Neighbours ) - >
format_crash_report ( Report , Neighbours ) - >
@ -379,12 +394,8 @@ format_crash_report(Report, Neighbours) ->
{ Class , Reason , Trace } = get_value ( error_info , Report ) ,
{ Class , Reason , Trace } = get_value ( error_info , Report ) ,
{ Md , ReasonStr } = format_reason_md ( { Reason , Trace } ) ,
{ Md , ReasonStr } = format_reason_md ( { Reason , Trace } ) ,
Type = case Class of
exit - > " exited " ;
_ - > " crashed "
end ,
{ Md0 ++ Md , io_lib : format ( " Process ~w with ~w neighbours ~s with reason: ~s " ,
[ Name , length ( Neighbours ) , Type , ReasonStr ] ) } .
Type = ? IIF ( Class == exit , < < " exited " > > , < < " crashed " > > ) ,
{ Md0 ++ Md , eFmt : formatBin ( " Process ~w with ~w neighbours ~s with reason: ~s " , [ Name , length ( Neighbours ) , Type , ReasonStr ] ) } .
format_offender ( Off ) - >
format_offender ( Off ) - >
case get_value ( mfargs , Off ) of
case get_value ( mfargs , Off ) of
@ -416,80 +427,64 @@ format_reason(Reason) ->
format_reason_md ( { 'function not exported' , [ { M , F , A } , MFA | _ ] } ) - >
format_reason_md ( { 'function not exported' , [ { M , F , A } , MFA | _ ] } ) - >
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ _ , Formatted2 } = format_mfa_md ( { M , F , length ( A ) } ) ,
{ _ , Formatted2 } = format_mfa_md ( { M , F , length ( A ) } ) ,
{ [ { reason , 'function not exported' } | Md ] ,
[ " call to undefined function " , Formatted2 ,
" from " , Formatted ] } ;
{ [ { reason , 'function not exported' } | Md ] , [ " call to undefined function " , Formatted2 , " from " , Formatted ] } ;
format_reason_md ( { 'function not exported' , [ { M , F , A , _ Props } , MFA | _ ] } ) - >
format_reason_md ( { 'function not exported' , [ { M , F , A , _ Props } , MFA | _ ] } ) - >
% % R15 line numbers
% % R15 line numbers
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ _ , Formatted2 } = format_mfa_md ( { M , F , length ( A ) } ) ,
{ _ , Formatted2 } = format_mfa_md ( { M , F , length ( A ) } ) ,
{ [ { reason , 'function not exported' } | Md ] ,
[ " call to undefined function " , Formatted2 ,
" from " , Formatted ] } ;
{ [ { reason , 'function not exported' } | Md ] , [ " call to undefined function " , Formatted2 , " from " , Formatted ] } ;
format_reason_md ( { undef , [ MFA | _ ] } ) - >
format_reason_md ( { undef , [ MFA | _ ] } ) - >
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ [ { reason , undef } | Md ] ,
[ " call to undefined function " , Formatted ] } ;
{ [ { reason , undef } | Md ] , [ " call to undefined function " , Formatted ] } ;
format_reason_md ( { bad_return , { _ MFA , { 'EXIT' , Reason } } } ) - >
format_reason_md ( { bad_return , { _ MFA , { 'EXIT' , Reason } } } ) - >
format_reason_md ( Reason ) ;
format_reason_md ( Reason ) ;
format_reason_md ( { bad_return , { MFA , Val } } ) - >
format_reason_md ( { bad_return , { MFA , Val } } ) - >
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ [ { reason , bad_return } | Md ] ,
[ " bad return value " , print_val ( Val ) , " from " , Formatted ] } ;
{ [ { reason , bad_return } | Md ] , [ " bad return value " , print_val ( Val ) , " from " , Formatted ] } ;
format_reason_md ( { bad_return_value , Val } ) - >
format_reason_md ( { bad_return_value , Val } ) - >
{ [ { reason , bad_return } ] ,
[ " bad return value: " , print_val ( Val ) ] } ;
{ [ { reason , bad_return } ] , [ " bad return value: " , print_val ( Val ) ] } ;
format_reason_md ( { { bad_return_value , Val } , MFA } ) - >
format_reason_md ( { { bad_return_value , Val } , MFA } ) - >
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ [ { reason , bad_return_value } | Md ] ,
[ " bad return value: " , print_val ( Val ) , " in " , Formatted ] } ;
{ [ { reason , bad_return_value } | Md ] , [ " bad return value: " , print_val ( Val ) , " in " , Formatted ] } ;
format_reason_md ( { { badrecord , Record } , [ MFA | _ ] } ) - >
format_reason_md ( { { badrecord , Record } , [ MFA | _ ] } ) - >
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ [ { reason , badrecord } | Md ] ,
[ " bad record " , print_val ( Record ) , " in " , Formatted ] } ;
{ [ { reason , badrecord } | Md ] , [ " bad record " , print_val ( Record ) , " in " , Formatted ] } ;
format_reason_md ( { { case_clause , Val } , [ MFA | _ ] } ) - >
format_reason_md ( { { case_clause , Val } , [ MFA | _ ] } ) - >
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ [ { reason , case_clause } | Md ] ,
[ " no case clause matching " , print_val ( Val ) , " in " , Formatted ] } ;
{ [ { reason , case_clause } | Md ] , [ " no case clause matching " , print_val ( Val ) , " in " , Formatted ] } ;
format_reason_md ( { function_clause , [ MFA | _ ] } ) - >
format_reason_md ( { function_clause , [ MFA | _ ] } ) - >
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ [ { reason , function_clause } | Md ] ,
[ " no function clause matching " , Formatted ] } ;
{ [ { reason , function_clause } | Md ] , [ " no function clause matching " , Formatted ] } ;
format_reason_md ( { if_clause , [ MFA | _ ] } ) - >
format_reason_md ( { if_clause , [ MFA | _ ] } ) - >
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ [ { reason , if_clause } | Md ] ,
[ " no true branch found while evaluating if expression in " , Formatted ] } ;
{ [ { reason , if_clause } | Md ] , [ " no true branch found while evaluating if expression in " , Formatted ] } ;
format_reason_md ( { { try_clause , Val } , [ MFA | _ ] } ) - >
format_reason_md ( { { try_clause , Val } , [ MFA | _ ] } ) - >
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ [ { reason , try_clause } | Md ] ,
[ " no try clause matching " , print_val ( Val ) , " in " , Formatted ] } ;
{ [ { reason , try_clause } | Md ] , [ " no try clause matching " , print_val ( Val ) , " in " , Formatted ] } ;
format_reason_md ( { badarith , [ MFA | _ ] } ) - >
format_reason_md ( { badarith , [ MFA | _ ] } ) - >
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ [ { reason , badarith } | Md ] ,
[ " bad arithmetic expression in " , Formatted ] } ;
{ [ { reason , badarith } | Md ] , [ " bad arithmetic expression in " , Formatted ] } ;
format_reason_md ( { { badmatch , Val } , [ MFA | _ ] } ) - >
format_reason_md ( { { badmatch , Val } , [ MFA | _ ] } ) - >
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ [ { reason , badmatch } | Md ] ,
[ " no match of right hand value " , print_val ( Val ) , " in " , Formatted ] } ;
{ [ { reason , badmatch } | Md ] , [ " no match of right hand value " , print_val ( Val ) , " in " , Formatted ] } ;
format_reason_md ( { emfile , _ Trace } ) - >
format_reason_md ( { emfile , _ Trace } ) - >
{ [ { reason , emfile } ] ,
" maximum number of file descriptors exhausted, check ulimit -n " } ;
{ [ { reason , emfile } ] , " maximum number of file descriptors exhausted, check ulimit -n " } ;
format_reason_md ( { system_limit , [ { M , F , _ } | _ ] = Trace } ) - >
format_reason_md ( { system_limit , [ { M , F , _ } | _ ] = Trace } ) - >
Limit = case { M , F } of
{ erlang , open_port } - >
" maximum number of ports exceeded " ;
{ erlang , spawn } - > ;
" maximum number of processes exceeded " ;
{ erlang , spawn_opt } - > ;
" maximum number of processes exceeded " ;
{ erlang , list_to_atom } - > ;
" tried to create an atom larger than 255, or maximum atom count exceeded " ;
{ ets , new } - > ;
" maximum number of ETS tables exceeded " ;
_ - > ;
{ Str , _ } = rumTruncIo : print ( Trace , 500 ) ,
Str
end ,
Limit =
case { M , F } of
{ erlang , open_port } - > ;
< < " maximum number of ports exceeded " > > ;
{ erlang , spawn } - > ;
< < " maximum number of processes exceeded " > > ;
{ erlang , spawn_opt } - > ;
< < " maximum number of processes exceeded " > > ;
{ erlang , list_to_atom } - > ;
< < " tried to create an atom larger than 255, or maximum atom count exceeded " > > ;
{ ets , new } - > ;
< < " maximum number of ETS tables exceeded " > > ;
_ - >
eFmt : formatBin ( < < " ~p " > > , [ Trace ] , [ { charsLimit , 500 } ] )
end ,
{ [ { reason , system_limit } ] , [ " system limit: " , Limit ] } ;
{ [ { reason , system_limit } ] , [ " system limit: " , Limit ] } ;
format_reason_md ( { badarg , [ MFA , MFA2 | _ ] } ) - >
format_reason_md ( { badarg , [ MFA , MFA2 | _ ] } ) - >
case MFA of
case MFA of
@ -624,7 +619,7 @@ no_silent_hwm_drops_test_() ->
application : set_env ( lager , handlers , [ { lager_test_backend , warning } ] ) ,
application : set_env ( lager , handlers , [ { lager_test_backend , warning } ] ) ,
application : set_env ( lager , errLoggerRedirect , true ) ,
application : set_env ( lager , errLoggerRedirect , true ) ,
application : set_env ( lager , errLoggerHwm , 5 ) ,
application : set_env ( lager , errLoggerHwm , 5 ) ,
application : set_env ( lager , error_logger_flush_q ueue , false ) ,
application : set_env ( lager , errLoggerFlushQ ueue , false ) ,
application : set_env ( lager , suppress_supervisor_start_stop , true ) ,
application : set_env ( lager , suppress_supervisor_start_stop , true ) ,
application : set_env ( lager , suppress_application_start_stop , true ) ,
application : set_env ( lager , suppress_application_start_stop , true ) ,
application : unset_env ( lager , crash_log ) ,
application : unset_env ( lager , crash_log ) ,