Skip to content
Closed
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Features

- Add strict trace continuation support ([#4972](https://github.com/getsentry/sentry-dotnet/pull/4972))

### Fixes

- The SDK now logs a `Warning` instead of an `Error` when being ratelimited ([#4927](https://github.com/getsentry/sentry-dotnet/pull/4927))
Expand Down
4 changes: 4 additions & 0 deletions src/Sentry/BindableSentryOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ internal partial class BindableSentryOptions
public double? TracesSampleRate { get; set; }
public List<string>? TracePropagationTargets { get; set; }
public bool? PropagateTraceparent { get; set; }
public bool? StrictTraceContinuation { get; set; }
public string? OrgId { get; set; }
public double? ProfilesSampleRate { get; set; }
public StackTraceMode? StackTraceMode { get; set; }
public long? MaxAttachmentSize { get; set; }
Expand Down Expand Up @@ -97,6 +99,8 @@ public void ApplyTo(SentryOptions options)
options.ProfilesSampleRate = ProfilesSampleRate ?? options.ProfilesSampleRate;
options.TracePropagationTargets = TracePropagationTargets?.Select(s => new StringOrRegex(s)).ToList() ?? options.TracePropagationTargets;
options.PropagateTraceparent = PropagateTraceparent ?? options.PropagateTraceparent;
options.StrictTraceContinuation = StrictTraceContinuation ?? options.StrictTraceContinuation;
options.OrgId = OrgId ?? options.OrgId;
options.StackTraceMode = StackTraceMode ?? options.StackTraceMode;
options.MaxAttachmentSize = MaxAttachmentSize ?? options.MaxAttachmentSize;
options.DetectStartupTime = DetectStartupTime ?? options.DetectStartupTime;
Expand Down
24 changes: 22 additions & 2 deletions src/Sentry/Dsn.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System.Text.RegularExpressions;

namespace Sentry;

/// <summary>
Expand All @@ -8,6 +10,8 @@ namespace Sentry;
/// </remarks>
internal sealed class Dsn
{
private static readonly Regex OrgIdRegex = new(@"^o(\d+)\.", RegexOptions.Compiled);

/// <summary>
/// Source DSN string.
/// </summary>
Expand All @@ -33,6 +37,11 @@ internal sealed class Dsn
/// </summary>
public string PublicKey { get; }

/// <summary>
/// The organization ID extracted from the DSN host.
/// </summary>
public string? OrgId { get; }

/// <summary>
/// Sentry API's base URI.
/// </summary>
Expand All @@ -44,14 +53,16 @@ private Dsn(
string? path,
string? secretKey,
string publicKey,
Uri apiBaseUri)
Uri apiBaseUri,
string? orgId = null)
{
Source = source;
ProjectId = projectId;
Path = path;
SecretKey = secretKey;
PublicKey = publicKey;
ApiBaseUri = apiBaseUri;
OrgId = orgId;
}

public Uri GetStoreEndpointUri() => new(ApiBaseUri, "store/");
Expand Down Expand Up @@ -101,13 +112,22 @@ public static Dsn Parse(string dsn)
Path = $"{path}/api/{projectId}/"
}.Uri;

// Extract org ID from host (e.g., "o123.ingest.sentry.io" -> "123")
string? orgId = null;
var orgMatch = OrgIdRegex.Match(uri.DnsSafeHost);
if (orgMatch.Success)
{
orgId = orgMatch.Groups[1].Value;
}

return new Dsn(
dsn,
projectId,
path,
secretKey,
publicKey,
apiBaseUri);
apiBaseUri,
orgId);
}

public static Dsn? TryParse(string? dsn)
Expand Down
17 changes: 13 additions & 4 deletions src/Sentry/DynamicSamplingContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ private DynamicSamplingContext(SentryId traceId,
string? release = null,
string? environment = null,
string? transactionName = null,
IReplaySession? replaySession = null)
IReplaySession? replaySession = null,
string? orgId = null)
{
// Validate and set required values
if (traceId == SentryId.Empty)
Expand Down Expand Up @@ -95,6 +96,11 @@ private DynamicSamplingContext(SentryId traceId,
items.Add("replay_id", replayId.ToString());
}

if (!string.IsNullOrWhiteSpace(orgId))
{
items.Add("org_id", orgId);
}

_items = items;
}

