Skip to content

oss_14_processor_export_lock_timeout#15

Open
ocelotl wants to merge 3 commits into
mainfrom
oss_14_processor_export_lock_timeout
Open

oss_14_processor_export_lock_timeout#15
ocelotl wants to merge 3 commits into
mainfrom
oss_14_processor_export_lock_timeout

Conversation

@ocelotl

@ocelotl ocelotl commented Jul 22, 2026

Copy link
Copy Markdown
Owner

Closes #12

Fixes span-processor export serialization + timeout (Linear OSS-14, findings T2/T3): SimpleSpanProcessor.export() is now serialized behind a lock (T2); BatchProcessor enforces OTEL_BSP_EXPORT_TIMEOUT via a bounded executor so a hung export can't block forever (T3), with instrumentation-suppression context preserved across the executor thread.

Linear issue: https://linear.app/dash0/issue/OSS-14/t2-t3-simplespanprocessor-concurrent-export-bsp-export-timeout-not

ocelotl added 2 commits July 19, 2026 12:16
SimpleSpanProcessor.on_end previously called span_exporter.export with no
synchronization, so two threads ending sampled spans could invoke export
concurrently, which the specification forbids. Guard the export call with a
per-processor lock so concurrent on_end calls are serialized.

The batch processor read OTEL_BSP_EXPORT_TIMEOUT into configuration but never
applied it, so a hung exporter could block the worker thread and force_flush
indefinitely. Run each export on a dedicated single-worker executor and await
it with the configured timeout as a deadline; on timeout the batch worker
stops waiting, records the failure, and moves on instead of blocking forever.
A non-positive timeout disables the deadline. This affects both
BatchSpanProcessor and BatchLogRecordProcessor via the shared BatchProcessor.

Add tests: SimpleSpanProcessor concurrent on_end never overlaps export, and a
hung batch export is bounded by the export timeout.
The batch export now runs on a separate ThreadPoolExecutor thread, but
ThreadPoolExecutor.submit does not copy the caller's contextvars into the
worker thread. As a result the _SUPPRESS_INSTRUMENTATION_KEY attached by the
batch worker was not visible to the exporter, so an auto-instrumented
transport used by the exporter could emit telemetry that feeds back into the
processor.

Capture the current context on the worker thread and run the export inside it
via contextvars.Context.run, restoring suppression during export. Add a
regression test asserting the exporter observes _SUPPRESS_INSTRUMENTATION_KEY
as True when driven through the BatchProcessor.
@ocelotl

ocelotl commented Jul 22, 2026

Copy link
Copy Markdown
Owner Author

🔒 Internal (dash0) — not for upstream.

@ocelotl

ocelotl commented Jul 22, 2026

Copy link
Copy Markdown
Owner Author

📣 Public-facing draft — to be opened upstream in open-telemetry/opentelemetry-python. No internal references; copy verbatim.

Title: Serialize SimpleSpanProcessor export and enforce BatchSpanProcessor export timeout

What

  • T2: SimpleSpanProcessor.export() is now serialized behind a per-processor lock, so concurrent on_end calls can no longer invoke the exporter concurrently.
  • T3: the batch processor now enforces OTEL_BSP_EXPORT_TIMEOUT. Each export runs on a dedicated single-worker executor awaited with the configured deadline; on timeout it logs, records the failure, and stops draining that cycle instead of blocking forever. The executor is recreated on fork and released on shutdown without waiting.

Why

The spec requires that Export not be called concurrently for the same exporter, and that Export not block indefinitely. SimpleSpanProcessor violated the first; the batch processor read OTEL_BSP_EXPORT_TIMEOUT but never applied it, so a hung exporter blocked the worker and force_flush forever.

Notes / limitations

Python cannot cancel a running synchronous call, so a timed-out export keeps running on the executor thread (bounded, single-thread back-pressure); the worker and force_flush are unblocked, which is the guarantee the spec requires. The export runs inside a copied context (contextvars.copy_context() + ctx.run) so instrumentation suppression is preserved across the executor thread. Because the timeout lives in the shared batch processor, it also benefits BatchLogRecordProcessor.

Testing

Tests cover: SimpleSpanProcessor never overlapping export under parallel on_end; a hung export being bounded by the timeout (span and log batch processors); and instrumentation suppression being active during export. Full SDK suite passes (834).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

oss_14_processor_export_lock_timeout

1 participant