feat: http client integration#876
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #876 +/- ##
==========================================
+ Coverage 86.04% 86.23% +0.19%
==========================================
Files 62 63 +1
Lines 6090 6148 +58
==========================================
+ Hits 5240 5302 +62
+ Misses 635 631 -4
Partials 215 215 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
@aldy505 We should document this (in _examples, and perhaps sentry-docs?), and also update changelog accordingly. |
| // Only create the `http.client` span only if there is a parent span. | ||
| parentSpan := sentry.GetSpanFromContext(request.Context()) | ||
| if parentSpan == nil { | ||
| return s.originalRoundTripper.RoundTrip(request) | ||
| } |
There was a problem hiding this comment.
A quick note why I prefer this instead of creating a sentry.WithOnlyIfParentExists() (a SpanOption type):
I used the JS SDK a lot at work lately, and I've been wondering the entire week, on their startSpan function, they have this as an option: https://github.com/getsentry/sentry-javascript/blob/216aaeba1ee27cce8a4876e1f9212ba374eb30b3/packages/types/src/startSpanOptions.ts#L14-L15
Should the Go SDK move forward with that, as a SpanOption or not?
We could to the SpanOption thing, but it feels really weird since the way Go SDK handles scopes/hubs with span is to add the span pointer into the scope. See
Lines 196 to 199 in a6acd05
Although we could just not call the scope.SetSpan() function, I don't know about the behavior if this span that we're creating will ever have a child span being created manually by the user.
| // Always add `Baggage` and `Sentry-Trace` headers. | ||
| request.Header.Add("Baggage", span.ToBaggage()) | ||
| request.Header.Add("Sentry-Trace", span.ToSentryTrace()) |
There was a problem hiding this comment.
To support the recently added "Tracing without Performance" feature, we should use hub.GetTraceparent() and hub.GetBaggage()
|
Will have a look after transport refactoring. |
|
@giortzisg updated |
_examples/httpclient/main.go
Outdated
| } | ||
|
|
||
| // With Sentry's HTTP client | ||
| err = getExamplePage(ctx, sentryhttpclient.Client) |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
httpclient/sentryhttpclient_test.go
Outdated
| if tt.WantSpan != nil && !foundMatch { | ||
| t.Errorf("Span mismatch (-want +got):\n%s", strings.Join(diffs, "\n")) | ||
| } else if tt.WantSpan == nil && foundMatch { | ||
| t.Errorf("Expected no span, got %+v", gotSpans) |
There was a problem hiding this comment.
Bug: Test cannot detect unwanted spans when expecting none
The test logic for validating the "no span expected" case is broken. When WantSpan is nil, the condition tt.WantSpan == nil && foundMatch at line 308 can never trigger because foundMatch only becomes true when cmp.Diff returns an empty string, but cmp.Diff(nil, gotSpan) always returns a diff when comparing nil to an actual span. This means if the implementation incorrectly creates an http.client span when none is expected (like when a URL doesn't match trace propagation targets), the test will silently pass instead of catching the bug.
_examples/httpclient/main.go
Outdated
| // With Sentry's HTTP client | ||
| err = getExamplePage(ctx, sentryhttpclient.Client) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| } |
Co-authored-by: Giannis Gkiortzis <58184179+giortzisg@users.noreply.github.com>
|
|
||
| if res.Body != nil { | ||
| res.Body.Close() | ||
| } |
There was a problem hiding this comment.
Bug: Nil pointer dereference when HTTP request fails
In TestDefaults, when client.Head() returns an error, res may be nil. Using t.Error(err) logs the error but does not stop execution, so the code continues to res.Body != nil. If res is nil, accessing res.Body causes a nil pointer dereference panic. The check needs to verify res != nil before accessing res.Body, or use t.Fatal(err) to stop execution on error.
| request.Header.Add("Baggage", hub.GetBaggage()) | ||
| request.Header.Add("Sentry-Trace", hub.GetTraceparent()) |
There was a problem hiding this comment.
Bug: Calls to hub.GetBaggage() and hub.GetTraceparent() can cause a panic due to a potential nil pointer dereference if the hub's scope is nil.
Severity: CRITICAL | Confidence: High
🔍 Detailed Analysis
The new code in sentryhttpclient.go retrieves a hub from the request context and checks if it's non-nil. However, it then calls hub.GetBaggage() and hub.GetTraceparent() without verifying that the hub's internal scope is also non-nil. The Sentry Go SDK's API contract allows for a hub to be created with a nil scope, via NewHub(client, nil). If such a hub is present in the context, the calls to GetBaggage() and GetTraceparent() will attempt to dereference a nil pointer, causing the application to panic.
💡 Suggested Fix
Before calling hub.GetBaggage() and hub.GetTraceparent(), add a check to ensure the hub's scope is not nil. For example: if hub := sentry.GetHubFromContext(request.Context()); hub != nil && hub.Scope() != nil { ... }.
🤖 Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.
Location: httpclient/sentryhttpclient.go#L99-L100
Potential issue: The new code in `sentryhttpclient.go` retrieves a `hub` from the
request context and checks if it's non-nil. However, it then calls `hub.GetBaggage()`
and `hub.GetTraceparent()` without verifying that the hub's internal scope is also
non-nil. The Sentry Go SDK's API contract allows for a hub to be created with a `nil`
scope, via `NewHub(client, nil)`. If such a hub is present in the context, the calls to
`GetBaggage()` and `GetTraceparent()` will attempt to dereference a nil pointer, causing
the application to panic.
Did we get this right? 👍 / 👎 to inform future reviews.
Reference ID: 7702273
The requested changes were resolved.
An effort to implement this: https://develop.sentry.dev/sdk/telemetry/traces/modules/requests/
Since we already have tracing without performance, this should be good to go.