From ef483dffa028fa9b892ced531aec1519d1691665 Mon Sep 17 00:00:00 2001 From: Reinaldy Rafli Date: Sun, 12 Jul 2026 21:35:05 +0700 Subject: [PATCH] feat(grpc): custom incoming server headers Closes https://github.com/getsentry/sentry-go/issues/1328 There are clients such as gRPC KMP client that strictly follow the '-bin' prefix for sending binary values for gRPC metadata. Right now, we can't have a trace propagation due to limitation on header key customization. --- go.work.sum | 4 +--- grpc/server.go | 28 ++++++++++++++++++++++------ 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/go.work.sum b/go.work.sum index aab9ffc01..871be539a 100644 --- a/go.work.sum +++ b/go.work.sum @@ -36,7 +36,6 @@ github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/T github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w= -github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o= github.com/dgraph-io/badger/v2 v2.2007.4/go.mod h1:vSw/ax2qojzbN6eXHIx6KPKtCSHJN/Uz0X0VPruTIhk= github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de h1:t0UHb5vdojIDUqktM6+xJAfScFBsVpXZmqC9dsgJmeA= @@ -119,7 +118,6 @@ github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c/go.mod h1:RqIHx9QI github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= -github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= @@ -128,7 +126,6 @@ github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= github.com/shirou/gopsutil/v3 v3.23.2 h1:PAWSuiAszn7IhPMBtXsbSCafej7PqUOvY6YywlQUExU= github.com/shirou/gopsutil/v3 v3.23.2/go.mod h1:gv0aQw33GLo3pG8SiWKiQrbDzbRY1K80RyZJ7V4Th1M= @@ -147,6 +144,7 @@ github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7Am github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= github.com/valyala/fasthttp v1.58.0/go.mod h1:SYXvHHaFp7QZHGKSHmoMipInhrI5StHrhDTYVEjK/Kw= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= diff --git a/grpc/server.go b/grpc/server.go index 1a9cc60c1..a0144f51a 100644 --- a/grpc/server.go +++ b/grpc/server.go @@ -30,12 +30,28 @@ type ServerOptions struct { // Timeout sets the maximum duration for Sentry event delivery. Timeout time.Duration + + // SentryTraceHeaderKey sets or overrides the header key used to propagate the trace id. + // It defaults to `sentry-trace`. + SentryTraceHeaderKey string + + // SentryBaggageHeaderKey sets or overrides the header key used to propagate the baggage. + // It defaults to `baggage`. + SentryBaggageHeaderKey string } func (o *ServerOptions) setDefaults() { if o.Timeout == 0 { o.Timeout = sentry.DefaultFlushTimeout } + + if o.SentryTraceHeaderKey == "" { + o.SentryTraceHeaderKey = sentry.SentryTraceHeader + } + + if o.SentryBaggageHeaderKey == "" { + o.SentryBaggageHeaderKey = sentry.SentryBaggageHeader + } } func recoverWithSentry(ctx context.Context, hub *sentry.Hub, o ServerOptions, onRecover func()) { @@ -69,14 +85,14 @@ func hubFromServerContext(ctx context.Context) *sentry.Hub { return hub } -func traceHeadersFromContext(ctx context.Context) (metadata.MD, string, string) { +func traceHeadersFromContext(ctx context.Context, traceHeaderKey string, baggageHeaderKey string) (metadata.MD, string, string) { md, _ := metadata.FromIncomingContext(ctx) - return md, getFirstHeader(md, sentry.SentryTraceHeader), getFirstHeader(md, sentry.SentryBaggageHeader) + return md, getFirstHeader(md, traceHeaderKey), getFirstHeader(md, baggageHeaderKey) } -func startServerTransaction(ctx context.Context, fullMethod string) (context.Context, *sentry.Hub, *sentry.Span) { +func startServerTransaction(ctx context.Context, fullMethod string, o ServerOptions) (context.Context, *sentry.Hub, *sentry.Span) { hub := hubFromServerContext(ctx) - md, sentryTraceHeader, sentryBaggageHeader := traceHeadersFromContext(ctx) + md, sentryTraceHeader, sentryBaggageHeader := traceHeadersFromContext(ctx, o.SentryTraceHeaderKey, o.SentryBaggageHeaderKey) name, service, method := parseGRPCMethod(fullMethod) setScopeMetadata(hub, name, md) @@ -123,7 +139,7 @@ func UnaryServerInterceptor(opts ServerOptions) grpc.UnaryServerInterceptor { opts.setDefaults() return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) { - ctx, hub, transaction := startServerTransaction(ctx, info.FullMethod) + ctx, hub, transaction := startServerTransaction(ctx, info.FullMethod, opts) defer transaction.Finish() defer recoverWithSentry(ctx, hub, opts, func() { @@ -142,7 +158,7 @@ func UnaryServerInterceptor(opts ServerOptions) grpc.UnaryServerInterceptor { func StreamServerInterceptor(opts ServerOptions) grpc.StreamServerInterceptor { opts.setDefaults() return func(srv any, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) (err error) { - ctx, hub, transaction := startServerTransaction(ss.Context(), info.FullMethod) + ctx, hub, transaction := startServerTransaction(ss.Context(), info.FullMethod, opts) defer transaction.Finish() stream := wrapServerStream(ctx, ss)