Expand Down Expand Up @@ -200,7 +206,8 @@ public static DynamicSamplingContext CreateFromTransaction(TransactionTracer tra
release,
environment,
transactionName,
replaySession);
replaySession,
orgId: options.EffectiveOrgId);
}

public static DynamicSamplingContext CreateFromUnsampledTransaction(UnsampledTransaction transaction, SentryOptions options, IReplaySession? replaySession)
Expand All @@ -225,7 +232,8 @@ public static DynamicSamplingContext CreateFromUnsampledTransaction(UnsampledTra
release,
environment,
transactionName,
replaySession);
replaySession,
orgId: options.EffectiveOrgId);
}

public static DynamicSamplingContext CreateFromPropagationContext(SentryPropagationContext propagationContext, SentryOptions options, IReplaySession? replaySession)
Expand All @@ -241,7 +249,8 @@ public static DynamicSamplingContext CreateFromPropagationContext(SentryPropagat
null,
release: release,
environment: environment,
replaySession: replaySession
replaySession: replaySession,
orgId: options.EffectiveOrgId
);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Sentry/Internal/Hub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ public TransactionContext ContinueTrace(
string? name = null,
string? operation = null)
{
var propagationContext = SentryPropagationContext.CreateFromHeaders(_options.DiagnosticLogger, traceHeader, baggageHeader, _replaySession);
var propagationContext = SentryPropagationContext.CreateFromHeaders(_options.DiagnosticLogger, traceHeader, baggageHeader, _replaySession, _options);
ConfigureScope(static (scope, propagationContext) => scope.SetPropagationContext(propagationContext), propagationContext);

return new TransactionContext(
Expand Down
18 changes: 18 additions & 0 deletions src/Sentry/SentryOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1032,6 +1032,24 @@ public IList<StringOrRegex> TracePropagationTargets
/// <seealso href="https://develop.sentry.dev/sdk/telemetry/traces/#propagatetraceparent"/>
public bool PropagateTraceparent { get; set; }

/// <summary>
/// Controls whether the SDK requires matching org IDs from incoming baggage to continue a trace.
/// When true, both the SDK's org ID and the incoming baggage org ID must be present and match.
/// Default is false.
/// </summary>
public bool StrictTraceContinuation { get; set; }

/// <summary>
/// An optional organization ID. The SDK will try to extract it from the DSN in most cases
/// but you can provide it explicitly for self-hosted and Relay setups.
/// </summary>
public string? OrgId { get; set; }

/// <summary>
/// Returns the effective org ID, preferring the explicit config option over the DSN-parsed value.
/// </summary>
internal string? EffectiveOrgId => OrgId ?? _parsedDsn?.OrgId;

internal ITransactionProfilerFactory? TransactionProfilerFactory { get; set; }

private StackTraceMode? _stackTraceMode;
Expand Down
41 changes: 41 additions & 0 deletions src/Sentry/SentryPropagationContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ public SentryPropagationContext(SentryPropagationContext? other)
}

public static SentryPropagationContext CreateFromHeaders(IDiagnosticLogger? logger, SentryTraceHeader? traceHeader, BaggageHeader? baggageHeader, IReplaySession replaySession)
{
return CreateFromHeaders(logger, traceHeader, baggageHeader, replaySession, null);
}

public static SentryPropagationContext CreateFromHeaders(IDiagnosticLogger? logger, SentryTraceHeader? traceHeader, BaggageHeader? baggageHeader, IReplaySession replaySession, SentryOptions? options)
{
logger?.LogDebug("Creating a propagation context from headers.");

Expand All @@ -58,7 +63,43 @@ public static SentryPropagationContext CreateFromHeaders(IDiagnosticLogger? logg
return new SentryPropagationContext();
}

if (options != null && !ShouldContinueTrace(options, baggageHeader))
{
logger?.LogDebug("Not continuing trace due to org ID mismatch.");
return new SentryPropagationContext();
}

var dynamicSamplingContext = baggageHeader?.CreateDynamicSamplingContext(replaySession);
return new SentryPropagationContext(traceHeader.TraceId, traceHeader.SpanId, dynamicSamplingContext);
}

internal static bool ShouldContinueTrace(SentryOptions options, BaggageHeader? baggageHeader)
{
var sdkOrgId = options.EffectiveOrgId;

string? baggageOrgId = null;
if (baggageHeader != null)
{
var sentryMembers = baggageHeader.GetSentryMembers();
sentryMembers.TryGetValue("org_id", out baggageOrgId);
}

// Mismatched org IDs always reject regardless of strict mode
if (sdkOrgId != null && baggageOrgId != null && sdkOrgId != baggageOrgId)
{
return false;
}

// In strict mode, both must be present and match (unless both are missing)
if (options.StrictTraceContinuation)
{
if (sdkOrgId == null && baggageOrgId == null)
{
return true;
}
return sdkOrgId != null && sdkOrgId == baggageOrgId;
}

return true;
}
}
28 changes: 28 additions & 0 deletions test/Sentry.Tests/Protocol/DsnTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -301,4 +301,32 @@ private static void AssertEqual(DsnTestCase @case, Dsn dsn)

