@@ -221,15 +221,18 @@ class ConcurrentMultiSpanProcessor(SpanProcessor):
221
221
def __init__ (self , num_threads : int = 2 ):
222
222
# use a tuple to avoid race conditions when adding a new span and
223
223
# iterating through it on "on_start" and "on_end".
224
- self ._span_processors = () # type: Tuple [SpanProcessor, ...]
224
+ self ._span_processors : tuple [SpanProcessor ] = ()
225
225
self ._lock = threading .Lock ()
226
226
self ._executor = concurrent .futures .ThreadPoolExecutor (
227
227
max_workers = num_threads
228
228
)
229
+ self ._is_shutdown : bool = False
229
230
230
231
def add_span_processor (self , span_processor : SpanProcessor ) -> None :
231
232
"""Adds a SpanProcessor to the list handled by this instance."""
232
233
with self ._lock :
234
+ if self ._is_shutdown :
235
+ return
233
236
self ._span_processors += (span_processor ,)
234
237
235
238
def _submit_and_await (
@@ -239,9 +242,13 @@ def _submit_and_await(
239
242
** kwargs : Any ,
240
243
):
241
244
futures = []
242
- for sp in self ._span_processors :
243
- future = self ._executor .submit (func (sp ), * args , ** kwargs )
244
- futures .append (future )
245
+ with self ._lock :
246
+ if self ._is_shutdown :
247
+ return
248
+ for sp in self ._span_processors :
249
+ future = self ._executor .submit (func (sp ), * args , ** kwargs )
250
+ futures .append (future )
251
+
245
252
for future in futures :
246
253
future .result ()
247
254
@@ -258,8 +265,16 @@ def on_end(self, span: "ReadableSpan") -> None:
258
265
self ._submit_and_await (lambda sp : sp .on_end , span )
259
266
260
267
def shutdown (self ) -> None :
261
- """Shuts down all underlying span processors in parallel."""
262
- self ._submit_and_await (lambda sp : sp .shutdown )
268
+ """Shuts down all underlying span processors and the executor."""
269
+ with self ._lock :
270
+ if self ._is_shutdown :
271
+ return
272
+ self ._is_shutdown = True
273
+
274
+ for sp in self ._span_processors :
275
+ sp .shutdown ()
276
+
277
+ self ._executor .shutdown (wait = True )
263
278
264
279
def force_flush (self , timeout_millis : int = 30000 ) -> bool :
265
280
"""Calls force_flush on all underlying span processors in parallel.
@@ -272,10 +287,14 @@ def force_flush(self, timeout_millis: int = 30000) -> bool:
272
287
True if all span processors flushed their spans within the given
273
288
timeout, False otherwise.
274
289
"""
275
- futures = []
276
- for sp in self ._span_processors : # type: SpanProcessor
277
- future = self ._executor .submit (sp .force_flush , timeout_millis )
278
- futures .append (future )
290
+ with self ._lock :
291
+ if self ._is_shutdown :
292
+ return False
293
+
294
+ futures = []
295
+ for sp in self ._span_processors :
296
+ future = self ._executor .submit (sp .force_flush , timeout_millis )
297
+ futures .append (future )
279
298
280
299
timeout_sec = timeout_millis / 1e3
281
300
done_futures , not_done_futures = concurrent .futures .wait (
0 commit comments