@ -148,20 +148,23 @@ log_event(Event, #state{sink=Sink} = State) ->
% % gen_server terminate
[ Name , _ Msg , _ State , Reason ] = Args ,
? CRASH_LOG ( Event ) ,
? LOGFMT ( Sink , error , Pid , " gen_server ~w terminated with reason: ~s " ,
[ Name , format_reason ( Reason ) ] ) ;
{ 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 " ++ _ } - >
% % gen_fsm terminate
[ Name , _ Msg , StateName , _ StateData , Reason ] = Args ,
{ Md , Formatted } = format_reason_md ( Reason ) ,
? CRASH_LOG ( Event ) ,
? LOGFMT ( Sink , error , Pid , " gen_fsm ~w in state ~w terminated with reason: ~s " ,
[ Name , StateName , format_reason ( Reason ) ] ) ;
? LOGFMT ( Sink , error , [ { pid , Pid } , { name , Name } | Md ] , " gen_fsm ~w in state ~w terminated with reason: ~s " ,
[ 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 , " gen_event ~w installed in ~w terminated with reason: ~s " ,
[ ID , Name , format_reason ( Reason ) ] ) ;
? 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 ) ,
@ -174,27 +177,31 @@ log_event(Event, #state{sink=Sink} = State) ->
[ Module , Function , Arity , _ Class , Reason | Tail ] - >
% % any other cowboy error_format list * always * ends with the stacktrace
StackTrace = lists : last ( Tail ) ,
? LOGFMT ( Sink , error , Pid ,
{ 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 , format_reason ( { Reason , StackTrace } ) ] )
[ Module , Module , Function , Arity , Formatted ] )
end ;
{ false , " Ranch listener " ++ _ } - >
% % Ranch errors
? CRASH_LOG ( Event ) ,
case Args of
[ Ref , _ Protocol , Worker , { [ { reason , Reason } , { mfa , { Module , Function , Arity } } , { stacktrace , StackTrace } | _ ] , _ } ] - >
? LOGFMT ( Sink , error , Worker ,
{ 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 , format_reason ( { Reason , StackTrace } ) ] ) ;
[ Ref , Module , Function , Arity , Formatted ] ) ;
[ Ref , _ Protocol , Worker , Reason ] - >
? LOGFMT ( Sink , error , Worker ,
{ Md , Formatted } = format_reason_md ( Reason ) ,
? LOGFMT ( Sink , error , [ { pid , Worker } | Md ] ,
" Ranch listener ~p terminated with reason: ~s " ,
[ Ref , format_reason ( Reason ) ] ) ;
[ Ref , Formatted ] ) ;
[ Ref , Protocol , Ret ] - >
% % ranch_conns_sup . erl module line 119 - 123 has three parameters error msg , log it .
? LOGFMT ( Sink , error , Protocol ,
{ Md , Formatted } = format_reason_md ( Ret ) ,
? LOGFMT ( Sink , error , [ { pid , Protocol } | Md ] ,
" Ranch listener ~p terminated with result: ~s " ,
[ Ref , format_reason ( Ret ) ] )
[ Ref , Formatted ] )
end ;
{ false , " webmachine error " ++ _ } - >
% % Webmachine HTTP server error
@ -207,7 +214,8 @@ log_event(Event, #state{sink=Sink} = State) ->
_ - >
Error
end ,
? LOGFMT ( Sink , error , Pid , " Webmachine error at path ~p : ~s " , [ Path , format_reason ( StackTrace ) ] ) ;
{ Md , Formatted } = format_reason_md ( StackTrace ) ,
? LOGFMT ( Sink , error , [ { pid , Pid } | Md ] , " Webmachine error at path ~p : ~s " , [ Path , Formatted ] ) ;
_ - >
? CRASH_LOG ( Event ) ,
? LOGFMT ( Sink , error , Pid , Fmt , Args )
@ -220,15 +228,17 @@ log_event(Event, #state{sink=Sink} = State) ->
case lists : sort ( D ) of
[ { errorContext , Ctx } , { offender , Off } , { reason , Reason } , { supervisor , Name } ] - >
Offender = format_offender ( Off ) ,
? LOGFMT ( Sink , error , Pid ,
{ Md , Formatted } = format_reason_md ( Reason ) ,
? LOGFMT ( Sink , error , [ { pid , Pid } | Md ] ,
" Supervisor ~w had child ~s exit with reason ~s in context ~w " ,
[ supervisor_name ( Name ) , Offender , format_reason ( Reason ) , Ctx ] ) ;
[ supervisor_name ( Name ) , Offender , Formatted , Ctx ] ) ;
_ - >
? LOGMSG ( Sink , error , Pid , " SUPERVISOR REPORT " ++ print_silly_list ( D ) )
end ;
{ error_report , _ GL , { Pid , crash_report , [ Self , Neighbours ] } } - >
? CRASH_LOG ( Event ) ,
? LOGMSG ( Sink , error , Pid , " CRASH REPORT " ++ format_crash_report ( Self , Neighbours ) ) ;
{ Md , Formatted } = format_crash_report ( Self , Neighbours ) ,
? LOGMSG ( Sink , error , [ { pid , Pid } | Md ] , " CRASH REPORT " ++ Formatted ) ;
{ warning_msg , _ GL , { Pid , Fmt , Args } } - >
? LOGFMT ( Sink , warning , Pid , Fmt , Args ) ;
{ warning_report , _ GL , { Pid , std_warning , Report } } - >
@ -243,8 +253,9 @@ log_event(Event, #state{sink=Sink} = State) ->
{ ok , true } when Reason == stopped - >
ok ;
_ - >
? LOGFMT ( Sink , info , Pid , " Application ~w exited with reason: ~s " ,
[ App , format_reason ( Reason ) ] )
{ Md , Formatted } = format_reason_md ( Reason ) ,
? LOGFMT ( Sink , info , [ { pid , Pid } | Md ] , " Application ~w exited with reason: ~s " ,
[ App , Formatted ] )
end ;
_ - >
? LOGMSG ( Sink , info , Pid , print_silly_list ( D ) )
@ -287,14 +298,23 @@ format_crash_report(Report, Neighbours) ->
get_value ( pid , Report ) ;
Atom - > Atom
end ,
Md0 = case get_value ( dictionary , Report , [ ] ) of
[ ] - >
% % process_info ( Pid , registered_name ) returns [ ] for unregistered processes
[ ] ;
Dict - >
% % pull the lager metadata out of the process dictionary , if we can
get_value ( '_lager_metadata' , Dict , [ ] )
end ,
{ Class , Reason , Trace } = get_value ( error_info , Report ) ,
ReasonStr = format_reason ( { Reason , Trace } ) ,
{ Md , ReasonStr } = format_reason_md ( { Reason , Trace } ) ,
Type = case Class of
exit - > " exited " ;
_ - > " crashed "
end ,
io_lib : format ( " Process ~w with ~w neighbours ~s with reason: ~s " ,
[ Name , length ( Neighbours ) , Type , ReasonStr ] ) .
{ Md0 ++ Md , io_lib : format ( " Process ~w with ~w neighbours ~s with reason: ~s " ,
[ Name , length ( Neighbours ) , Type , ReasonStr ] ) } .
format_offender ( Off ) - >
case get_value ( mfargs , Off ) of
@ -304,7 +324,7 @@ format_offender(Off) ->
[ get_value ( mod , Off ) , get_value ( pid , Off ) ] ) ;
MFArgs - >
% % regular supervisor
MFA = format_mfa ( MFArgs ) ,
{ _ , MFA } = format_mfa_md ( MFArgs ) ,
% % In 2014 the error report changed from ` name ' to
% % ` id ' , so try that first .
@ -318,40 +338,73 @@ format_offender(Off) ->
[ Name , MFA , get_value ( pid , Off ) ] )
end .
format_reason ( { 'function not exported' , [ { M , F , A } , MFA | _ ] } ) - >
[ " call to undefined function " , format_mfa ( { M , F , length ( A ) } ) ,
" from " , format_mfa ( MFA ) ] ;
format_reason ( { 'function not exported' , [ { M , F , A , _ Props } , MFA | _ ] } ) - >
% % backwards compatability shim
format_reason ( Reason ) - >
element ( 2 , format_reason_md ( Reason ) ) .
- spec format_reason_md ( Stacktrace : : any ( ) ) - > { Metadata : : [ { atom ( ) , any ( ) } ] , String : : list ( ) } .
format_reason_md ( { 'function not exported' , [ { M , F , A } , MFA | _ ] } ) - >
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ _ , Formatted2 } = format_mfa_md ( { M , F , length ( A ) } ) ,
{ [ { reason , 'function not exported' } | Md ] ,
[ " call to undefined function " , Formatted2 ,
" from " , Formatted ] } ;
format_reason_md ( { 'function not exported' , [ { M , F , A , _ Props } , MFA | _ ] } ) - >
% % R15 line numbers
[ " call to undefined function " , format_mfa ( { M , F , length ( A ) } ) ,
" from " , format_mfa ( MFA ) ] ;
format_reason ( { undef , [ MFA | _ ] } ) - >
[ " call to undefined function " , format_mfa ( MFA ) ] ;
format_reason ( { bad_return , { _ MFA , { 'EXIT' , Reason } } } ) - >
format_reason ( Reason ) ;
format_reason ( { bad_return , { MFA , Val } } ) - >
[ " bad return value " , print_val ( Val ) , " from " , format_mfa ( MFA ) ] ;
format_reason ( { bad_return_value , Val } ) - >
[ " bad return value: " , print_val ( Val ) ] ;
format_reason ( { { bad_return_value , Val } , MFA } ) - >
[ " bad return value: " , print_val ( Val ) , " in " , format_mfa ( MFA ) ] ;
format_reason ( { { badrecord , Record } , [ MFA | _ ] } ) - >
[ " bad record " , print_val ( Record ) , " in " , format_mfa ( MFA ) ] ;
format_reason ( { { case_clause , Val } , [ MFA | _ ] } ) - >
[ " no case clause matching " , print_val ( Val ) , " in " , format_mfa ( MFA ) ] ;
format_reason ( { function_clause , [ MFA | _ ] } ) - >
[ " no function clause matching " , format_mfa ( MFA ) ] ;
format_reason ( { if_clause , [ MFA | _ ] } ) - >
[ " no true branch found while evaluating if expression in " , format_mfa ( MFA ) ] ;
format_reason ( { { try_clause , Val } , [ MFA | _ ] } ) - >
[ " no try clause matching " , print_val ( Val ) , " in " , format_mfa ( MFA ) ] ;
format_reason ( { badarith , [ MFA | _ ] } ) - >
[ " bad arithmetic expression in " , format_mfa ( MFA ) ] ;
format_reason ( { { badmatch , Val } , [ MFA | _ ] } ) - >
[ " no match of right hand value " , print_val ( Val ) , " in " , format_mfa ( MFA ) ] ;
format_reason ( { emfile , _ Trace } ) - >
" maximum number of file descriptors exhausted, check ulimit -n " ;
format_reason ( { system_limit , [ { M , F , _ } | _ ] = Trace } ) - >
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ _ , Formatted2 } = format_mfa_md ( { M , F , length ( A ) } ) ,
{ [ { reason , 'function not exported' } | Md ] ,
[ " call to undefined function " , Formatted2 ,
" from " , Formatted ] } ;
format_reason_md ( { undef , [ MFA | _ ] } ) - >
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ [ { reason , undef } | Md ] ,
[ " call to undefined function " , Formatted ] } ;
format_reason_md ( { bad_return , { _ MFA , { 'EXIT' , Reason } } } ) - >
format_reason_md ( Reason ) ;
format_reason_md ( { bad_return , { MFA , Val } } ) - >
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ [ { reason , bad_return } | Md ] ,
[ " bad return value " , print_val ( Val ) , " from " , Formatted ] } ;
format_reason_md ( { bad_return_value , Val } ) - >
{ [ { reason , bad_return } ] ,
[ " bad return value: " , print_val ( Val ) ] } ;
format_reason_md ( { { bad_return_value , Val } , MFA } ) - >
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ [ { reason , bad_return_value } | Md ] ,
[ " bad return value: " , print_val ( Val ) , " in " , Formatted ] } ;
format_reason_md ( { { badrecord , Record } , [ MFA | _ ] } ) - >
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ [ { reason , badrecord } | Md ] ,
[ " bad record " , print_val ( Record ) , " in " , Formatted ] } ;
format_reason_md ( { { case_clause , Val } , [ MFA | _ ] } ) - >
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ [ { reason , case_clause } | Md ] ,
[ " no case clause matching " , print_val ( Val ) , " in " , Formatted ] } ;
format_reason_md ( { function_clause , [ MFA | _ ] } ) - >
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ [ { reason , function_clause } | Md ] ,
[ " no function clause matching " , Formatted ] } ;
format_reason_md ( { if_clause , [ MFA | _ ] } ) - >
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ [ { reason , if_clause } | Md ] ,
[ " no true branch found while evaluating if expression in " , Formatted ] } ;
format_reason_md ( { { try_clause , Val } , [ MFA | _ ] } ) - >
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ [ { reason , try_clause } | Md ] ,
[ " no try clause matching " , print_val ( Val ) , " in " , Formatted ] } ;
format_reason_md ( { badarith , [ MFA | _ ] } ) - >
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ [ { reason , badarith } | Md ] ,
[ " bad arithmetic expression in " , Formatted ] } ;
format_reason_md ( { { badmatch , Val } , [ MFA | _ ] } ) - >
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ [ { reason , badmatch } | Md ] ,
[ " no match of right hand value " , print_val ( Val ) , " in " , Formatted ] } ;
format_reason_md ( { emfile , _ Trace } ) - >
{ [ { reason , emfile } ] ,
" maximum number of file descriptors exhausted, check ulimit -n " } ;
format_reason_md ( { system_limit , [ { M , F , _ } | _ ] = Trace } ) - >
Limit = case { M , F } of
{ erlang , open_port } - >
" maximum number of ports exceeded " ;
@ -367,57 +420,81 @@ format_reason({system_limit, [{M, F, _}|_] = Trace}) ->
{ Str , _ } = lager_trunc_io : print ( Trace , 500 ) ,
Str
end ,
[ " system limit: " , Limit ] ;
format_reason ( { badarg , [ MFA , MFA2 | _ ] } ) - >
{ [ { reason , system_limit } ] , [" system limit: " , Limit ] } ;
format_reason_md ( { badarg , [ MFA , MFA2 | _ ] } ) - >
case MFA of
{ _ M , _ F , A , _ Props } when is_list ( A ) - >
% % R15 line numbers
[ " bad argument in call to " , format_mfa ( MFA ) , " in " , format_mfa ( MFA2 ) ] ;
{ Md , Formatted } = format_mfa_md ( MFA2 ) ,
{ _ , Formatted2 } = format_mfa_md ( MFA ) ,
{ [ { reason , badarg } | Md ] ,
[ " bad argument in call to " , Formatted2 , " in " , Formatted ] } ;
{ _ M , _ F , A } when is_list ( A ) - >
[ " bad argument in call to " , format_mfa ( MFA ) , " in " , format_mfa ( MFA2 ) ] ;
{ Md , Formatted } = format_mfa_md ( MFA2 ) ,
{ _ , Formatted2 } = format_mfa_md ( MFA ) ,
{ [ { reason , badarg } | Md ] ,
[ " bad argument in call to " , Formatted2 , " in " , Formatted ] } ;
_ - >
% % seems to be generated by a bad call to a BIF
[ " bad argument in " , format_mfa ( MFA ) ]
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ [ { reason , badarg } | Md ] ,
[ " bad argument in " , Formatted ] }
end ;
format_reason ( { { badarg , Stack } , _ } ) - >
format_reason ( { badarg , Stack } ) ;
format_reason ( { { badarity , { Fun , Args } } , [ MFA | _ ] } ) - >
format_reason_md ( { { badarg , Stack } , _ } ) - >
format_reason_md ( { badarg , Stack } ) ;
format_reason_md ( { { badarity , { Fun , Args } } , [ MFA | _ ] } ) - >
{ arity , Arity } = lists : keyfind ( arity , 1 , erlang : fun_info ( Fun ) ) ,
[ io_lib : format ( " fun called with wrong arity of ~w instead of ~w in " ,
[ length ( Args ) , Arity ] ) , format_mfa ( MFA ) ] ;
format_reason ( { noproc , MFA } ) - >
[ " no such process or port in call to " , format_mfa ( MFA ) ] ;
format_reason ( { { badfun , Term } , [ MFA | _ ] } ) - >
[ " bad function " , print_val ( Term ) , " in " , format_mfa ( MFA ) ] ;
format_reason ( { Reason , [ { M , F , A } | _ ] } ) when is_atom ( M ) , is_atom ( F ) , is_integer ( A ) - >
[ format_reason ( Reason ) , " in " , format_mfa ( { M , F , A } ) ] ;
format_reason ( { Reason , [ { M , F , A , Props } | _ ] } ) when is_atom ( M ) , is_atom ( F ) , is_integer ( A ) , is_list ( Props ) - >
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ [ { reason , badarity } | Md ] ,
[ io_lib : format ( " fun called with wrong arity of ~w instead of ~w in " ,
[ length ( Args ) , Arity ] ) , Formatted ] } ;
format_reason_md ( { noproc , MFA } ) - >
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ [ { reason , badarity } | Md ] ,
[ " no such process or port in call to " , Formatted ] } ;
format_reason_md ( { { badfun , Term } , [ MFA | _ ] } ) - >
{ Md , Formatted } = format_mfa_md ( MFA ) ,
{ [ { reason , badfun } | Md ] ,
[ " bad function " , print_val ( Term ) , " in " , Formatted ] } ;
format_reason_md ( { Reason , [ { M , F , A } | _ ] } ) when is_atom ( M ) , is_atom ( F ) , is_integer ( A ) - >
{ Md , Formatted } = format_reason_md ( Reason ) ,
{ _ , Formatted2 } = format_mfa_md ( { M , F , A } ) ,
{ Md , [ Formatted , " in " , Formatted2 ] } ;
format_reason_md ( { Reason , [ { M , F , A , Props } | _ ] } ) when is_atom ( M ) , is_atom ( F ) , is_integer ( A ) , is_list ( Props ) - >
% % line numbers
[ format_reason ( Reason ) , " in " , format_mfa ( { M , F , A , Props } ) ] ;
format_reason ( Reason ) - >
{ Md , Formatted } = format_reason_md ( Reason ) ,
{ _ , Formatted2 } = format_mfa_md ( { M , F , A , Props } ) ,
{ Md , [ Formatted , " in " , Formatted2 ] } ;
format_reason_md ( Reason ) - >
{ Str , _ } = lager_trunc_io : print ( Reason , 500 ) ,
Str .
{ [ ] , Str } .
% % backwards compatability shim
format_mfa ( MFA ) - >
element ( 2 , format_mfa_md ( MFA ) ) .
format_mfa ( { M , F , A } ) when is_list ( A ) - >
- spec format_mfa_md ( any ( ) ) - > { [ { atom ( ) , any ( ) } ] , list ( ) } .
format_mfa_md ( { M , F , A } ) when is_list ( A ) - >
{ FmtStr , Args } = format_args ( A , [ ] , [ ] ) ,
io_lib : format ( " ~w : ~w ( " ++ FmtStr ++ " ) " , [ M , F | Args ] ) ;
format_mfa ( { M , F , A } ) when is_integer ( A ) - >
io_lib : format ( " ~w : ~w / ~w " , [ M , F , A ] ) ;
format_mfa ( { M , F , A , Props } ) when is_list ( Props ) - >
{ [ { module , M } , { function , F } ] , io_lib : format ( " ~w : ~w ( " ++ FmtStr ++ " ) " , [ M , F | Args ] ) } ;
format_mfa_md ( { M , F , A } ) when is_integer ( A ) - >
{ [ { module , M } , { function , F } ] , io_lib : format ( " ~w : ~w / ~w " , [ M , F , A ] ) } ;
format_mfa_md ( { M , F , A , Props } ) when is_list ( Props ) - >
case get_value ( line , Props ) of
undefined - >
format_mfa ( { M , F , A } ) ;
format_mfa_md ( { M , F , A } ) ;
Line - >
[ format_mfa ( { M , F , A } ) , io_lib : format ( " line ~w " , [ Line ] ) ]
{ Md , Formatted } = format_mfa_md ( { M , F , A } ) ,
{ [ { line , Line } | Md ] , [ Formatted , io_lib : format ( " line ~w " , [ Line ] ) ] }
end ;
format_mfa ( [ { M , F , A } , _ ] ) - >
format_mfa_md ( [ { M , F , A } , _ ] ) - >
% % this kind of weird stacktrace can be generated by a uncaught throw in a gen_server
format_mfa ( { M , F , A } ) ;
format_mfa ( [ { M , F , A , Props } , _ ] ) when is_list ( Props ) - >
format_mfa_md ( { M , F , A } ) ;
format_mfa_md ( [ { M , F , A , Props } , _ ] ) when is_list ( Props ) - >
% % this kind of weird stacktrace can be generated by a uncaught throw in a gen_server
format_mfa ( { M , F , A , Props } ) ;
format_mfa ( Other ) - >
io_lib : format ( " ~w " , [ Other ] ) .
format_mfa_md ( { M , F , A , Props } ) ;
format_mfa_md ( Other ) - >
{ [ ] , io_lib : format ( " ~w " , [ Other ] ) } .
format_args ( [ ] , FmtAcc , ArgsAcc ) - >
{ string : join ( lists : reverse ( FmtAcc ) , " , " ) , lists : reverse ( ArgsAcc ) } ;