Skip to content

Commit 998141a

Browse files
authored
fix: http integration uses correct parent span id (#4264)
1 parent 5f03fdb commit 998141a

4 files changed

Lines changed: 47 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Unreleased
44

5+
### Fixes
6+
7+
- The HTTP instrumentation uses the span created for the outgoing request in the sentry-trace header, fixing the parent-child relationship between client and server ([#4264](https://github.com/getsentry/sentry-dotnet/pull/4264))
8+
59
### Dependencies
610

711
- Bump Native SDK from v0.8.5 to v0.9.0 ([#4260](https://github.com/getsentry/sentry-dotnet/pull/4260))

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project>
22

33
<PropertyGroup>
4-
<VersionPrefix>5.10.0</VersionPrefix>
4+
<VersionPrefix>5.11.0-alpha.1</VersionPrefix>
55
<LangVersion>13</LangVersion>
66
<AccelerateBuildsInVisualStudio>true</AccelerateBuildsInVisualStudio>
77
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>

src/Sentry/SentryMessageHandler.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ protected override async Task<HttpResponseMessage> SendAsync(
8686
var span = ProcessRequest(request, method, url);
8787
try
8888
{
89-
PropagateTraceHeaders(request, url);
89+
PropagateTraceHeaders(request, url, span);
9090
var response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
9191
HandleResponse(response, span, method, url);
9292
return response;
@@ -108,7 +108,7 @@ protected override HttpResponseMessage Send(HttpRequestMessage request, Cancella
108108
var span = ProcessRequest(request, method, url);
109109
try
110110
{
111-
PropagateTraceHeaders(request, url);
111+
PropagateTraceHeaders(request, url, span);
112112
var response = base.Send(request, cancellationToken);
113113
HandleResponse(response, span, method, url);
114114
return response;
@@ -121,7 +121,7 @@ protected override HttpResponseMessage Send(HttpRequestMessage request, Cancella
121121
}
122122
#endif
123123

124-
private void PropagateTraceHeaders(HttpRequestMessage request, string url)
124+
private void PropagateTraceHeaders(HttpRequestMessage request, string url, ISpan? parentSpan)
125125
{
126126
// Assign a default inner handler for convenience the first time this is used.
127127
// We can't do this in a constructor, or it will throw when used with HttpMessageHandlerBuilderFilter.
@@ -135,15 +135,17 @@ private void PropagateTraceHeaders(HttpRequestMessage request, string url)
135135

136136
if (_options?.TracePropagationTargets.MatchesSubstringOrRegex(url) is true or null)
137137
{
138-
AddSentryTraceHeader(request);
138+
AddSentryTraceHeader(request, parentSpan);
139139
AddBaggageHeader(request);
140140
}
141141
}
142142

143-
private void AddSentryTraceHeader(HttpRequestMessage request)
143+
private void AddSentryTraceHeader(HttpRequestMessage request, ISpan? parentSpan)
144144
{
145145
// Set trace header if it hasn't already been set
146-
if (!request.Headers.Contains(SentryTraceHeader.HttpHeaderName) && _hub.GetTraceHeader() is { } traceHeader)
146+
if (!request.Headers.Contains(SentryTraceHeader.HttpHeaderName) &&
147+
// Use the span created by this integration as parent, instead of its own parent
148+
(parentSpan?.GetTraceHeader() ?? _hub.GetTraceHeader()) is { } traceHeader)
147149
{
148150
request.Headers.Add(SentryTraceHeader.HttpHeaderName, traceHeader.ToString());
149151
}

test/Sentry.Tests/SentryHttpMessageHandlerTests.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,40 @@ public async Task SendAsync_SentryTraceHeaderNotSet_SetsHeader_ByDefault()
3333
string.Concat(h.Value) == "75302ac48a024bde9a3b3734a82e36c8-1000000000000000-0");
3434
}
3535

36+
[Fact]
37+
public async Task SendAsync_SentryTraceHeaderNotSet_SetsHeader_ToCorrectParent()
38+
{
39+
// Arrange
40+
var hub = Substitute.For<IHub>();
41+
42+
const string rootTraceHeader = "75302ac48a024bde9a3b3734a82e36c8-1000000000000000-1";
43+
hub.GetTraceHeader().ReturnsForAnyArgs(
44+
SentryTraceHeader.Parse(rootTraceHeader));
45+
var parentSpan = Substitute.For<ISpan>();
46+
parentSpan.GetTraceHeader().ReturnsForAnyArgs(
47+
SentryTraceHeader.Parse(rootTraceHeader));
48+
hub.GetSpan().ReturnsForAnyArgs(parentSpan);
49+
const string httpSpanTraceHeader = "75302ac48a024bde9a3b3734a82e36c8-2000000000000000-1";
50+
var httpSpan = Substitute.For<ISpan>();
51+
httpSpan.GetTraceHeader().ReturnsForAnyArgs(
52+
SentryTraceHeader.Parse(httpSpanTraceHeader));
53+
parentSpan.StartChild(Arg.Any<string>()).ReturnsForAnyArgs(httpSpan);
54+
55+
using var innerHandler = new RecordingHttpMessageHandler(new FakeHttpMessageHandler());
56+
using var sentryHandler = new SentryHttpMessageHandler(innerHandler, hub);
57+
using var client = new HttpClient(sentryHandler);
58+
59+
// Act
60+
await client.GetAsync("https://localhost/");
61+
62+
using var request = innerHandler.GetRequests().Single();
63+
64+
// Assert
65+
request.Headers.Should().Contain(h =>
66+
h.Key == "sentry-trace" &&
67+
string.Concat(h.Value) == httpSpanTraceHeader);
68+
}
69+
3670
[Fact]
3771
public async Task SendAsync_SentryTraceHeaderNotSet_SetsHeader_WhenUrlMatchesPropagationOptions()
3872
{

0 commit comments

Comments
 (0)