@@ -200,10 +200,36 @@ impl PeriodicReader {
200
200
otel_debug ! (
201
201
name: "PeriodReaderThreadExportingDueToFlush"
202
202
) ;
203
- if let Err ( _e) = cloned_reader. collect_and_export ( timeout) {
204
- response_sender. send ( false ) . unwrap ( ) ;
205
- } else {
206
- response_sender. send ( true ) . unwrap ( ) ;
203
+
204
+ let export_result = cloned_reader. collect_and_export ( timeout) ;
205
+ otel_debug ! (
206
+ name: "PeriodReaderInvokedExport" ,
207
+ export_result = format!( "{:?}" , export_result)
208
+ ) ;
209
+
210
+ // If response_sender is disconnected, we can't send
211
+ // the result back. This occurs when the thread that
212
+ // initiated flush gave up due to timeout.
213
+ // Gracefully handle that with internal logs. The
214
+ // internal errors are of Info level, as this is
215
+ // useful for user to know whether the flush was
216
+ // successful or not, when flush() itself merely
217
+ // tells that it timed out.
218
+
219
+ if export_result. is_err ( ) {
220
+ if response_sender. send ( false ) . is_err ( ) {
221
+ otel_info ! (
222
+ name: "PeriodReader.Flush.ResponseSendError" ,
223
+ message = "PeriodicReader's flush has failed, but unable to send this info back to caller.
224
+ This occurs when the caller has timed out waiting for the response. If you see this occuring frequently, consider increasing the flush timeout."
225
+ ) ;
226
+ }
227
+ } else if response_sender. send ( true ) . is_err ( ) {
228
+ otel_info ! (
229
+ name: "PeriodReader.Flush.ResponseSendError" ,
230
+ message = "PeriodicReader's flush has completed successfully, but unable to send this info back to caller.
231
+ This occurs when the caller has timed out waiting for the response. If you see this occuring frequently, consider increasing the flush timeout."
232
+ ) ;
207
233
}
208
234
209
235
// Adjust the remaining interval after the flush
@@ -232,15 +258,39 @@ impl PeriodicReader {
232
258
// Perform final export and break out of loop and exit the thread
233
259
otel_debug ! ( name: "PeriodReaderThreadExportingDueToShutdown" ) ;
234
260
let export_result = cloned_reader. collect_and_export ( timeout) ;
261
+ otel_debug ! (
262
+ name: "PeriodReaderInvokedExport" ,
263
+ export_result = format!( "{:?}" , export_result)
264
+ ) ;
235
265
let shutdown_result = exporter_arc. shutdown ( ) ;
236
266
otel_debug ! (
237
267
name: "PeriodReaderInvokedExporterShutdown" ,
238
268
shutdown_result = format!( "{:?}" , shutdown_result)
239
269
) ;
270
+
271
+ // If response_sender is disconnected, we can't send
272
+ // the result back. This occurs when the thread that
273
+ // initiated shutdown gave up due to timeout.
274
+ // Gracefully handle that with internal logs and
275
+ // continue with shutdown (i.e exit thread) The
276
+ // internal errors are of Info level, as this is
277
+ // useful for user to know whether the shutdown was
278
+ // successful or not, when shutdown() itself merely
279
+ // tells that it timed out.
240
280
if export_result. is_err ( ) || shutdown_result. is_err ( ) {
241
- response_sender. send ( false ) . unwrap ( ) ;
242
- } else {
243
- response_sender. send ( true ) . unwrap ( ) ;
281
+ if response_sender. send ( false ) . is_err ( ) {
282
+ otel_info ! (
283
+ name: "PeriodReaderThreadShutdown.ResponseSendError" ,
284
+ message = "PeriodicReader's shutdown has failed, but unable to send this info back to caller.
285
+ This occurs when the caller has timed out waiting for the response. If you see this occuring frequently, consider increasing the shutdown timeout."
286
+ ) ;
287
+ }
288
+ } else if response_sender. send ( true ) . is_err ( ) {
289
+ otel_info ! (
290
+ name: "PeriodReaderThreadShutdown.ResponseSendError" ,
291
+ message = "PeriodicReader completed its shutdown, but unable to send this info back to caller.
292
+ This occurs when the caller has timed out waiting for the response. If you see this occuring frequently, consider increasing the shutdown timeout."
293
+ ) ;
244
294
}
245
295
246
296
otel_debug ! (
@@ -255,11 +305,11 @@ impl PeriodicReader {
255
305
name: "PeriodReaderThreadExportingDueToTimer"
256
306
) ;
257
307
258
- if let Err ( _e ) = cloned_reader. collect_and_export ( timeout) {
259
- otel_debug ! (
260
- name: "PeriodReaderThreadExportingDueToTimerFailed"
261
- ) ;
262
- }
308
+ let export_result = cloned_reader. collect_and_export ( timeout) ;
309
+ otel_debug ! (
310
+ name: "PeriodReaderInvokedExport" ,
311
+ export_result = format! ( "{:?}" , export_result )
312
+ ) ;
263
313
264
314
let time_taken_for_export = export_start. elapsed ( ) ;
265
315
if time_taken_for_export > interval {
@@ -390,17 +440,7 @@ impl PeriodicReaderInner {
390
440
391
441
// Relying on futures executor to execute async call.
392
442
// TODO: Pass timeout to exporter
393
- let exporter_result = futures_executor:: block_on ( self . exporter . export ( & mut rm) ) ;
394
- #[ allow( clippy:: question_mark) ]
395
- if let Err ( e) = exporter_result {
396
- otel_warn ! (
397
- name: "PeriodReaderExportError" ,
398
- error = format!( "{:?}" , e)
399
- ) ;
400
- return Err ( e) ;
401
- }
402
-
403
- Ok ( ( ) )
443
+ futures_executor:: block_on ( self . exporter . export ( & mut rm) )
404
444
}
405
445
406
446
fn force_flush ( & self ) -> MetricResult < ( ) > {
0 commit comments