Skip to content

sync BatchSpanProcessor silently ignores OTEL_BSP_MAX_CONCURRENT_EXPORTS / max_concurrent_exports #3402

@glaziermag

Description

@glaziermag

Summary

The thread-based sync BatchSpanProcessor accepts/document-parses OTEL_BSP_MAX_CONCURRENT_EXPORTS, but does not honor concurrent exporting at runtime.

This is best classified as a misleading no-op configuration / docs-contract drift, not a newly introduced semantic bug in the sync redesign.

Important scope nuance

with_max_concurrent_exports(...) is feature-gated (experimental_trace_batch_span_processor_with_async_runtime).

So the always-on mismatch is specifically:

  • sync/thread-based BSP exports serially by design,
  • while OTEL_BSP_MAX_CONCURRENT_EXPORTS is still documented and parsed on the shared config surface.

When the experimental async-runtime feature is enabled, with_max_concurrent_exports(...) can still populate the shared BatchConfig, but that value remains a no-op for the sync/thread-based processor.

Repro

I used a custom exporter that tracks concurrent in-flight export() calls via atomics and sleeps briefly inside export().

Config used on sync BSP:

  • max_export_batch_size = 1
  • max_queue_size = 32
  • scheduled_delay = 3600s (to avoid timer-triggered noise)
  • max_concurrent_exports = 4

Then emit several spans quickly and force_flush().

Observed: max overlap stayed 1 (serial).

Differential evidence

The async-runtime BSP path does honor this knob and has behavior tests for both concurrent and serial modes:

  • trace::span_processor_with_async_runtime::tests::test_concurrent_exports_expected
  • trace::span_processor_with_async_runtime::tests::test_exports_serial_when_max_concurrent_exports_1

Intent vs contract mismatch

The redesign changelog states sync/thread-based BSP does not support multiple concurrent exports, so serial sync behavior appears intentional.

However, the config/docs surface still advertises OTEL_BSP_MAX_CONCURRENT_EXPORTS broadly enough that users can reasonably expect it to have effect on sync BSP.

That combination makes the setting effectively a silent no-op on sync BSP.

Suggested resolution

Either (or both):

  1. Document clearly that max_concurrent_exports / OTEL_BSP_MAX_CONCURRENT_EXPORTS is async-runtime BSP only.
  2. In sync BSP, reject or warn (or clamp with warning) when max_concurrent_exports > 1 instead of silently accepting it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions