Skip to content

Commit 220e329

Browse files
committed
ref(grpc): migrate server to context scope API
1 parent 7efce58 commit 220e329

5 files changed

Lines changed: 250 additions & 32 deletions

File tree

crosstest/go.mod

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ replace (
99
github.com/getsentry/sentry-go/fiber => ../fiber
1010
github.com/getsentry/sentry-go/fiberv3 => ../fiberv3
1111
github.com/getsentry/sentry-go/gin => ../gin
12+
github.com/getsentry/sentry-go/grpc => ../grpc
1213
github.com/getsentry/sentry-go/iris => ../iris
1314
github.com/getsentry/sentry-go/logrus => ../logrus
1415
github.com/getsentry/sentry-go/negroni => ../negroni
@@ -24,6 +25,7 @@ require (
2425
github.com/getsentry/sentry-go/fiber v0.49.0
2526
github.com/getsentry/sentry-go/fiberv3 v0.49.0
2627
github.com/getsentry/sentry-go/gin v0.49.0
28+
github.com/getsentry/sentry-go/grpc v0.49.0
2729
github.com/getsentry/sentry-go/iris v0.49.0
2830
github.com/getsentry/sentry-go/logrus v0.49.0
2931
github.com/getsentry/sentry-go/negroni v0.49.0
@@ -41,6 +43,7 @@ require (
4143
github.com/valyala/fasthttp v1.71.0
4244
go.opentelemetry.io/otel/trace v1.43.0
4345
go.uber.org/zap v1.27.1
46+
google.golang.org/grpc v1.82.1
4447
)
4548

4649
require (
@@ -110,6 +113,7 @@ require (
110113
golang.org/x/sys v0.46.0 // indirect
111114
golang.org/x/text v0.39.0 // indirect
112115
golang.org/x/time v0.14.0 // indirect
116+
google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 // indirect
113117
google.golang.org/protobuf v1.36.11 // indirect
114118
gopkg.in/ini.v1 v1.67.0 // indirect
115119
gopkg.in/yaml.v3 v3.0.1 // indirect

crosstest/go.sum

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
4646
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
4747
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
4848
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
49+
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
50+
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
51+
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
52+
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
4953
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
5054
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
5155
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
@@ -66,6 +70,8 @@ github.com/gofiber/schema v1.7.1 h1:oSJBKdgP8JeIME4TQSAqlNKTU2iBB+2RNmKi8Nsc+TI=
6670
github.com/gofiber/schema v1.7.1/go.mod h1:A/X5Ffyru4p9eBdp99qu+nzviHzQiZ7odLT+TwxWhbk=
6771
github.com/gofiber/utils/v2 v2.0.6 h1:7fXYy7nSsyqbH0GQUMtK4Kwjy4J7R5742VM7JsZxzOs=
6872
github.com/gofiber/utils/v2 v2.0.6/go.mod h1:p7mAHAk3+oUK10ZX2xTw9fZQixb4hCg8SKd4IH2xroU=
73+
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
74+
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
6975
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
7076
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
7177
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
@@ -221,8 +227,16 @@ github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FB
221227
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M=
222228
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
223229
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
230+
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
231+
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
224232
go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I=
225233
go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0=
234+
go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM=
235+
go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY=
236+
go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg=
237+
go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg=
238+
go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw=
239+
go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A=
226240
go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A=
227241
go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0=
228242
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
@@ -273,6 +287,12 @@ golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
273287
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
274288
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
275289
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
290+
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
291+
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
292+
google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478 h1:RmoJA1ujG+/lRGNfUnOMfhCy5EipVMyvUE+KNbPbTlw=
293+
google.golang.org/genproto/googleapis/rpc v0.0.0-20260414002931-afd174a4e478/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
294+
google.golang.org/grpc v1.82.1 h1:NnAxzGRA0677vCa4BUkOAnO5+FfQqVl9iUXeD0IqcGE=
295+
google.golang.org/grpc v1.82.1/go.mod h1:yzTZ1TB1Z3SG+LIYaI+WiE8D5+PZ3ArnrSp8zF3+/ZA=
276296
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
277297
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
278298
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

crosstest/grpc_link_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package crosstest
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/getsentry/sentry-go"
8+
sentrygrpc "github.com/getsentry/sentry-go/grpc"
9+
"github.com/getsentry/sentry-go/internal/sentrytest"
10+
"google.golang.org/grpc"
11+
"google.golang.org/grpc/codes"
12+
"google.golang.org/grpc/metadata"
13+
"google.golang.org/grpc/status"
14+
)
15+
16+
func TestGRPCServerLinksManualErrorsLogsMetricsAndPanicsToOTel(t *testing.T) {
17+
t.Parallel()
18+
otelCtx, traceID, spanID := fixedOTelContext()
19+
20+
sentrytest.Run(t, func(t *testing.T, f *sentrytest.Fixture) {
21+
const identifier = "grpc"
22+
baseCtx := f.NewContext(context.Background())
23+
logger := sentry.NewLogger(baseCtx)
24+
meter := sentry.NewMeter(baseCtx)
25+
ctx := metadata.NewIncomingContext(f.NewContext(otelCtx), metadata.Pairs("x-request-id", "req-123"))
26+
interceptor := sentrygrpc.UnaryServerInterceptor(sentrygrpc.ServerOptions{WaitForDelivery: true})
27+
28+
_, err := interceptor(ctx, nil, &grpc.UnaryServerInfo{
29+
FullMethod: "/test.TestService/Method",
30+
}, func(ctx context.Context, _ any) (any, error) {
31+
sendContextSignals(ctx, identifier, logger, meter)
32+
return nil, nil
33+
})
34+
if status.Code(err) != codes.Internal {
35+
t.Fatalf("status code = %s, want %s", status.Code(err), codes.Internal)
36+
}
37+
38+
f.Flush()
39+
requireRequestSignalsLinked(t, f.Events(), traceID, spanID, identifier)
40+
}, otelOpts()...)
41+
}

grpc/server.go

Lines changed: 21 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,16 @@ func (o *ServerOptions) setDefaults() {
3838
}
3939
}
4040

41-
func recoverWithSentry(ctx context.Context, hub *sentry.Hub, o ServerOptions, onRecover func()) {
41+
func recoverWithSentry(ctx context.Context, o ServerOptions, onRecover func()) {
4242
if r := recover(); r != nil {
43-
eventID := hub.RecoverWithContext(ctx, r)
43+
eventID := sentry.CapturePanic(ctx, r)
4444

4545
if onRecover != nil {
4646
onRecover()
4747
}
4848

4949
if eventID != nil && o.WaitForDelivery {
50-
hub.Flush(o.Timeout)
50+
sentry.GetClient(ctx).Flush(o.Timeout)
5151
}
5252

5353
if o.Repanic {
@@ -56,33 +56,25 @@ func recoverWithSentry(ctx context.Context, hub *sentry.Hub, o ServerOptions, on
5656
}
5757
}
5858

59-
func hubFromServerContext(ctx context.Context) *sentry.Hub {
60-
hub := sentry.GetHubFromContext(ctx)
61-
if hub == nil {
62-
hub = sentry.CurrentHub().Clone()
63-
}
64-
65-
if client := hub.Client(); client.IsEnabled() {
66-
client.SetSDKIdentifier(sdkIdentifier)
67-
}
68-
69-
return hub
70-
}
71-
7259
func traceHeadersFromContext(ctx context.Context) (metadata.MD, string, string) {
7360
md, _ := metadata.FromIncomingContext(ctx)
7461
return md, getFirstHeader(md, sentry.SentryTraceHeader), getFirstHeader(md, sentry.SentryBaggageHeader)
7562
}
7663

77-
func startServerTransaction(ctx context.Context, fullMethod string) (context.Context, *sentry.Hub, *sentry.Span) {
78-
hub := hubFromServerContext(ctx)
64+
func startServerTransaction(ctx context.Context, fullMethod string) (context.Context, *sentry.Span) {
65+
ctx, scope := sentry.WithIsolationScope(ctx)
66+
client := sentry.GetClient(ctx)
67+
if client.IsEnabled() {
68+
client.SetSDKIdentifier(sdkIdentifier)
69+
}
70+
7971
md, sentryTraceHeader, sentryBaggageHeader := traceHeadersFromContext(ctx)
8072
name, service, method := parseGRPCMethod(fullMethod)
8173

82-
setScopeMetadata(hub, name, md)
74+
setScopeMetadata(scope, client, name, md)
8375

8476
transaction := sentry.StartTransaction(
85-
sentry.SetHubOnContext(ctx, hub),
77+
ctx,
8678
name,
8779
sentry.ContinueTrace(sentryTraceHeader, sentryBaggageHeader),
8880
sentry.WithOpName(defaultServerOperationName),
@@ -98,7 +90,7 @@ func startServerTransaction(ctx context.Context, fullMethod string) (context.Con
9890
}
9991
transaction.SetData("rpc.system", "grpc")
10092

101-
return transaction.Context(), hub, transaction
93+
return transaction.Context(), transaction
10294
}
10395

10496
func setRPCStatus(span *sentry.Span, err error) {
@@ -123,10 +115,10 @@ func UnaryServerInterceptor(opts ServerOptions) grpc.UnaryServerInterceptor {
123115
opts.setDefaults()
124116

125117
return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) {
126-
ctx, hub, transaction := startServerTransaction(ctx, info.FullMethod)
118+
ctx, transaction := startServerTransaction(ctx, info.FullMethod)
127119
defer transaction.Finish()
128120

129-
defer recoverWithSentry(ctx, hub, opts, func() {
121+
defer recoverWithSentry(ctx, opts, func() {
130122
err = status.Error(codes.Internal, internalServerErrorMessage)
131123
setRPCStatus(transaction, err)
132124
})
@@ -142,12 +134,12 @@ func UnaryServerInterceptor(opts ServerOptions) grpc.UnaryServerInterceptor {
142134
func StreamServerInterceptor(opts ServerOptions) grpc.StreamServerInterceptor {
143135
opts.setDefaults()
144136
return func(srv any, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) (err error) {
145-
ctx, hub, transaction := startServerTransaction(ss.Context(), info.FullMethod)
137+
ctx, transaction := startServerTransaction(ss.Context(), info.FullMethod)
146138
defer transaction.Finish()
147139

148140
stream := wrapServerStream(ctx, ss)
149141

150-
defer recoverWithSentry(ctx, hub, opts, func() {
142+
defer recoverWithSentry(ctx, opts, func() {
151143
err = status.Error(codes.Internal, internalServerErrorMessage)
152144
setRPCStatus(transaction, err)
153145
})
@@ -166,12 +158,10 @@ func getFirstHeader(md metadata.MD, key string) string {
166158
return ""
167159
}
168160

169-
func setScopeMetadata(hub *sentry.Hub, method string, md metadata.MD) {
170-
hub.ConfigureScope(func(scope *sentry.Scope) {
171-
scope.SetContext("grpc", sentry.Context{
172-
"method": method,
173-
"metadata": metadataToContext(hub.Client(), md),
174-
})
161+
func setScopeMetadata(scope *sentry.Scope, client *sentry.Client, method string, md metadata.MD) {
162+
scope.SetContext("grpc", sentry.Context{
163+
"method": method,
164+
"metadata": metadataToContext(client, md),
175165
})
176166
}
177167

0 commit comments

Comments
 (0)