@@ -89,6 +89,15 @@ impl BufferReader {
8989 /// This is the main entry point for receiving metric data.
9090 /// Note: Different transports have different blocking behaviors.
9191 async fn read ( & self ) -> std:: io:: Result < ( Vec < u8 > , MessageSource ) > {
92+ debug ! (
93+ "BufferReader::read() called, variant: {}" ,
94+ match self {
95+ BufferReader :: UdpSocket ( _) => "UdpSocket" ,
96+ BufferReader :: MirrorTest ( _, _) => "MirrorTest" ,
97+ #[ cfg( windows) ]
98+ BufferReader :: NamedPipe { .. } => "NamedPipe" ,
99+ }
100+ ) ;
92101 match self {
93102 BufferReader :: UdpSocket ( socket) => {
94103 // UDP socket: blocks until a packet arrives
@@ -137,18 +146,30 @@ async fn handle_pipe_error_with_backoff(
137146 ) ;
138147
139148 if * consecutive_errors >= MAX_NAMED_PIPE_ERRORS {
140- return Err ( std:: io:: Error :: other ( format ! (
141- "Too many consecutive {} errors: {}" ,
142- error_type, error
143- ) ) ) ;
149+ let err_msg = format ! ( "Too many consecutive {} errors: {}" , error_type, error) ;
150+ debug ! (
151+ "MAX_NAMED_PIPE_ERRORS ({}) reached: {}" ,
152+ MAX_NAMED_PIPE_ERRORS , err_msg
153+ ) ;
154+ return Err ( std:: io:: Error :: other ( err_msg) ) ;
144155 }
145156
146157 let backoff_ms = 10u64 * ( 1 << * consecutive_errors) ;
158+ debug ! (
159+ "Backing off {}ms after {} error (attempt {})" ,
160+ backoff_ms, error_type, consecutive_errors
161+ ) ;
147162
148163 // Sleep with cancellation support for clean, fast shutdown
149164 tokio:: select! {
150- _ = sleep( Duration :: from_millis( backoff_ms) ) => Ok ( true ) ,
151- _ = cancel_token. cancelled( ) => Ok ( false ) ,
165+ _ = sleep( Duration :: from_millis( backoff_ms) ) => {
166+ debug!( "Backoff sleep completed" ) ;
167+ Ok ( true )
168+ } ,
169+ _ = cancel_token. cancelled( ) => {
170+ debug!( "Backoff cancelled via token" ) ;
171+ Ok ( false )
172+ } ,
152173 }
153174}
154175
@@ -162,21 +183,34 @@ async fn read_from_named_pipe(
162183 pipe_name : & str ,
163184 cancel_token : & tokio_util:: sync:: CancellationToken ,
164185) -> std:: io:: Result < Vec < u8 > > {
186+ debug ! ( "read_from_named_pipe() called for: {}" , pipe_name) ;
165187 let mut consecutive_errors = 0 ;
166188 let mut current_pipe: Option < tokio:: net:: windows:: named_pipe:: NamedPipeServer > = None ;
167189 let mut needs_connection = true ; // Track whether we need to wait for a client
168190
191+ debug ! (
192+ "Entering retry loop, cancel_token.is_cancelled() = {}" ,
193+ cancel_token. is_cancelled( )
194+ ) ;
169195 // Let named pipes cancel cleanly when the server is shut down
170196 while !cancel_token. is_cancelled ( ) {
171197 // Create pipe if needed (initial startup or after error)
172198 if current_pipe. is_none ( ) {
199+ debug ! ( "Attempting to create named pipe: {}" , pipe_name) ;
173200 match ServerOptions :: new ( ) . create ( pipe_name) {
174201 Ok ( new_pipe) => {
202+ debug ! ( "Successfully created named pipe: {}" , pipe_name) ;
175203 consecutive_errors = 0 ; // Reset on successful pipe creation
176204 current_pipe = Some ( new_pipe) ;
177205 needs_connection = true ;
178206 }
179207 Err ( e) => {
208+ debug ! (
209+ "Failed to create named pipe: {} - ErrorKind: {:?}, Error: {}" ,
210+ pipe_name,
211+ e. kind( ) ,
212+ e
213+ ) ;
180214 match handle_pipe_error_with_backoff (
181215 & mut consecutive_errors,
182216 "pipe creation" ,
@@ -185,8 +219,17 @@ async fn read_from_named_pipe(
185219 )
186220 . await ?
187221 {
188- true => continue ,
189- false => break ,
222+ true => {
223+ debug ! (
224+ "Retrying after pipe creation error backoff (attempt {})" ,
225+ consecutive_errors
226+ ) ;
227+ continue ;
228+ }
229+ false => {
230+ debug ! ( "Breaking loop - cancelled during pipe creation error backoff" ) ;
231+ break ;
232+ }
190233 }
191234 }
192235 }
@@ -197,19 +240,23 @@ async fn read_from_named_pipe(
197240 #[ allow( clippy:: expect_used) ]
198241 let pipe = current_pipe. as_ref ( ) . expect ( "pipe must exist" ) ;
199242
243+ debug ! ( "Waiting for client to connect to named pipe: {}" , pipe_name) ;
200244 let connect_result = tokio:: select! {
201245 result = pipe. connect( ) => result,
202246 _ = cancel_token. cancelled( ) => {
247+ debug!( "Named pipe connect cancelled via token" ) ;
203248 break ;
204249 }
205250 } ;
206251
207252 match connect_result {
208253 Ok ( ( ) ) => {
254+ debug ! ( "Client connected successfully to named pipe: {}" , pipe_name) ;
209255 consecutive_errors = 0 ;
210256 needs_connection = false ;
211257 }
212258 Err ( e) => {
259+ debug ! ( "Connection failed for named pipe: {} - {:?}" , pipe_name, e) ;
213260 // Connection failed - disconnect and recreate pipe on next iteration
214261 if let Some ( pipe) = current_pipe. as_ref ( ) {
215262 let _ = pipe. disconnect ( ) ; // Ignore disconnect errors, we're recreating anyway
@@ -223,8 +270,14 @@ async fn read_from_named_pipe(
223270 )
224271 . await ?
225272 {
226- true => continue ,
227- false => break ,
273+ true => {
274+ debug ! ( "Retrying after connection error backoff" ) ;
275+ continue ;
276+ }
277+ false => {
278+ debug ! ( "Breaking loop - cancelled during connection error backoff" ) ;
279+ break ;
280+ }
228281 }
229282 }
230283 }
@@ -306,8 +359,13 @@ impl DogStatsD {
306359 aggregator_handle : AggregatorHandle ,
307360 cancel_token : tokio_util:: sync:: CancellationToken ,
308361 ) -> DogStatsD {
362+ debug ! (
363+ "DogStatsD::new() called with windows_pipe_name: {:?}, host: {}, port: {}" ,
364+ config. windows_pipe_name, config. host, config. port
365+ ) ;
309366 #[ allow( unused_variables) ] // pipe_name unused on non-Windows
310367 let buffer_reader = if let Some ( ref pipe_name) = config. windows_pipe_name {
368+ debug ! ( "Creating NamedPipe BufferReader for: {}" , pipe_name) ;
311369 #[ cfg( windows) ]
312370 {
313371 BufferReader :: NamedPipe {
@@ -321,6 +379,10 @@ impl DogStatsD {
321379 panic ! ( "Named pipes are only supported on Windows." )
322380 }
323381 } else {
382+ debug ! (
383+ "Creating UdpSocket BufferReader for: {}:{}" ,
384+ config. host, config. port
385+ ) ;
324386 // UDP socket for all platforms
325387 let addr = format ! ( "{}:{}" , config. host, config. port) ;
326388 // TODO (UDS socket)
@@ -330,6 +392,7 @@ impl DogStatsD {
330392 . expect ( "couldn't bind to address" ) ;
331393 BufferReader :: UdpSocket ( socket)
332394 } ;
395+ debug ! ( "BufferReader created successfully" ) ;
333396
334397 DogStatsD {
335398 cancel_token,
@@ -341,21 +404,31 @@ impl DogStatsD {
341404
342405 /// Main event loop that continuously receives and processes metrics.
343406 pub async fn spin ( self ) {
407+ debug ! (
408+ "spin() starting, cancel_token.is_cancelled() = {}" ,
409+ self . cancel_token. is_cancelled( )
410+ ) ;
344411 let mut spin_cancelled = false ;
345412 while !spin_cancelled {
413+ debug ! ( "spin() loop iteration, calling consume_statsd()..." ) ;
346414 self . consume_statsd ( ) . await ;
415+ debug ! ( "consume_statsd() returned" ) ;
347416 spin_cancelled = self . cancel_token . is_cancelled ( ) ;
417+ debug ! ( "spin_cancelled = {}" , spin_cancelled) ;
348418 }
419+ debug ! ( "spin() exiting" ) ;
349420 }
350421
351422 /// Receive one batch of metrics from the transport layer and process them.
352423 async fn consume_statsd ( & self ) {
424+ debug ! ( "consume_statsd() called, about to read from buffer_reader" ) ;
353425 #[ allow( clippy:: expect_used) ]
354426 let ( buf, src) = self
355427 . buffer_reader
356428 . read ( )
357429 . await
358430 . expect ( "didn't receive data" ) ;
431+ debug ! ( "buffer_reader.read() completed with {} bytes" , buf. len( ) ) ;
359432
360433 #[ allow( clippy:: expect_used) ]
361434 let msgs = std:: str:: from_utf8 ( & buf) . expect ( "couldn't parse as string" ) ;
0 commit comments