Package
OpenTelemetry.Api
Package Version
| Package Name |
Version |
| OpenTelemetry.Api |
1.8.0 |
| OpenTelemetry |
1.8.0 |
Description
In Azure SDKs we want to be able to propagate baggage between messaging producer and consumer.
However there are two baggages:
System.Diagnostics.Acitivity.Baggage - legacy(?) API that uses Correlation-Context header (by default via default implementation of DistributedContextPropagator)
OpenTelemetry.Baggage.Current - OTel baggage available in OpenTelemetry.Api package.
OTel discourages usage of Activity.Baggage:
|
OpenTelemetry users should not use the `Activity.AddBaggage` method. |
As a result:
- It's not possible to use OTel baggage without taking dependency on
OpenTelemetry.Api - this is a showstopper for Azure SDK instrumentations
- Users have inconsistent baggages that don't work together
Expected Result
OTel and BCL should provide just one way to work with the baggage.
In the meantime, OTel can still provide consistent experience in the following way:
- Implement
System.Diagnostics.DistributedContextPropagator that does OTel-compatible baggage propagation: W3C + baggage header. It also reads any context provided in the Activity.Baggage (and never sets it)
- Configure that propagator on
DistributedContextPropagator.Current - at least as an opt-in mechanism
Here's a PoC (tested for general happy case)
class OTelBridgePropagator : DistributedContextPropagator
{
private readonly TextMapPropagator _inner;
public OTelBridgePropagator(TextMapPropagator propagator)
{
_inner = propagator;
Fields = new ReadOnlyCollection<string>(_inner.Fields.ToArray());
}
public override IReadOnlyCollection<string> Fields { get; }
private PropagationContext Extract(object? carrier, PropagatorGetterCallback getter)
{
return _inner.Extract(default, carrier, (c, n) =>
{
getter.Invoke(c, n, out var value, out var values);
return values;
});
}
public override IEnumerable<KeyValuePair<string, string?>>? ExtractBaggage(object? carrier, PropagatorGetterCallback? getter)
{
if (getter == null)
{
return null;
}
return Extract(carrier, getter).Baggage.GetBaggage();
}
public override void ExtractTraceIdAndState(object? carrier, PropagatorGetterCallback? getter, out string? traceParent, out string? traceState)
{
traceParent = null;
traceState = null;
if (getter != null)
{
var context = Extract(carrier, getter);
var flags = (context.ActivityContext.TraceFlags == ActivityTraceFlags.Recorded) ? "01" : "00";
traceParent = $"00-{context.ActivityContext.TraceId}-{context.ActivityContext.SpanId}-{flags}";
traceState = context.ActivityContext.TraceState;
}
}
public override void Inject(Activity? activity, object? carrier, PropagatorSetterCallback? setter)
{
if (setter == null)
{
return;
}
if (activity != null)
{
foreach (var kvp in activity.Baggage)
{
Baggage.Current.SetBaggage(kvp.Key, kvp.Value);
}
}
var context = new PropagationContext(activity?.Context ?? default, Baggage.Current);
_inner.Inject(context, carrier, setter.Invoke);
}
}
Configuration
var otelPropagator = new CompositeTextMapPropagator(
new TextMapPropagator[] {
new TraceContextPropagator(),
new BaggagePropagator(),
});
Sdk.SetDefaultTextMapPropagator(otelPropagator);
DistributedContextPropagator.Current = new OTelBridgePropagator(otelPropagator); // this should be done by OTel SDK
As a result:
- users can add baggage using
Baggage.Current or via Activity.Baggage - both will end up in baggage header (or whatever is configured withSetDefaultTextMapPropagator
- Client/instrumentation libraries can use
DistributedContextPropagator.Current to propagate context - it will be consistent with one in the Sdk.SetDefaultTextMapPropagator
Related issues:
Package
OpenTelemetry.Api
Package Version
Description
In Azure SDKs we want to be able to propagate baggage between messaging producer and consumer.
However there are two baggages:
System.Diagnostics.Acitivity.Baggage- legacy(?) API that usesCorrelation-Contextheader (by default via default implementation ofDistributedContextPropagator)OpenTelemetry.Baggage.Current- OTel baggage available inOpenTelemetry.Apipackage.OTel discourages usage of
Activity.Baggage:opentelemetry-dotnet/src/OpenTelemetry.Api/README.md
Line 107 in c38cc27
As a result:
OpenTelemetry.Api- this is a showstopper for Azure SDK instrumentationsExpected Result
OTel and BCL should provide just one way to work with the baggage.
In the meantime, OTel can still provide consistent experience in the following way:
System.Diagnostics.DistributedContextPropagatorthat does OTel-compatible baggage propagation: W3C +baggageheader. It also reads any context provided in theActivity.Baggage(and never sets it)DistributedContextPropagator.Current- at least as an opt-in mechanismHere's a PoC (tested for general happy case)
Configuration
As a result:
Baggage.Currentor viaActivity.Baggage- both will end up inbaggageheader (or whatever is configured withSetDefaultTextMapPropagatorDistributedContextPropagator.Currentto propagate context - it will be consistent with one in theSdk.SetDefaultTextMapPropagatorRelated issues:
DistributedContextPropagatorcan be used to avoid injecting and extracting context in instrumentation libraries opentelemetry-dotnet-contrib#2013