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

feat(performance): start transaction for fasthttp integration #723

Merged
merged 10 commits into from
Mar 26, 2024
19 changes: 19 additions & 0 deletions _examples/fasthttp/main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"context"
"fmt"

"github.com/getsentry/sentry-go"
Expand All @@ -13,6 +14,24 @@ func enhanceSentryEvent(handler fasthttp.RequestHandler) fasthttp.RequestHandler
if hub := sentryfasthttp.GetHubFromContext(ctx); hub != nil {
hub.Scope().SetTag("someRandomTag", "maybeYouNeedIt")
}

expensiveThing := func(ctx context.Context) error {
span := sentry.StartTransaction(ctx, "expensive_thing")
defer span.Finish()
// do resource intensive thing
return nil
}

// Acquire transaction on current hub that's created by the SDK.
// Be careful, it might be a nil value if you didn't set up sentryecho middleware.
sentrySpan := sentryfasthttp.GetSpanFromContext(ctx)
// Pass in the `.Context()` method from `*sentry.Span` struct.
// The `context.Context` instance inherits the context from `echo.Context`.
err := expensiveThing(sentrySpan.Context())
if err != nil {
sentry.CaptureException(err)
}

handler(ctx)
}
}
Expand Down
46 changes: 40 additions & 6 deletions fasthttp/sentryfasthttp.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ import (
"github.com/valyala/fasthttp"
)

// The identifier of the FastHTTP SDK.
const sdkIdentifier = "sentry.go.fasthttp"

type contextKey int

const ContextKey = contextKey(1)
const valuesKey = "sentry"
const (
ContextKey = contextKey(1)
// The identifier of the FastHTTP SDK.
sdkIdentifier = "sentry.go.fasthttp"
valuesKey = "sentry"
transactionKey = "sentry_transaction"
)

type Handler struct {
repanic bool
Expand Down Expand Up @@ -66,10 +68,33 @@ func (h *Handler) Handle(handler fasthttp.RequestHandler) fasthttp.RequestHandle
client.SetSDKIdentifier(sdkIdentifier)
}

convertedHTTPRequest := convert(ctx)

options := []sentry.SpanOption{
sentry.WithOpName("http.server"),
sentry.ContinueFromRequest(convertedHTTPRequest),
sentry.WithTransactionSource(sentry.SourceRoute),
}

method := string(ctx.Method())

transaction := sentry.StartTransaction(
sentry.SetHubOnContext(ctx, hub),
vaind marked this conversation as resolved.
Show resolved Hide resolved
fmt.Sprintf("%s %s", method, string(ctx.Path())),
options...,
)
defer func() {
transaction.Status = sentry.HTTPtoSpanStatus(ctx.Response.StatusCode())
transaction.Finish()
}()

transaction.SetData("http.request.method", method)

scope := hub.Scope()
scope.SetRequest(convert(ctx))
scope.SetRequest(convertedHTTPRequest)
scope.SetRequestBody(ctx.Request.Body())
ctx.SetUserValue(valuesKey, hub)
ctx.SetUserValue(transactionKey, transaction)
defer h.recoverWithSentry(hub, ctx)
handler(ctx)
}
Expand Down Expand Up @@ -99,6 +124,15 @@ func GetHubFromContext(ctx *fasthttp.RequestCtx) *sentry.Hub {
return nil
}

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

func convert(ctx *fasthttp.RequestCtx) *http.Request {
defer func() {
if err := recover(); err != nil {
Expand Down
Loading
Loading