Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tracing without performance improvements #862

Merged
merged 17 commits into from
Sep 4, 2024
9 changes: 3 additions & 6 deletions dynamic_sampling_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ func DynamicSamplingContextFromHeader(header []byte) (DynamicSamplingContext, er
}

func DynamicSamplingContextFromTransaction(span *Span) DynamicSamplingContext {
entries := map[string]string{}

hub := hubFromContext(span.Context())
scope := hub.Scope()
client := hub.Client()
Expand All @@ -52,6 +50,8 @@ func DynamicSamplingContextFromTransaction(span *Span) DynamicSamplingContext {
}
}

entries := make(map[string]string)

if traceID := span.TraceID.String(); traceID != "" {
entries["trace_id"] = traceID
}
Expand Down Expand Up @@ -80,10 +80,7 @@ func DynamicSamplingContextFromTransaction(span *Span) DynamicSamplingContext {

entries["sampled"] = strconv.FormatBool(span.Sampled.Bool())

return DynamicSamplingContext{
Entries: entries,
Frozen: true,
}
return DynamicSamplingContext{Entries: entries, Frozen: true}
}

func (d DynamicSamplingContext) HasEntries() bool {
Expand Down
6 changes: 3 additions & 3 deletions echo/sentryecho.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func New(options Options) echo.MiddlewareFunc {

func (h *handler) handle(next echo.HandlerFunc) echo.HandlerFunc {
return func(ctx echo.Context) error {
hub := sentry.GetHubFromContext(ctx.Request().Context())
hub := GetHubFromContext(ctx)
if hub == nil {
hub = sentry.CurrentHub().Clone()
}
Expand All @@ -70,8 +70,8 @@ func (h *handler) handle(next echo.HandlerFunc) echo.HandlerFunc {
}

options := []sentry.SpanOption{
sentry.ContinueTrace(hub, r.Header.Get(sentry.SentryTraceHeader), r.Header.Get(sentry.SentryBaggageHeader)),
sentry.WithOpName("http.server"),
sentry.ContinueFromRequest(r),
sentry.WithTransactionSource(transactionSource),
sentry.WithSpanOrigin(sentry.SpanOriginEcho),
}
Expand All @@ -82,7 +82,7 @@ func (h *handler) handle(next echo.HandlerFunc) echo.HandlerFunc {
options...,
)

transaction.SetData("http.request.method", ctx.Request().Method)
transaction.SetData("http.request.method", r.Method)

defer func() {
status := ctx.Response().Status
Expand Down
12 changes: 8 additions & 4 deletions fasthttp/sentryfasthttp.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,20 @@ func New(options Options) *Handler {
// Handle wraps fasthttp.RequestHandler and recovers from caught panics.
func (h *Handler) Handle(handler fasthttp.RequestHandler) fasthttp.RequestHandler {
return func(ctx *fasthttp.RequestCtx) {
hub := sentry.CurrentHub().Clone()
hub := GetHubFromContext(ctx)
if hub == nil {
hub = sentry.CurrentHub().Clone()
}

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

convertedHTTPRequest := convert(ctx)
r := convert(ctx)

options := []sentry.SpanOption{
sentry.ContinueTrace(hub, r.Header.Get(sentry.SentryTraceHeader), r.Header.Get(sentry.SentryBaggageHeader)),
sentry.WithOpName("http.server"),
sentry.ContinueFromRequest(convertedHTTPRequest),
sentry.WithTransactionSource(sentry.SourceRoute),
sentry.WithSpanOrigin(sentry.SpanOriginFastHTTP),
}
Expand All @@ -90,11 +93,12 @@ func (h *Handler) Handle(handler fasthttp.RequestHandler) fasthttp.RequestHandle
transaction.SetData("http.request.method", method)

scope := hub.Scope()
scope.SetRequest(convertedHTTPRequest)
scope.SetRequest(r)
scope.SetRequestBody(ctx.Request.Body())
ctx.SetUserValue(valuesKey, hub)
ctx.SetUserValue(transactionKey, transaction)
defer h.recoverWithSentry(hub, ctx)

handler(ctx)
}
}
Expand Down
12 changes: 8 additions & 4 deletions fiber/sentryfiber.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,22 +54,25 @@ func New(options Options) fiber.Handler {
}

func (h *handler) handle(ctx *fiber.Ctx) error {
hub := sentry.CurrentHub().Clone()
hub := GetHubFromContext(ctx)
if hub == nil {
hub = sentry.CurrentHub().Clone()
}

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

convertedHTTPRequest := convert(ctx)
r := convert(ctx)

method := ctx.Method()

transactionName := ctx.Path()
transactionSource := sentry.SourceURL

options := []sentry.SpanOption{
sentry.ContinueTrace(hub, r.Header.Get(sentry.SentryTraceHeader), r.Header.Get(sentry.SentryBaggageHeader)),
sentry.WithOpName("http.server"),
sentry.ContinueFromRequest(convertedHTTPRequest),
sentry.WithTransactionSource(transactionSource),
sentry.WithSpanOrigin(sentry.SpanOriginFiber),
}
Expand All @@ -90,11 +93,12 @@ func (h *handler) handle(ctx *fiber.Ctx) error {
transaction.SetData("http.request.method", method)

scope := hub.Scope()
scope.SetRequest(convertedHTTPRequest)
scope.SetRequest(r)
scope.SetRequestBody(ctx.Request().Body())
ctx.Locals(valuesKey, hub)
ctx.Locals(transactionKey, transaction)
defer h.recoverWithSentry(hub, ctx)

return ctx.Next()
}

Expand Down
22 changes: 19 additions & 3 deletions gin/sentrygin.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
const sdkIdentifier = "sentry.go.gin"

const valuesKey = "sentry"
const transactionKey = "sentry_transaction"

type handler struct {
repanic bool
Expand Down Expand Up @@ -55,7 +56,6 @@
hub := sentry.GetHubFromContext(ctx)
if hub == nil {
hub = sentry.CurrentHub().Clone()
ctx = sentry.SetHubOnContext(ctx, hub)
}

if client := hub.Client(); client != nil {
Expand All @@ -71,17 +71,20 @@
}

options := []sentry.SpanOption{
sentry.ContinueTrace(hub, c.GetHeader(sentry.SentryTraceHeader), c.GetHeader(sentry.SentryBaggageHeader)),
sentry.WithOpName("http.server"),
sentry.ContinueFromRequest(c.Request),
sentry.WithTransactionSource(transactionSource),
sentry.WithSpanOrigin(sentry.SpanOriginGin),
}

transaction := sentry.StartTransaction(ctx,
transaction := sentry.StartTransaction(
sentry.SetHubOnContext(ctx, hub),
fmt.Sprintf("%s %s", c.Request.Method, transactionName),
options...,
)

transaction.SetData("http.request.method", c.Request.Method)

defer func() {
status := c.Writer.Status()
transaction.Status = sentry.HTTPtoSpanStatus(status)
Expand All @@ -92,7 +95,9 @@
c.Request = c.Request.WithContext(transaction.Context())
hub.Scope().SetRequest(c.Request)
c.Set(valuesKey, hub)
c.Set(transactionKey, transaction)
defer h.recoverWithSentry(hub, c.Request)

c.Next()
}

Expand Down Expand Up @@ -135,3 +140,14 @@
}
return nil
}

// GetSpanFromContext retrieves attached *sentry.Span instance from gin.Context.
// If there is no transaction on echo.Context, it will return nil.
func GetSpanFromContext(ctx *gin.Context) *sentry.Span {
if span, ok := ctx.Get(transactionKey); ok {
if span, ok := span.(*sentry.Span); ok {
return span
}

Check warning on line 150 in gin/sentrygin.go

View check run for this annotation

Codecov / codecov/patch

gin/sentrygin.go#L146-L150

Added lines #L146 - L150 were not covered by tests
}
return nil

Check warning on line 152 in gin/sentrygin.go

View check run for this annotation

Codecov / codecov/patch

gin/sentrygin.go#L152

Added line #L152 was not covered by tests
}
11 changes: 4 additions & 7 deletions http/sentryhttp.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func (h *Handler) HandleFunc(handler http.HandlerFunc) http.HandlerFunc {
func (h *Handler) handle(handler http.Handler) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
hub := sentry.GetHubFromContext(ctx)
hub := sentry.GetHubFromContext(r.Context())
if hub == nil {
hub = sentry.CurrentHub().Clone()
ctx = sentry.SetHubOnContext(ctx, hub)
Expand All @@ -95,8 +95,8 @@ func (h *Handler) handle(handler http.Handler) http.HandlerFunc {
}

options := []sentry.SpanOption{
sentry.ContinueTrace(hub, r.Header.Get(sentry.SentryTraceHeader), r.Header.Get(sentry.SentryBaggageHeader)),
sentry.WithOpName("http.server"),
sentry.ContinueFromRequest(r),
sentry.WithTransactionSource(sentry.SourceURL),
sentry.WithSpanOrigin(sentry.SpanOriginStdLib),
}
Expand All @@ -116,13 +116,10 @@ func (h *Handler) handle(handler http.Handler) http.HandlerFunc {
transaction.Finish()
}()

// TODO(tracing): if the next handler.ServeHTTP panics, store
// information on the transaction accordingly (status, tag,
// level?, ...).
r = r.WithContext(transaction.Context())
hub.Scope().SetRequest(r)

r = r.WithContext(transaction.Context())
defer h.recoverWithSentry(hub, r)

handler.ServeHTTP(rw, r)
}
}
Expand Down
34 changes: 21 additions & 13 deletions hub.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package sentry

import (
"context"
"fmt"
"sync"
"time"
)
Expand Down Expand Up @@ -365,25 +366,32 @@ func (hub *Hub) Flush(timeout time.Duration) bool {
return client.Flush(timeout)
}

// Continue a trace based on HTTP header values. If performance is enabled this
// returns a SpanOption that can be used to start a transaction, otherwise nil.
func (hub *Hub) ContinueTrace(trace, baggage string) (SpanOption, error) {
cleptric marked this conversation as resolved.
Show resolved Hide resolved
// GetTraceparent returns the current Sentry traceparent string, to be used as a HTTP header value
// or HTML meta tag value.
// This function is context aware, as in it either returns the traceparent based
// on the current span, or the scope's propagation context.
func (hub *Hub) GetTraceparent() string {
scope := hub.Scope()
propagationContext, err := PropagationContextFromHeaders(trace, baggage)
if err != nil {
return nil, err

if scope.span != nil {
return scope.span.ToSentryTrace()
}

scope.SetPropagationContext(propagationContext)
return fmt.Sprintf("%s-%s", scope.propagationContext.TraceID, scope.propagationContext.SpanID)
}

client := hub.Client()
if client != nil && client.options.EnableTracing {
return ContinueFromHeaders(trace, baggage), nil
}
// GetBaggage returns the current Sentry baggage string, to be used as a HTTP header value
// or HTML meta tag value.
// This function is context aware, as in it either returns the baggage based
// on the current span or the scope's propagation context.
func (hub *Hub) GetBaggage() string {
scope := hub.Scope()

scope.SetContext("trace", propagationContext.Map())
if scope.span != nil {
return scope.span.ToBaggage()
}

return nil, nil
return scope.propagationContext.DynamicSamplingContext.String()
}

// HasHubOnContext checks whether Hub instance is bound to a given Context struct.
Expand Down
Loading
Loading