It should be possible to propagate context without creating a new span
There are multiple cases when passive context propagation (without modification) is desirable:
- proxy/load-balancer/service-mesh that just passes context around. While it may be implemented with explicit context propagation, it'd be hard to do especially when the component produces some logs or events that should be correlated.
- Tracing without SDK - it could be a reasonable default for a service to just propagate context when tracing is disabled. It was also considered as possible API default at some point - https://github.com/open-telemetry/opentelemetry-specification/issues/689
- similar cases when application wants to hide its implementation details from the users. E.g. Azure Functions host handles request and invokes a worker running in a different process. Tracing calls between host and worker is a bit verbose and should be opt-in, so the desire is to create one span on the host and use it as a parent for the telemetry on the worker
- Inside the process context propagation without modification is useful when suppressing spans without breaking correlation.
Some languages (Java, Go) allow it all with a code like
// extract span context
SpanContext remote = SpanContext.createFromRemoteParent("<traceId>", "<spanId>", ...);
// create parent Context from SpanContext
Context parent = Context.root().with(Span.wrap(remote));
// now we can make it current and it'll become a parent to any spans created in its scope
Scope scope = parent.makeCurrent();
Span child = tracer.spanBuilder("child").startSpan();
child.end();
scope.close();
but some other languages (.NET) don't implement it since spec does not tell anything about it - https://github.com/open-telemetry/opentelemetry-dotnet/issues/5286
Indeed, https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#context-interaction defines interactions between Span and Context and tells nothing about SpanContext or ability to represent existing SpanContext with a Span
The solutions I would like:
- Add a language that allows to associate a
SpanContextwith the currentContext. - It implies the ability to have a
Span-like representation of aSpanContextthat'd be returned byTracer.getCurrentSpan(). - Such span would be non-recording and would just wrap the
SpanContextit was created in. See PropagatedSpan implementation in Java [UPDATE]: Or nonRecordingSpan in go (thanks @dmathieu for the pointers).
For the record, Go allows doing this with the trace.ContextWithSpanContext and trace.ContextWithRemoteSpanContext methods, which allows injecting a span context into the context.
I think I'm missing something. In the example code given isn't Span.wrap(remote) actually creating a new span? Following the API spec for wrapping, https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#wrapping-a-spancontext-in-a-span
Which is how the propagation api is supported, it extracts the span context and attaches it as the current span so it is used as the parent.
We actually do this different in Erlang/Elixir and don't require a new Span, but I'm not sure that is needed or changes to the spec to support what I understand the examples to be?
but some other languages (.NET) don't implement it since spec does not tell anything about it
Just saw this issue, note I made a .NET proposal for this: https://github.com/dotnet/runtime/issues/86966