Assert.Equal(@case, uri);
}

[Fact]
public void Parse_OrgIdFromHost()
{
var dsn = Dsn.Parse("https://key@o123.ingest.sentry.io/456");
Assert.Equal("123", dsn.OrgId);
}

[Fact]
public void Parse_SingleDigitOrgId()
{
var dsn = Dsn.Parse("https://key@o1.ingest.us.sentry.io/456");
Assert.Equal("1", dsn.OrgId);
}

[Fact]
public void Parse_NoOrgIdInHost()
{
var dsn = Dsn.Parse("https://key@sentry.io/456");
Assert.Null(dsn.OrgId);
}

[Fact]
public void Parse_NonStandardHost_NoOrgId()
{
var dsn = Dsn.Parse("http://key@localhost:9000/456");
Assert.Null(dsn.OrgId);
}
}
73 changes: 73 additions & 0 deletions test/Sentry.Tests/SentryPropagationContextTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,77 @@
Assert.Equal("bfd31b89a59d41c99d96dc2baf840ecd", Assert.Contains("replay_id", dsc.Items));
}
}

// Decision matrix tests for ShouldContinueTrace

[Theory]
// strict=false cases
[InlineData("1", "1", false, true)] // matching orgs → continue
[InlineData(null, "1", false, true)] // baggage missing → continue
[InlineData("1", null, false, true)] // SDK missing → continue
[InlineData(null, null, false, true)] // both missing → continue
[InlineData("1", "2", false, false)] // mismatch → new trace
// strict=true cases
[InlineData("1", "1", true, true)] // matching orgs → continue
[InlineData(null, "1", true, false)] // baggage missing → new trace
[InlineData("1", null, true, false)] // SDK missing → new trace
[InlineData(null, null, true, true)] // both missing → continue
[InlineData("1", "2", true, false)] // mismatch → new trace
public void ShouldContinueTrace_DecisionMatrix(string baggageOrgId, string sdkOrgId, bool strict, bool expected)
{
var options = new SentryOptions
{
Dsn = ValidDsn,
StrictTraceContinuation = strict
};
if (sdkOrgId != null)
{
options.OrgId = sdkOrgId;
}

BaggageHeader baggage = null;
if (baggageOrgId != null)
{
baggage = BaggageHeader.TryParse($"sentry-trace_id=bc6d53f15eb88f4320054569b8c553d4,sentry-org_id={baggageOrgId}");
}
else
{
baggage = BaggageHeader.TryParse("sentry-trace_id=bc6d53f15eb88f4320054569b8c553d4");
}

var result = SentryPropagationContext.ShouldContinueTrace(options, baggage);
Assert.Equal(expected, result);
}

