@@ -32,7 +32,7 @@ use std::net::{IpAddr, Ipv6Addr, SocketAddr};
32
32
use std:: os:: unix:: io:: AsFd ;
33
33
#[ cfg( windows) ]
34
34
use std:: os:: windows:: io:: AsSocket ;
35
- #[ cfg( not( wasm_browser) ) ]
35
+ #[ cfg( all ( not( wasm_browser) , any ( feature = "tracing" , feature = "direct-log" ) ) ) ]
36
36
use std:: {
37
37
sync:: Mutex ,
38
38
time:: { Duration , Instant } ,
@@ -146,33 +146,47 @@ pub struct Transmit<'a> {
146
146
pub src_ip : Option < IpAddr > ,
147
147
}
148
148
149
- /// Log at most 1 IO error per minute
150
- #[ cfg( not( wasm_browser) ) ]
151
- const IO_ERROR_LOG_INTERVAL : Duration = std:: time:: Duration :: from_secs ( 60 ) ;
152
-
153
- /// Logs a warning message when sendmsg fails
154
- ///
155
- /// Logging will only be performed if at least [`IO_ERROR_LOG_INTERVAL`]
156
- /// has elapsed since the last error was logged.
157
149
#[ cfg( all( not( wasm_browser) , any( feature = "tracing" , feature = "direct-log" ) ) ) ]
158
- fn log_sendmsg_error (
159
- last_send_error : & Mutex < Instant > ,
160
- err : impl core:: fmt:: Debug ,
161
- transmit : & Transmit ,
162
- ) {
163
- let now = Instant :: now ( ) ;
164
- let last_send_error = & mut * last_send_error. lock ( ) . expect ( "poisend lock" ) ;
165
- if now. saturating_duration_since ( * last_send_error) > IO_ERROR_LOG_INTERVAL {
166
- * last_send_error = now;
167
- log:: warn!(
168
- "sendmsg error: {:?}, Transmit: {{ destination: {:?}, src_ip: {:?}, ecn: {:?}, len: {:?}, segment_size: {:?} }}" ,
169
- err, transmit. destination, transmit. src_ip, transmit. ecn, transmit. contents. len( ) , transmit. segment_size) ;
170
- }
150
+ const IO_ERROR_LOG_INTERVAL : Duration = Duration :: from_secs ( 60 ) ;
151
+
152
+ /// Helper for rate-limiting the logging of sendmsg errors.
153
+ #[ derive( Debug ) ]
154
+ struct SendErrorSink {
155
+ #[ cfg( all( not( wasm_browser) , any( feature = "tracing" , feature = "direct-log" ) ) ) ]
156
+ last_send_error : Mutex < Instant > ,
171
157
}
172
158
173
- // No-op
174
- #[ cfg( not( any( wasm_browser, feature = "tracing" , feature = "direct-log" ) ) ) ]
175
- fn log_sendmsg_error ( _: & Mutex < Instant > , _: impl core:: fmt:: Debug , _: & Transmit ) { }
159
+ impl SendErrorSink {
160
+ /// Produces a record the last send error in socket state for error reporting
161
+ fn new ( ) -> Self {
162
+ Self {
163
+ #[ cfg( all( not( wasm_browser) , any( feature = "tracing" , feature = "direct-log" ) ) ) ]
164
+ last_send_error : {
165
+ let now = Instant :: now ( ) ;
166
+ Mutex :: new ( now. checked_sub ( 2 * IO_ERROR_LOG_INTERVAL ) . unwrap_or ( now) )
167
+ } ,
168
+ }
169
+ }
170
+
171
+ /// Logs a warning message when sendmsg fails
172
+ ///
173
+ /// Logging will only be performed if at least [`IO_ERROR_LOG_INTERVAL`]
174
+ /// has elapsed since the last error was logged.
175
+ #[ allow( unused_variables) ]
176
+ fn log_sendmsg_error ( & self , err : impl core:: fmt:: Debug , transmit : & Transmit ) {
177
+ #[ cfg( all( not( wasm_browser) , any( feature = "tracing" , feature = "direct-log" ) ) ) ]
178
+ {
179
+ let now = Instant :: now ( ) ;
180
+ let last_send_error = & mut * self . last_send_error . lock ( ) . expect ( "poisoned lock" ) ;
181
+ if now. saturating_duration_since ( * last_send_error) > IO_ERROR_LOG_INTERVAL {
182
+ * last_send_error = now;
183
+ log:: warn!(
184
+ "sendmsg error: {:?}, Transmit: {{ destination: {:?}, src_ip: {:?}, ecn: {:?}, len: {:?}, segment_size: {:?} }}" ,
185
+ err, transmit. destination, transmit. src_ip, transmit. ecn, transmit. contents. len( ) , transmit. segment_size) ;
186
+ }
187
+ }
188
+ }
189
+ }
176
190
177
191
/// A borrowed UDP socket
178
192
///
0 commit comments