11defmodule Logger.ErrorHandler do
22 @ moduledoc false
3-
43 @ behaviour :gen_event
54
6- require Logger
7-
85 def init ( { otp? , sasl? , threshold } ) do
96 # We store the Logger PID in the state because when we are shutting
107 # down the Logger application, the Logger process may be terminated
@@ -14,11 +11,10 @@ defmodule Logger.ErrorHandler do
1411 state = % {
1512 otp: otp? ,
1613 sasl: sasl? ,
17- threshold: threshold ,
14+ discard_threshold: threshold ,
15+ keep_threshold: trunc ( threshold * 0.75 ) ,
1816 logger: Process . whereis ( Logger ) ,
19- last_length: 0 ,
20- last_time: :os . timestamp ( ) ,
21- dropped: 0
17+ skip: 0
2218 }
2319
2420 { :ok , state }
@@ -31,7 +27,7 @@ defmodule Logger.ErrorHandler do
3127 end
3228
3329 def handle_event ( event , state ) do
34- state = check_threshold ( state )
30+ state = check_threshold_unless_skipping ( state )
3531 log_event ( event , state )
3632 { :ok , state }
3733 end
@@ -84,10 +80,15 @@ defmodule Logger.ErrorHandler do
8480 defp log_event ( _ , _state ) , do: :ok
8581
8682 defp log_event ( level , kind , gl , pid , { type , _ } = data , state ) do
87- % { level: min_level , truncate: truncate , utc_log: utc_log? , translators: translators } =
88- Logger.Config . __data__ ( )
89-
90- with log when log != :lt <- Logger . compare_levels ( level , min_level ) ,
83+ % {
84+ mode: mode ,
85+ level: min_level ,
86+ truncate: truncate ,
87+ utc_log: utc_log? ,
88+ translators: translators
89+ } = Logger.Config . __data__ ( )
90+
91+ with true <- Logger . compare_levels ( level , min_level ) != :lt and mode != :discard ,
9192 { :ok , message } <- translate ( translators , min_level , level , kind , data , truncate ) do
9293 message = Logger.Utils . truncate ( message , truncate )
9394
@@ -106,31 +107,35 @@ defmodule Logger.ErrorHandler do
106107 defp ensure_pid ( pid ) when is_pid ( pid ) , do: pid
107108 defp ensure_pid ( _ ) , do: self ( )
108109
109- defp check_threshold ( state ) do
110- % { last_time: last_time , last_length: last_length , dropped: dropped , threshold: threshold } =
111- state
110+ defp check_threshold_unless_skipping ( % { skip: 0 } = state ) do
111+ check_threshold ( state )
112+ end
112113
113- { m , s , _ } = current_time = :os . timestamp ( )
114- current_length = message_queue_length ( )
114+ defp check_threshold_unless_skipping ( % { skip: skip } = state ) do
115+ % { state | skip: skip - 1 }
116+ end
115117
116- cond do
117- match? ( { ^ m , ^ s , _ } , last_time ) and current_length - last_length > threshold ->
118- count = drop_messages ( current_time , 0 )
119- % { state | dropped: dropped + count , last_length: message_queue_length ( ) }
118+ def check_threshold ( state ) do
119+ % { discard_threshold: discard_threshold , keep_threshold: keep_threshold } = state
120+ current_length = message_queue_length ( )
120121
121- match? ( { ^ m , ^ s , _ } , last_time ) ->
122- state
122+ if current_length >= discard_threshold do
123+ to_drop = current_length - keep_threshold
124+ drop_messages ( to_drop )
123125
124- true ->
125- if dropped > 0 do
126- message =
127- "Logger dropped #{ dropped } OTP/SASL messages as it " <>
128- "exceeded the amount of #{ threshold } messages/second"
126+ message =
127+ "Logger dropped #{ to_drop } OTP/SASL messages as it had #{ current_length } messages in " <>
128+ "its inbox, exceeding the amount of :discard_threshold #{ discard_threshold } messages. " <>
129+ "The number of messages was reduced to #{ keep_threshold } (75% of the threshold)"
129130
130- Logger . warn ( message )
131- end
131+ % { utc_log: utc_log? } = Logger.Config . __data__ ( )
132+ event = { Logger , message , Logger.Utils . timestamp ( utc_log? ) , pid: self ( ) }
133+ :gen_event . notify ( state . logger , { :warn , Process . group_leader ( ) , event } )
132134
133- % { state | dropped: 0 , last_time: current_time , last_length: current_length }
135+ # We won't check the threshold for the next 10% of the threshold messages
136+ % { state | skip: trunc ( discard_threshold * 0.1 ) }
137+ else
138+ state
134139 end
135140 end
136141
@@ -139,17 +144,15 @@ defmodule Logger.ErrorHandler do
139144 len
140145 end
141146
142- defp drop_messages ( { m , s , _ } = last_time , count ) do
143- case :os . timestamp ( ) do
144- { ^ m , ^ s , _ } ->
145- receive do
146- { :notify , _event } -> drop_messages ( last_time , count + 1 )
147- after
148- 0 -> count
149- end
147+ defp drop_messages ( 0 ) do
148+ :ok
149+ end
150150
151- _ ->
152- count
151+ defp drop_messages ( count ) do
152+ receive do
153+ { :notify , _event } -> drop_messages ( count - 1 )
154+ after
155+ 0 -> :ok
153156 end
154157 end
155158
0 commit comments