[Fact]
public void CreateFromHeaders_WithOrgMismatch_StartsNewTrace()
{
var options = new SentryOptions
{
Dsn = "https://key@o2.ingest.sentry.io/456",
StrictTraceContinuation = false
};

var traceHeader = SentryTraceHeader.Parse("bc6d53f15eb88f4320054569b8c553d4-b72fa28504b07285-1");
var baggage = BaggageHeader.TryParse("sentry-trace_id=bc6d53f15eb88f4320054569b8c553d4,sentry-org_id=1");

var propagationContext = SentryPropagationContext.CreateFromHeaders(null, traceHeader, baggage, _fixture.InactiveReplaySession, options);

Check failure on line 218 in test/Sentry.Tests/SentryPropagationContextTests.cs

View workflow job for this annotation

GitHub Actions / .NET (win-arm64)

Sentry.Tests.SentryPropagationContextTests.CreateFromHeaders_WithOrgMismatch_StartsNewTrace

Assert.NotEqual() Failure: Values are equal Expected: Not bc6d53f15eb88f4320054569b8c553d4 Actual: bc6d53f15eb88f4320054569b8c553d4
Assert.NotEqual(SentryId.Parse("bc6d53f15eb88f4320054569b8c553d4"), propagationContext.TraceId);

Check failure on line 219 in test/Sentry.Tests/SentryPropagationContextTests.cs

View workflow job for this annotation

GitHub Actions / .NET (linux-musl-arm64)

Sentry.Tests.SentryPropagationContextTests.CreateFromHeaders_WithOrgMismatch_StartsNewTrace

Assert.NotEqual() Failure: Values are equal Expected: Not bc6d53f15eb88f4320054569b8c553d4 Actual: bc6d53f15eb88f4320054569b8c553d4

Check failure on line 219 in test/Sentry.Tests/SentryPropagationContextTests.cs

View workflow job for this annotation

GitHub Actions / .NET (linux-musl-arm64)

Sentry.Tests.SentryPropagationContextTests.CreateFromHeaders_WithOrgMismatch_StartsNewTrace

Assert.NotEqual() Failure: Values are equal Expected: Not bc6d53f15eb88f4320054569b8c553d4 Actual: bc6d53f15eb88f4320054569b8c553d4

Check failure on line 219 in test/Sentry.Tests/SentryPropagationContextTests.cs

View workflow job for this annotation

GitHub Actions / .NET (linux-musl-arm64)

Sentry.Tests.SentryPropagationContextTests.CreateFromHeaders_WithOrgMismatch_StartsNewTrace

Assert.NotEqual() Failure: Values are equal Expected: Not bc6d53f15eb88f4320054569b8c553d4 Actual: bc6d53f15eb88f4320054569b8c553d4

Check failure on line 219 in test/Sentry.Tests/SentryPropagationContextTests.cs

View workflow job for this annotation

GitHub Actions / .NET (linux-arm64)

Sentry.Tests.SentryPropagationContextTests.CreateFromHeaders_WithOrgMismatch_StartsNewTrace

Assert.NotEqual() Failure: Values are equal Expected: Not bc6d53f15eb88f4320054569b8c553d4 Actual: bc6d53f15eb88f4320054569b8c553d4

Check failure on line 219 in test/Sentry.Tests/SentryPropagationContextTests.cs

View workflow job for this annotation

GitHub Actions / .NET (linux-arm64)

Sentry.Tests.SentryPropagationContextTests.CreateFromHeaders_WithOrgMismatch_StartsNewTrace

Assert.NotEqual() Failure: Values are equal Expected: Not bc6d53f15eb88f4320054569b8c553d4 Actual: bc6d53f15eb88f4320054569b8c553d4

Check failure on line 219 in test/Sentry.Tests/SentryPropagationContextTests.cs

View workflow job for this annotation

GitHub Actions / .NET (linux-arm64)

Sentry.Tests.SentryPropagationContextTests.CreateFromHeaders_WithOrgMismatch_StartsNewTrace

Assert.NotEqual() Failure: Values are equal Expected: Not bc6d53f15eb88f4320054569b8c553d4 Actual: bc6d53f15eb88f4320054569b8c553d4

Check failure on line 219 in test/Sentry.Tests/SentryPropagationContextTests.cs

View workflow job for this annotation

GitHub Actions / .NET (linux-musl-x64)

Sentry.Tests.SentryPropagationContextTests.CreateFromHeaders_WithOrgMismatch_StartsNewTrace

Assert.NotEqual() Failure: Values are equal Expected: Not bc6d53f15eb88f4320054569b8c553d4 Actual: bc6d53f15eb88f4320054569b8c553d4

Check failure on line 219 in test/Sentry.Tests/SentryPropagationContextTests.cs

View workflow job for this annotation

GitHub Actions / .NET (linux-musl-x64)

Sentry.Tests.SentryPropagationContextTests.CreateFromHeaders_WithOrgMismatch_StartsNewTrace

Assert.NotEqual() Failure: Values are equal Expected: Not bc6d53f15eb88f4320054569b8c553d4 Actual: bc6d53f15eb88f4320054569b8c553d4

Check failure on line 219 in test/Sentry.Tests/SentryPropagationContextTests.cs

View workflow job for this annotation

GitHub Actions / .NET (linux-musl-x64)

Sentry.Tests.SentryPropagationContextTests.CreateFromHeaders_WithOrgMismatch_StartsNewTrace

Assert.NotEqual() Failure: Values are equal Expected: Not bc6d53f15eb88f4320054569b8c553d4 Actual: bc6d53f15eb88f4320054569b8c553d4

Check failure on line 219 in test/Sentry.Tests/SentryPropagationContextTests.cs

View workflow job for this annotation

GitHub Actions / .NET (linux-x64)

Sentry.Tests.SentryPropagationContextTests.CreateFromHeaders_WithOrgMismatch_StartsNewTrace

Assert.NotEqual() Failure: Values are equal Expected: Not bc6d53f15eb88f4320054569b8c553d4 Actual: bc6d53f15eb88f4320054569b8c553d4

Check failure on line 219 in test/Sentry.Tests/SentryPropagationContextTests.cs

View workflow job for this annotation

GitHub Actions / .NET (linux-x64)

Sentry.Tests.SentryPropagationContextTests.CreateFromHeaders_WithOrgMismatch_StartsNewTrace

Assert.NotEqual() Failure: Values are equal Expected: Not bc6d53f15eb88f4320054569b8c553d4 Actual: bc6d53f15eb88f4320054569b8c553d4

Check failure on line 219 in test/Sentry.Tests/SentryPropagationContextTests.cs

View workflow job for this annotation

GitHub Actions / .NET (linux-x64)

Sentry.Tests.SentryPropagationContextTests.CreateFromHeaders_WithOrgMismatch_StartsNewTrace

Assert.NotEqual() Failure: Values are equal Expected: Not bc6d53f15eb88f4320054569b8c553d4 Actual: bc6d53f15eb88f4320054569b8c553d4

Check failure on line 219 in test/Sentry.Tests/SentryPropagationContextTests.cs

View workflow job for this annotation

GitHub Actions / .NET (win-arm64)

Sentry.Tests.SentryPropagationContextTests.CreateFromHeaders_WithOrgMismatch_StartsNewTrace

Assert.NotEqual() Failure: Values are equal Expected: Not bc6d53f15eb88f4320054569b8c553d4 Actual: bc6d53f15eb88f4320054569b8c553d4

Check failure on line 219 in test/Sentry.Tests/SentryPropagationContextTests.cs

View workflow job for this annotation

GitHub Actions / .NET (win-arm64)

Sentry.Tests.SentryPropagationContextTests.CreateFromHeaders_WithOrgMismatch_StartsNewTrace

Assert.NotEqual() Failure: Values are equal Expected: Not bc6d53f15eb88f4320054569b8c553d4 Actual: bc6d53f15eb88f4320054569b8c553d4

Check failure on line 219 in test/Sentry.Tests/SentryPropagationContextTests.cs

View workflow job for this annotation

GitHub Actions / .NET (win-arm64)

Sentry.Tests.SentryPropagationContextTests.CreateFromHeaders_WithOrgMismatch_StartsNewTrace

Assert.NotEqual() Failure: Values are equal Expected: Not bc6d53f15eb88f4320054569b8c553d4 Actual: bc6d53f15eb88f4320054569b8c553d4

Check failure on line 219 in test/Sentry.Tests/SentryPropagationContextTests.cs

View workflow job for this annotation

GitHub Actions / .NET (win-x64)

Sentry.Tests.SentryPropagationContextTests.CreateFromHeaders_WithOrgMismatch_StartsNewTrace

Assert.NotEqual() Failure: Values are equal Expected: Not bc6d53f15eb88f4320054569b8c553d4 Actual: bc6d53f15eb88f4320054569b8c553d4

Check failure on line 219 in test/Sentry.Tests/SentryPropagationContextTests.cs

View workflow job for this annotation

GitHub Actions / .NET (win-x64)

Sentry.Tests.SentryPropagationContextTests.CreateFromHeaders_WithOrgMismatch_StartsNewTrace

Assert.NotEqual() Failure: Values are equal Expected: Not bc6d53f15eb88f4320054569b8c553d4 Actual: bc6d53f15eb88f4320054569b8c553d4

Check failure on line 219 in test/Sentry.Tests/SentryPropagationContextTests.cs

View workflow job for this annotation

GitHub Actions / .NET (win-x64)

Sentry.Tests.SentryPropagationContextTests.CreateFromHeaders_WithOrgMismatch_StartsNewTrace

Assert.NotEqual() Failure: Values are equal Expected: Not bc6d53f15eb88f4320054569b8c553d4 Actual: bc6d53f15eb88f4320054569b8c553d4

Check failure on line 219 in test/Sentry.Tests/SentryPropagationContextTests.cs

View workflow job for this annotation

GitHub Actions / .NET (macos)

Sentry.Tests.SentryPropagationContextTests.CreateFromHeaders_WithOrgMismatch_StartsNewTrace

Assert.NotEqual() Failure: Values are equal Expected: Not bc6d53f15eb88f4320054569b8c553d4 Actual: bc6d53f15eb88f4320054569b8c553d4

Check failure on line 219 in test/Sentry.Tests/SentryPropagationContextTests.cs

View workflow job for this annotation

GitHub Actions / .NET (macos)

Sentry.Tests.SentryPropagationContextTests.CreateFromHeaders_WithOrgMismatch_StartsNewTrace

Assert.NotEqual() Failure: Values are equal Expected: Not bc6d53f15eb88f4320054569b8c553d4 Actual: bc6d53f15eb88f4320054569b8c553d4

Check failure on line 219 in test/Sentry.Tests/SentryPropagationContextTests.cs

View workflow job for this annotation

GitHub Actions / .NET (macos)

Sentry.Tests.SentryPropagationContextTests.CreateFromHeaders_WithOrgMismatch_StartsNewTrace

Assert.NotEqual() Failure: Values are equal Expected: Not bc6d53f15eb88f4320054569b8c553d4 Actual: bc6d53f15eb88f4320054569b8c553d4
}

