Skip to content

Commit

Permalink
transport: Fix tracing roundtripper
Browse files Browse the repository at this point in the history
  • Loading branch information
monstermunchkin committed Nov 29, 2024
1 parent bafb344 commit 01e72c8
Showing 1 changed file with 37 additions and 11 deletions.
48 changes: 37 additions & 11 deletions http/transport/tracing_round_tripper.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
package transport

import (
"fmt"
"net/http"
"strings"

"github.com/getsentry/sentry-go"
)

// The identifier of the HTTP SDK.
const sdkIdentifier = "sentry.go.http"

// TracingRoundTripper implements a chainable round tripper for tracing
type TracingRoundTripper struct {
transport http.RoundTripper
Expand All @@ -28,37 +31,60 @@ func (l *TracingRoundTripper) SetTransport(rt http.RoundTripper) {
func (l *TracingRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
ctx := req.Context()

hub := sentry.GetHubFromContext(ctx)
hub := sentry.GetHubFromContext(req.Context())
if hub == nil {
// Check the concurrency guide for more details: https://docs.sentry.io/platforms/go/concurrency/
hub = sentry.CurrentHub().Clone()
ctx = sentry.SetHubOnContext(ctx, hub)
}

if client := hub.Client(); client != nil {
client.SetSDKIdentifier(sdkIdentifier)
}

options := []sentry.SpanOption{
// Set the OP based on values from https://develop.sentry.dev/sdk/performance/span-operations/
sentry.ContinueTrace(hub, req.Header.Get(sentry.SentryTraceHeader), req.Header.Get(sentry.SentryBaggageHeader)),
sentry.WithOpName("http.client"),
sentry.ContinueFromRequest(req),
sentry.WithTransactionSource(sentry.SourceURL),
sentry.WithSpanOrigin(sentry.SpanOriginStdLib),
}

span := sentry.StartTransaction(ctx, fmt.Sprintf("%s %s", req.Method, req.URL.Path), options...)
defer span.Finish()
transaction := sentry.StartTransaction(ctx,
getHTTPSpanName(req),
options...,
)
transaction.SetData("http.request.method", req.Method)

ctx = span.Context()
defer transaction.Finish()

ctx = transaction.Context()

resp, err := l.Transport().RoundTrip(req.WithContext(ctx))

attempt := attemptFromCtx(ctx)
if attempt > 0 {
span.SetData("attempt", int(attempt))
transaction.SetData("http.request.attempt", int(attempt))
}
if err != nil {
span.SetData("error", err)
transaction.SetData("http.response.error", err)
return nil, err
}

span.SetData("code", resp.StatusCode)
transaction.SetData("http.response.status_code", resp.StatusCode)

return resp, nil
}

// getHTTPSpanName grab needed fields from *http.Request to generate a span name for `http.server` span op.
func getHTTPSpanName(r *http.Request) string {
if r.Pattern != "" {
// If value does not start with HTTP methods, add them.
// The method and the path should be separated by a space.
if parts := strings.SplitN(r.Pattern, " ", 2); len(parts) == 1 {
return r.Method + " " + r.Pattern
}

return r.Pattern
}

return r.Method + " " + r.URL.Path
}

0 comments on commit 01e72c8

Please sign in to comment.