56
56
//! those contexts.
57
57
//!
58
58
//! ```
59
- //! use futures::{stream};
59
+ //! use futures::{FutureExt as _, stream};
60
60
//! use opentelemetry::{api, sdk, global};
61
61
//! use std::time::Duration;
62
62
//!
68
68
//! // Then build a batch processor. You can use whichever executor you have available, for
69
69
//! // example if you are using `async-std` instead of `tokio` you can replace the spawn and
70
70
//! // interval functions with `async_std::task::spawn` and `async_std::stream::interval`.
71
- //! let batch = sdk::BatchSpanProcessor::builder(exporter, tokio::spawn, tokio::time::interval)
71
+ //! let spawn = |future| tokio::spawn(future).map(|result| result.expect("task failed"));
72
+ //! let batch = sdk::BatchSpanProcessor::builder(exporter, spawn, tokio::time::interval)
72
73
//! .with_max_queue_size(4096)
73
74
//! .build();
74
75
//!
@@ -96,6 +97,7 @@ use futures::{
96
97
task:: { Context , Poll } ,
97
98
Future , Stream , StreamExt ,
98
99
} ;
100
+ use std:: fmt:: Debug ;
99
101
use std:: pin:: Pin ;
100
102
use std:: sync:: { Arc , Mutex } ;
101
103
use std:: time;
@@ -134,9 +136,17 @@ impl api::SpanProcessor for SimpleSpanProcessor {
134
136
/// them at a preconfigured interval.
135
137
///
136
138
/// [`SpanProcessor`]: ../../../api/trace/span_processor/trait.SpanProcessor.html
137
- #[ derive( Debug ) ]
138
139
pub struct BatchSpanProcessor {
139
140
message_sender : Mutex < mpsc:: Sender < BatchMessage > > ,
141
+ worker_handle : Mutex < Option < Pin < Box < dyn Future < Output = ( ) > + Send + Sync > > > > ,
142
+ }
143
+
144
+ impl Debug for BatchSpanProcessor {
145
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
146
+ f. debug_struct ( "BatchSpanProcessor" )
147
+ . field ( "message_sender" , & self . message_sender )
148
+ . finish ( )
149
+ }
140
150
}
141
151
142
152
impl api:: SpanProcessor for BatchSpanProcessor {
@@ -154,6 +164,15 @@ impl api::SpanProcessor for BatchSpanProcessor {
154
164
if let Ok ( mut sender) = self . message_sender . lock ( ) {
155
165
let _ = sender. try_send ( BatchMessage :: Shutdown ) ;
156
166
}
167
+
168
+ if let Some ( worker_handle) = self
169
+ . worker_handle
170
+ . lock ( )
171
+ . expect ( "worker_handle Mutex panicked" )
172
+ . take ( )
173
+ {
174
+ futures:: executor:: block_on ( worker_handle) ;
175
+ }
157
176
}
158
177
}
159
178
@@ -233,12 +252,13 @@ impl BatchSpanProcessor {
233
252
S : Fn ( BatchSpanProcessorWorker ) -> SO ,
234
253
I : Fn ( time:: Duration ) -> IS ,
235
254
IS : Stream < Item = ISI > + Send + ' static ,
255
+ SO : Future < Output = ( ) > + Send + Sync + ' static ,
236
256
{
237
257
let ( message_sender, message_receiver) = mpsc:: channel ( config. max_queue_size ) ;
238
258
let ticker = interval ( config. scheduled_delay ) . map ( |_| BatchMessage :: Tick ) ;
239
259
240
260
// Spawn worker process via user-defined spawn function.
241
- spawn ( BatchSpanProcessorWorker {
261
+ let worker_handle = spawn ( BatchSpanProcessorWorker {
242
262
exporter,
243
263
messages : Box :: pin ( futures:: stream:: select ( message_receiver, ticker) ) ,
244
264
config,
@@ -248,6 +268,7 @@ impl BatchSpanProcessor {
248
268
// Return batch processor with link to worker
249
269
BatchSpanProcessor {
250
270
message_sender : Mutex :: new ( message_sender) ,
271
+ worker_handle : Mutex :: new ( Some ( Box :: pin ( worker_handle) ) ) ,
251
272
}
252
273
}
253
274
@@ -316,6 +337,7 @@ where
316
337
S : Fn ( BatchSpanProcessorWorker ) -> SO ,
317
338
I : Fn ( time:: Duration ) -> IS ,
318
339
IS : Stream < Item = ISI > + Send + ' static ,
340
+ SO : Future < Output = ( ) > + Send + Sync + ' static ,
319
341
{
320
342
/// Set max queue size for batches
321
343
pub fn with_max_queue_size ( self , size : usize ) -> Self {
0 commit comments