Check failure on line 220 in test/Sentry.Tests/SentryPropagationContextTests.cs

View workflow job for this annotation

GitHub Actions / .NET (win-x64)

Sentry.Tests.SentryPropagationContextTests.CreateFromHeaders_WithOrgMismatch_StartsNewTrace

Assert.NotEqual() Failure: Values are equal Expected: Not bc6d53f15eb88f4320054569b8c553d4 Actual: bc6d53f15eb88f4320054569b8c553d4

[Fact]
public void CreateFromHeaders_WithOrgMatch_ContinuesTrace()
{
var options = new SentryOptions
{
Dsn = "https://key@o1.ingest.sentry.io/456",
StrictTraceContinuation = false
};

var traceHeader = SentryTraceHeader.Parse("bc6d53f15eb88f4320054569b8c553d4-b72fa28504b07285-1");
var baggage = BaggageHeader.TryParse("sentry-trace_id=bc6d53f15eb88f4320054569b8c553d4,sentry-org_id=1,sentry-public_key=key,sentry-sample_rate=1.0,sentry-sample_rand=0.5000,sentry-sampled=true");

var propagationContext = SentryPropagationContext.CreateFromHeaders(null, traceHeader, baggage, _fixture.InactiveReplaySession, options);
Assert.Equal(SentryId.Parse("bc6d53f15eb88f4320054569b8c553d4"), propagationContext.TraceId);
}
}
Loading