Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public static bool HasStarted(HttpContextBase context, out Activity? aspNetActiv
Activity? activity = null;
try
{
Baggage.Current = propagationContext.Baggage;
activity = onRequestStartedCallback?.Invoke(context, propagationContext.ActivityContext);
}
catch (Exception callbackEx)
Expand All @@ -71,8 +72,6 @@ public static bool HasStarted(HttpContextBase context, out Activity? aspNetActiv
{
if (textMapPropagator is not TraceContextPropagator)
{
Baggage.Current = propagationContext.Baggage;

context.Items[ContextKey] = new ContextHolder(activity, RuntimeContext.GetValue(BaggageSlotName));
}
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

* Propagate baggage before `Activity` is created.
([#3820](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/3820))

## 1.15.0

Released 2026-Jan-21
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

using System.Collections;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Web;
using OpenTelemetry.Context.Propagation;
Expand Down Expand Up @@ -56,6 +54,16 @@ public void Has_Started_Returns_Correctly()
Assert.Equal(activity, aspNetActivity);
}

[Fact]
public void Baggage_Is_Restored_Before_Starting_Activity()
{
this.EnableListener();
var propagator = new MockTextMapPropagator();
var context = HttpContextHelper.GetFakeHttpContextBase();
using var activity = ActivityHelper.StartAspNetActivity(propagator, context, this.StartTestActivityWithBaggageAttribute);
Assert.Equal(MockTextMapPropagator.BaggageValue, activity?.Tags.FirstOrDefault(kv => kv.Key == MockTextMapPropagator.BaggageKey).Value);
}

[Fact]
public async Task Can_Restore_Activity()
{
Expand Down Expand Up @@ -507,72 +515,45 @@ private void EnableListener(Action<Activity>? onStarted = null, Action<Activity>
return this.testActivitySource.StartActivity(ActivityKind.Server, activityContext);
}

private class TestHttpRequest : HttpRequestBase
private Activity? StartTestActivityWithBaggageAttribute(HttpContextBase httpContext, ActivityContext activityContext)
{
private readonly NameValueCollection headers = [];

public override NameValueCollection Headers => this.headers;

public override UnvalidatedRequestValuesBase Unvalidated => new TestUnvalidatedRequestValues(this.headers);
var baggageValue = Baggage.Current.GetBaggage(MockTextMapPropagator.BaggageKey);
var activity = this.testActivitySource.StartActivity(ActivityKind.Server, activityContext);
activity?.AddTag(MockTextMapPropagator.BaggageKey, baggageValue);
return activity;
}

private class TestUnvalidatedRequestValues : UnvalidatedRequestValuesBase
{
public TestUnvalidatedRequestValues(NameValueCollection headers)
{
this.Headers = headers;
}

public override NameValueCollection Headers { get; }
}

private class TestHttpResponse : HttpResponseBase
{
}

private class TestHttpServerUtility : HttpServerUtilityBase
private class NoopTextMapPropagator : TextMapPropagator
{
private readonly HttpContextBase context;
public override ISet<string>? Fields => null;

public TestHttpServerUtility(HttpContextBase context)
public override PropagationContext Extract<T>(PropagationContext context, T carrier, Func<T, string, IEnumerable<string>?> getter)
{
this.context = context;
return default;
}

public override Exception GetLastError()
public override void Inject<T>(PropagationContext context, T carrier, Action<T, string, string> setter)
{
return this.context.Error;
}
}

private class TestHttpContext : HttpContextBase
private class MockTextMapPropagator : TextMapPropagator
{
private readonly Hashtable items;

public TestHttpContext(Exception? error = null)
{
this.Server = new TestHttpServerUtility(this);
this.items = [];
this.Error = error;
}

public override HttpRequestBase Request { get; } = new TestHttpRequest();

/// <inheritdoc />
public override IDictionary Items => this.items;

public override Exception? Error { get; }
internal const string BaggageKey = "TestKey1";
internal const string BaggageValue = "TestValue1";

public override HttpServerUtilityBase Server { get; }
}

private class NoopTextMapPropagator : TextMapPropagator
{
public override ISet<string>? Fields => null;

public override PropagationContext Extract<T>(PropagationContext context, T carrier, Func<T, string, IEnumerable<string>?> getter)
{
return default;
var baggage = Baggage.Create(new Dictionary<string, string>
{
{ BaggageKey, BaggageValue },
});

var activityContext = new ActivityContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.Recorded);

return new PropagationContext(activityContext, baggage);
}

public override void Inject<T>(PropagationContext context, T carrier, Action<T, string, string> setter)
Expand Down