diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6cc5ac8e26..4b171ed991 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,7 @@
### Features
+- The SDK now provides and overload of `ContinueTrace` that accepts headers as `string` ([#2601](https://github.com/getsentry/sentry-dotnet/pull/2601))
- Sentry tracing middleware now gets configured automatically ([#2602](https://github.com/getsentry/sentry-dotnet/pull/2602))
### Dependencies
@@ -11,6 +12,7 @@
- Bump CLI from v2.20.6 to v2.20.7 ([#2604](https://github.com/getsentry/sentry-dotnet/pull/2604))
- [changelog](https://github.com/getsentry/sentry-cli/blob/master/CHANGELOG.md#2207)
- [diff](https://github.com/getsentry/sentry-cli/compare/2.20.6...2.20.7)
+
## 3.39.1
### Fixes
diff --git a/src/Sentry/Extensibility/DisabledHub.cs b/src/Sentry/Extensibility/DisabledHub.cs
index 6ea3e66da2..8a5ef6c8d2 100644
--- a/src/Sentry/Extensibility/DisabledHub.cs
+++ b/src/Sentry/Extensibility/DisabledHub.cs
@@ -80,7 +80,20 @@ public void BindException(Exception exception, ISpan span)
public BaggageHeader? GetBaggage() => null;
///
- /// Returns null.
+ /// Returns sampled out transaction context.
+ ///
+ public TransactionContext ContinueTrace(
+ string? traceHeader,
+ string? baggageHeader,
+ string? name = null,
+ string? operation = null)
+ {
+ // Transactions from DisabledHub are always sampled out
+ return new TransactionContext( name ?? string.Empty, operation ?? string.Empty, false);
+ }
+
+ ///
+ /// Returns sampled out transaction context.
///
public TransactionContext ContinueTrace(
SentryTraceHeader? traceHeader,
diff --git a/src/Sentry/Extensibility/HubAdapter.cs b/src/Sentry/Extensibility/HubAdapter.cs
index 6989cd1ac9..d9e86363f4 100644
--- a/src/Sentry/Extensibility/HubAdapter.cs
+++ b/src/Sentry/Extensibility/HubAdapter.cs
@@ -113,6 +113,17 @@ public void BindException(Exception exception, ISpan span) =>
public BaggageHeader? GetBaggage()
=> SentrySdk.GetBaggage();
+ ///
+ /// Forwards the call to .
+ ///
+ [DebuggerStepThrough]
+ public TransactionContext ContinueTrace(
+ string? traceHeader,
+ string? baggageHeader,
+ string? name = null,
+ string? operation = null)
+ => SentrySdk.ContinueTrace(traceHeader, baggageHeader, name, operation);
+
///
/// Forwards the call to .
///
diff --git a/src/Sentry/IHub.cs b/src/Sentry/IHub.cs
index 570e60b499..f2c20b1aee 100644
--- a/src/Sentry/IHub.cs
+++ b/src/Sentry/IHub.cs
@@ -49,6 +49,18 @@ ITransaction StartTransaction(
///
BaggageHeader? GetBaggage();
+ ///
+ /// Continues a trace based on HTTP header values provided as strings.
+ ///
+ ///
+ /// If no "sentry-trace" header is provided a random trace ID and span ID is created.
+ ///
+ TransactionContext ContinueTrace(
+ string? traceHeader,
+ string? baggageHeader,
+ string? name = null,
+ string? operation = null);
+
///
/// Continues a trace based on HTTP header values.
///
diff --git a/src/Sentry/Internal/Hub.cs b/src/Sentry/Internal/Hub.cs
index e49db790fa..4a426f6da2 100644
--- a/src/Sentry/Internal/Hub.cs
+++ b/src/Sentry/Internal/Hub.cs
@@ -219,6 +219,27 @@ public BaggageHeader GetBaggage()
return propagationContext.GetOrCreateDynamicSamplingContext(_options).ToBaggageHeader();
}
+ public TransactionContext ContinueTrace(
+ string? traceHeader,
+ string? baggageHeader,
+ string? name = null,
+ string? operation = null)
+ {
+ SentryTraceHeader? sentryTraceHeader = null;
+ if (traceHeader is not null)
+ {
+ sentryTraceHeader = SentryTraceHeader.Parse(traceHeader);
+ }
+
+ BaggageHeader? sentryBaggageHeader = null;
+ if (baggageHeader is not null)
+ {
+ sentryBaggageHeader = BaggageHeader.TryParse(baggageHeader, onlySentry: true);
+ }
+
+ return ContinueTrace(sentryTraceHeader, sentryBaggageHeader, name, operation);
+ }
+
public TransactionContext ContinueTrace(
SentryTraceHeader? traceHeader,
BaggageHeader? baggageHeader,
diff --git a/src/Sentry/SentrySdk.cs b/src/Sentry/SentrySdk.cs
index 723a220241..c0bb979b23 100644
--- a/src/Sentry/SentrySdk.cs
+++ b/src/Sentry/SentrySdk.cs
@@ -624,6 +624,20 @@ public static void BindException(Exception exception, ISpan span)
public static BaggageHeader? GetBaggage()
=> CurrentHub.GetBaggage();
+ ///
+ /// Continues a trace based on HTTP header values provided as strings.
+ ///
+ ///
+ /// If no "sentry-trace" header is provided a random trace ID and span ID is created.
+ ///
+ [DebuggerStepThrough]
+ public static TransactionContext ContinueTrace(
+ string? traceHeader,
+ string? baggageHeader,
+ string? name = null,
+ string? operation = null)
+ => CurrentHub.ContinueTrace(traceHeader, baggageHeader, name, operation);
+
///
/// Continues a trace based on HTTP header values.
///
diff --git a/test/Sentry.Tests/ApiApprovalTests.Run.Core3_1.verified.txt b/test/Sentry.Tests/ApiApprovalTests.Run.Core3_1.verified.txt
index 27e6905bae..b09c5062dd 100644
--- a/test/Sentry.Tests/ApiApprovalTests.Run.Core3_1.verified.txt
+++ b/test/Sentry.Tests/ApiApprovalTests.Run.Core3_1.verified.txt
@@ -231,6 +231,7 @@ namespace Sentry
void BindException(System.Exception exception, Sentry.ISpan span);
Sentry.SentryId CaptureEvent(Sentry.SentryEvent evt, System.Action configureScope);
Sentry.TransactionContext ContinueTrace(Sentry.SentryTraceHeader? traceHeader, Sentry.BaggageHeader? baggageHeader, string? name = null, string? operation = null);
+ Sentry.TransactionContext ContinueTrace(string? traceHeader, string? baggageHeader, string? name = null, string? operation = null);
void EndSession(Sentry.SessionEndStatus status = 0);
Sentry.BaggageHeader? GetBaggage();
Sentry.ISpan? GetSpan();
@@ -760,6 +761,7 @@ namespace Sentry
public static void ConfigureScope(System.Action configureScope) { }
public static System.Threading.Tasks.Task ConfigureScopeAsync(System.Func configureScope) { }
public static Sentry.TransactionContext ContinueTrace(Sentry.SentryTraceHeader? traceHeader, Sentry.BaggageHeader? baggageHeader, string? name = null, string? operation = null) { }
+ public static Sentry.TransactionContext ContinueTrace(string? traceHeader, string? baggageHeader, string? name = null, string? operation = null) { }
public static void EndSession(Sentry.SessionEndStatus status = 0) { }
public static void Flush() { }
public static void Flush(System.TimeSpan timeout) { }
@@ -1236,6 +1238,7 @@ namespace Sentry.Extensibility
public void ConfigureScope(System.Action configureScope) { }
public System.Threading.Tasks.Task ConfigureScopeAsync(System.Func configureScope) { }
public Sentry.TransactionContext ContinueTrace(Sentry.SentryTraceHeader? traceHeader, Sentry.BaggageHeader? baggageHeader, string? name = null, string? operation = null) { }
+ public Sentry.TransactionContext ContinueTrace(string? traceHeader, string? baggageHeader, string? name = null, string? operation = null) { }
public void Dispose() { }
public void EndSession(Sentry.SessionEndStatus status = 0) { }
public System.Threading.Tasks.Task FlushAsync(System.TimeSpan timeout) { }
@@ -1277,6 +1280,7 @@ namespace Sentry.Extensibility
public void ConfigureScope(System.Action configureScope) { }
public System.Threading.Tasks.Task ConfigureScopeAsync(System.Func configureScope) { }
public Sentry.TransactionContext ContinueTrace(Sentry.SentryTraceHeader? traceHeader, Sentry.BaggageHeader? baggageHeader, string? name = null, string? operation = null) { }
+ public Sentry.TransactionContext ContinueTrace(string? traceHeader, string? baggageHeader, string? name = null, string? operation = null) { }
public void EndSession(Sentry.SessionEndStatus status = 0) { }
public System.Threading.Tasks.Task FlushAsync(System.TimeSpan timeout) { }
public Sentry.BaggageHeader? GetBaggage() { }
diff --git a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet6_0.verified.txt b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet6_0.verified.txt
index 875f2835fc..e87375aed5 100644
--- a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet6_0.verified.txt
+++ b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet6_0.verified.txt
@@ -231,6 +231,7 @@ namespace Sentry
void BindException(System.Exception exception, Sentry.ISpan span);
Sentry.SentryId CaptureEvent(Sentry.SentryEvent evt, System.Action configureScope);
Sentry.TransactionContext ContinueTrace(Sentry.SentryTraceHeader? traceHeader, Sentry.BaggageHeader? baggageHeader, string? name = null, string? operation = null);
+ Sentry.TransactionContext ContinueTrace(string? traceHeader, string? baggageHeader, string? name = null, string? operation = null);
void EndSession(Sentry.SessionEndStatus status = 0);
Sentry.BaggageHeader? GetBaggage();
Sentry.ISpan? GetSpan();
@@ -761,6 +762,7 @@ namespace Sentry
public static void ConfigureScope(System.Action configureScope) { }
public static System.Threading.Tasks.Task ConfigureScopeAsync(System.Func configureScope) { }
public static Sentry.TransactionContext ContinueTrace(Sentry.SentryTraceHeader? traceHeader, Sentry.BaggageHeader? baggageHeader, string? name = null, string? operation = null) { }
+ public static Sentry.TransactionContext ContinueTrace(string? traceHeader, string? baggageHeader, string? name = null, string? operation = null) { }
public static void EndSession(Sentry.SessionEndStatus status = 0) { }
public static void Flush() { }
public static void Flush(System.TimeSpan timeout) { }
@@ -1237,6 +1239,7 @@ namespace Sentry.Extensibility
public void ConfigureScope(System.Action configureScope) { }
public System.Threading.Tasks.Task ConfigureScopeAsync(System.Func configureScope) { }
public Sentry.TransactionContext ContinueTrace(Sentry.SentryTraceHeader? traceHeader, Sentry.BaggageHeader? baggageHeader, string? name = null, string? operation = null) { }
+ public Sentry.TransactionContext ContinueTrace(string? traceHeader, string? baggageHeader, string? name = null, string? operation = null) { }
public void Dispose() { }
public void EndSession(Sentry.SessionEndStatus status = 0) { }
public System.Threading.Tasks.Task FlushAsync(System.TimeSpan timeout) { }
@@ -1278,6 +1281,7 @@ namespace Sentry.Extensibility
public void ConfigureScope(System.Action configureScope) { }
public System.Threading.Tasks.Task ConfigureScopeAsync(System.Func configureScope) { }
public Sentry.TransactionContext ContinueTrace(Sentry.SentryTraceHeader? traceHeader, Sentry.BaggageHeader? baggageHeader, string? name = null, string? operation = null) { }
+ public Sentry.TransactionContext ContinueTrace(string? traceHeader, string? baggageHeader, string? name = null, string? operation = null) { }
public void EndSession(Sentry.SessionEndStatus status = 0) { }
public System.Threading.Tasks.Task FlushAsync(System.TimeSpan timeout) { }
public Sentry.BaggageHeader? GetBaggage() { }
diff --git a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet7_0.verified.txt b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet7_0.verified.txt
index 875f2835fc..e87375aed5 100644
--- a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet7_0.verified.txt
+++ b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet7_0.verified.txt
@@ -231,6 +231,7 @@ namespace Sentry
void BindException(System.Exception exception, Sentry.ISpan span);
Sentry.SentryId CaptureEvent(Sentry.SentryEvent evt, System.Action configureScope);
Sentry.TransactionContext ContinueTrace(Sentry.SentryTraceHeader? traceHeader, Sentry.BaggageHeader? baggageHeader, string? name = null, string? operation = null);
+ Sentry.TransactionContext ContinueTrace(string? traceHeader, string? baggageHeader, string? name = null, string? operation = null);
void EndSession(Sentry.SessionEndStatus status = 0);
Sentry.BaggageHeader? GetBaggage();
Sentry.ISpan? GetSpan();
@@ -761,6 +762,7 @@ namespace Sentry
public static void ConfigureScope(System.Action configureScope) { }
public static System.Threading.Tasks.Task ConfigureScopeAsync(System.Func configureScope) { }
public static Sentry.TransactionContext ContinueTrace(Sentry.SentryTraceHeader? traceHeader, Sentry.BaggageHeader? baggageHeader, string? name = null, string? operation = null) { }
+ public static Sentry.TransactionContext ContinueTrace(string? traceHeader, string? baggageHeader, string? name = null, string? operation = null) { }
public static void EndSession(Sentry.SessionEndStatus status = 0) { }
public static void Flush() { }
public static void Flush(System.TimeSpan timeout) { }
@@ -1237,6 +1239,7 @@ namespace Sentry.Extensibility
public void ConfigureScope(System.Action configureScope) { }
public System.Threading.Tasks.Task ConfigureScopeAsync(System.Func configureScope) { }
public Sentry.TransactionContext ContinueTrace(Sentry.SentryTraceHeader? traceHeader, Sentry.BaggageHeader? baggageHeader, string? name = null, string? operation = null) { }
+ public Sentry.TransactionContext ContinueTrace(string? traceHeader, string? baggageHeader, string? name = null, string? operation = null) { }
public void Dispose() { }
public void EndSession(Sentry.SessionEndStatus status = 0) { }
public System.Threading.Tasks.Task FlushAsync(System.TimeSpan timeout) { }
@@ -1278,6 +1281,7 @@ namespace Sentry.Extensibility
public void ConfigureScope(System.Action configureScope) { }
public System.Threading.Tasks.Task ConfigureScopeAsync(System.Func configureScope) { }
public Sentry.TransactionContext ContinueTrace(Sentry.SentryTraceHeader? traceHeader, Sentry.BaggageHeader? baggageHeader, string? name = null, string? operation = null) { }
+ public Sentry.TransactionContext ContinueTrace(string? traceHeader, string? baggageHeader, string? name = null, string? operation = null) { }
public void EndSession(Sentry.SessionEndStatus status = 0) { }
public System.Threading.Tasks.Task FlushAsync(System.TimeSpan timeout) { }
public Sentry.BaggageHeader? GetBaggage() { }
diff --git a/test/Sentry.Tests/ApiApprovalTests.Run.Net4_8.verified.txt b/test/Sentry.Tests/ApiApprovalTests.Run.Net4_8.verified.txt
index dd4c09e8ed..a3174ce82f 100644
--- a/test/Sentry.Tests/ApiApprovalTests.Run.Net4_8.verified.txt
+++ b/test/Sentry.Tests/ApiApprovalTests.Run.Net4_8.verified.txt
@@ -230,6 +230,7 @@ namespace Sentry
void BindException(System.Exception exception, Sentry.ISpan span);
Sentry.SentryId CaptureEvent(Sentry.SentryEvent evt, System.Action configureScope);
Sentry.TransactionContext ContinueTrace(Sentry.SentryTraceHeader? traceHeader, Sentry.BaggageHeader? baggageHeader, string? name = null, string? operation = null);
+ Sentry.TransactionContext ContinueTrace(string? traceHeader, string? baggageHeader, string? name = null, string? operation = null);
void EndSession(Sentry.SessionEndStatus status = 0);
Sentry.BaggageHeader? GetBaggage();
Sentry.ISpan? GetSpan();
@@ -759,6 +760,7 @@ namespace Sentry
public static void ConfigureScope(System.Action configureScope) { }
public static System.Threading.Tasks.Task ConfigureScopeAsync(System.Func configureScope) { }
public static Sentry.TransactionContext ContinueTrace(Sentry.SentryTraceHeader? traceHeader, Sentry.BaggageHeader? baggageHeader, string? name = null, string? operation = null) { }
+ public static Sentry.TransactionContext ContinueTrace(string? traceHeader, string? baggageHeader, string? name = null, string? operation = null) { }
public static void EndSession(Sentry.SessionEndStatus status = 0) { }
public static void Flush() { }
public static void Flush(System.TimeSpan timeout) { }
@@ -1235,6 +1237,7 @@ namespace Sentry.Extensibility
public void ConfigureScope(System.Action configureScope) { }
public System.Threading.Tasks.Task ConfigureScopeAsync(System.Func configureScope) { }
public Sentry.TransactionContext ContinueTrace(Sentry.SentryTraceHeader? traceHeader, Sentry.BaggageHeader? baggageHeader, string? name = null, string? operation = null) { }
+ public Sentry.TransactionContext ContinueTrace(string? traceHeader, string? baggageHeader, string? name = null, string? operation = null) { }
public void Dispose() { }
public void EndSession(Sentry.SessionEndStatus status = 0) { }
public System.Threading.Tasks.Task FlushAsync(System.TimeSpan timeout) { }
@@ -1276,6 +1279,7 @@ namespace Sentry.Extensibility
public void ConfigureScope(System.Action configureScope) { }
public System.Threading.Tasks.Task ConfigureScopeAsync(System.Func configureScope) { }
public Sentry.TransactionContext ContinueTrace(Sentry.SentryTraceHeader? traceHeader, Sentry.BaggageHeader? baggageHeader, string? name = null, string? operation = null) { }
+ public Sentry.TransactionContext ContinueTrace(string? traceHeader, string? baggageHeader, string? name = null, string? operation = null) { }
public void EndSession(Sentry.SessionEndStatus status = 0) { }
public System.Threading.Tasks.Task FlushAsync(System.TimeSpan timeout) { }
public Sentry.BaggageHeader? GetBaggage() { }
diff --git a/test/Sentry.Tests/HubTests.cs b/test/Sentry.Tests/HubTests.cs
index 900c415ed5..493dd003be 100644
--- a/test/Sentry.Tests/HubTests.cs
+++ b/test/Sentry.Tests/HubTests.cs
@@ -915,13 +915,44 @@ public void ContinueTrace_SetsPropagationContextAndReturnsTransactionContext()
var propagationContext = new SentryPropagationContext(
SentryId.Parse("43365712692146d08ee11a729dfbcaca"), SpanId.Parse("1000000000000000"));
hub.ConfigureScope(scope => scope.PropagationContext = propagationContext);
+
var traceHeader = new SentryTraceHeader(SentryId.Parse("5bd5f6d346b442dd9177dce9302fd737"),
SpanId.Parse("2000000000000000"), null);
var baggageHeader = BaggageHeader.Create(new List>
{
- {"sentry-public_key", "49d0f7386ad645858ae85020e393bef3"}
+ {"sentry-trace_id", "5bd5f6d346b442dd9177dce9302fd737"},
+ {"sentry-public_key", "49d0f7386ad645858ae85020e393bef3"},
+ {"sentry-sample_rate", "1.0"}
+ });
+
+ hub.ConfigureScope(scope => scope.PropagationContext.TraceId.Should().Be("43365712692146d08ee11a729dfbcaca")); // Sanity check
+
+ // Act
+ var transactionContext = hub.ContinueTrace(traceHeader, baggageHeader, "test-name");
+
+ // Assert
+ hub.ConfigureScope(scope =>
+ {
+ scope.PropagationContext.TraceId.Should().Be(SentryId.Parse("5bd5f6d346b442dd9177dce9302fd737"));
+ scope.PropagationContext.ParentSpanId.Should().Be(SpanId.Parse("2000000000000000"));
+ Assert.NotNull(scope.PropagationContext._dynamicSamplingContext);
});
+ transactionContext.TraceId.Should().Be(SentryId.Parse("5bd5f6d346b442dd9177dce9302fd737"));
+ transactionContext.ParentSpanId.Should().Be(SpanId.Parse("2000000000000000"));
+ }
+
+ [Fact]
+ public void ContinueTrace_ReceivesHeadersAsStrings_SetsPropagationContextAndReturnsTransactionContext()
+ {
+ // Arrange
+ var hub = _fixture.GetSut();
+ var propagationContext = new SentryPropagationContext(
+ SentryId.Parse("43365712692146d08ee11a729dfbcaca"), SpanId.Parse("1000000000000000"));
+ hub.ConfigureScope(scope => scope.PropagationContext = propagationContext);
+ var traceHeader = "5bd5f6d346b442dd9177dce9302fd737-2000000000000000";
+ var baggageHeader ="sentry-trace_id=5bd5f6d346b442dd9177dce9302fd737, sentry-public_key=49d0f7386ad645858ae85020e393bef3, sentry-sample_rate=1.0";
+
hub.ConfigureScope(scope => scope.PropagationContext.TraceId.Should().Be("43365712692146d08ee11a729dfbcaca")); // Sanity check
// Act
@@ -932,6 +963,7 @@ public void ContinueTrace_SetsPropagationContextAndReturnsTransactionContext()
{
scope.PropagationContext.TraceId.Should().Be(SentryId.Parse("5bd5f6d346b442dd9177dce9302fd737"));
scope.PropagationContext.ParentSpanId.Should().Be(SpanId.Parse("2000000000000000"));
+ Assert.NotNull(scope.PropagationContext._dynamicSamplingContext);
});
transactionContext.TraceId.Should().Be(SentryId.Parse("5bd5f6d346b442dd9177dce9302fd737"));