Skip to content

Conversation

@fbogsany
Copy link
Contributor

@fbogsany fbogsany commented Aug 25, 2025

The spec states:

The API MUST return a non-recording Span with the SpanContext in the
parent Context (whether explicitly given or implicit current). If the
Span in the parent Context is already non-recording, it SHOULD be
returned directly without instantiating a new Span. If the parent
Context contains no Span, an empty non-recording Span MUST be returned
instead (i.e., having a SpanContext with all-zero Span and Trace IDs,
empty Tracestate, and unsampled TraceFlags).

With new tests that match the spec, the current implementation fails with:

non-recording span with the parent span context if the parent span is
recording [test/opentelemetry/trace/tracer_test.rb:97]: Expected
@context=#<OpenTelemetry::Trace::SpanContext:0x0000000120e17140
@trace_id="E\xC6d\xD5S+h\x8B\xC6u\xE6\xD5\ePQ\xDD",
@span_id="\xE2\xB3\x01\x99\xEC\xA0\xC1\x81",
@trace_flags=#<OpenTelemetry::Trace::TraceFlags:0x00000001052a50c0
@flags=0>,
@tracestate=#<OpenTelemetry::Trace::Tracestate:0x000000012085fdd8
@hash={}>, @remote=false>> to not be equal to
@context=#<OpenTelemetry::Trace::SpanContext:0x0000000120e17140
@trace_id="E\xC6d\xD5S+h\x8B\xC6u\xE6\xD5\ePQ\xDD",
@span_id="\xE2\xB3\x01\x99\xEC\xA0\xC1\x81",
@trace_flags=#<OpenTelemetry::Trace::TraceFlags:0x00000001052a50c0
@flags=0>,
@tracestate=#<OpenTelemetry::Trace::Tracestate:0x000000012085fdd8
@hash={}>, @remote=false>>.

The new implementation correctly passes this test (and the old tests). Shopify has been running with a similar patch in production for several years, based on a belief that the spec was incorrect - instead the implementation was wrong 🤦 .

Context: IIRC the API Tracer was written assuming that it would be used only when no SDK was present, however that is not necessarily true (anyone can create a no-op API Tracer instance even if the SDK TracerProvider is installed) and the spec for TracerConfig states:

If a Tracer is disabled, it MUST behave equivalently to a No-op Tracer.

The obvious implementation of TracerConfig would delegate to an API Tracer instance when a Tracer is disabled.

The spec states:
> The API MUST return a non-recording Span with the SpanContext in the
  parent Context (whether explicitly given or implicit current). If the
  Span in the parent Context is already non-recording, it SHOULD be
  returned directly without instantiating a new Span. If the parent
  Context contains no Span, an empty non-recording Span MUST be returned
  instead (i.e., having a SpanContext with all-zero Span and Trace IDs,
  empty Tracestate, and unsampled TraceFlags).

With new tests that match the spec, the current implementation fails
with:

``` OpenTelemetry::Trace::Tracer::#start_span#test_0002_returns a
non-recording span with the parent span context if the parent span is
recording [test/opentelemetry/trace/tracer_test.rb:97]: Expected
@context=#<OpenTelemetry::Trace::SpanContext:0x0000000120e17140
@trace_id="E\xC6d\xD5S+h\x8B\xC6u\xE6\xD5\ePQ\xDD",
@span_id="\xE2\xB3\x01\x99\xEC\xA0\xC1\x81",
@trace_flags=#<OpenTelemetry::Trace::TraceFlags:0x00000001052a50c0
@flags=0>,
@tracestate=#<OpenTelemetry::Trace::Tracestate:0x000000012085fdd8
@hash={}>, @Remote=false>> to not be equal to
@context=#<OpenTelemetry::Trace::SpanContext:0x0000000120e17140
@trace_id="E\xC6d\xD5S+h\x8B\xC6u\xE6\xD5\ePQ\xDD",
@span_id="\xE2\xB3\x01\x99\xEC\xA0\xC1\x81",
@trace_flags=#<OpenTelemetry::Trace::TraceFlags:0x00000001052a50c0
@flags=0>,
@tracestate=#<OpenTelemetry::Trace::Tracestate:0x000000012085fdd8
@hash={}>, @Remote=false>>. ```

The new implementation correctly passes this test (and the old tests).
Shopify has been running with a similar patch in production for several
years, based on a belief that the spec was incorrect - instead the
_implementation_ was wrong.
@fbogsany fbogsany changed the title This PR corrects the spec-compliance of API Tracer.start_span. fix: Correct spec-compliance of API Tracer.start_span Aug 25, 2025
Copy link
Contributor

@kaylareopelle kaylareopelle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for catching this and sharing Shopify's patch!

@fbogsany fbogsany merged commit 463ef11 into main Aug 29, 2025
71 of 72 checks passed
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.

2 participants