Skip to content

Commit 08fc7cd

Browse files
committed
Use the functional options pattern to configure interceptor
Also adresse other minor/style issues.
1 parent a960775 commit 08fc7cd

File tree

3 files changed

+93
-62
lines changed

3 files changed

+93
-62
lines changed

grpc/options.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package sentrygrpc
2+
3+
import (
4+
"google.golang.org/grpc/codes"
5+
"google.golang.org/grpc/status"
6+
)
7+
8+
type options struct {
9+
repanic bool
10+
reportOn ReportOn
11+
}
12+
13+
func buildOptions(ff ...Option) options {
14+
opts := options{
15+
reportOn: ReportAlways,
16+
}
17+
18+
for _, f := range ff {
19+
f(&opts)
20+
}
21+
22+
return opts
23+
}
24+
25+
// Option configures reporting behavior.
26+
type Option func(*options)
27+
28+
// WithRepanic configures whether to panic again after recovering from
29+
// a panic. Use this option if you have other panic handlers.
30+
func WithRepanic(b bool) Option {
31+
return func(o *options) {
32+
o.repanic = b
33+
}
34+
}
35+
36+
// ReportOn configures whether to report an error. Defaults to
37+
// ReportAlways.
38+
func WithReportOn(r ReportOn) Option {
39+
return func(o *options) {
40+
o.reportOn = r
41+
}
42+
}
43+
44+
// ReportOn decides error should be reported to sentry.
45+
type ReportOn func(error) bool
46+
47+
// ReportAlways returns true if err is non-nil.
48+
func ReportAlways(err error) bool {
49+
return err != nil
50+
}
51+
52+
// ReportOnCodes returns true if error code matches on of the given codes.
53+
func ReportOnCodes(cc ...codes.Code) ReportOn {
54+
return func(err error) bool {
55+
c := status.Code(err)
56+
for i := range cc {
57+
if c == cc[i] {
58+
return true
59+
}
60+
}
61+
62+
return false
63+
}
64+
}

grpc/server.go

Lines changed: 6 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,15 @@ import (
1111

1212
// UnaryServerInterceptor is a grpc interceptor that reports errors and panics
1313
// to sentry. It also sets *sentry.Hub to context.
14-
func UnaryServerInterceptor(opts UnaryServerInterceptorOptions) grpc.UnaryServerInterceptor {
15-
if opts.ReportOn == nil {
16-
opts.ReportOn = ReportAlways
17-
}
14+
func UnaryServerInterceptor(options ...Option) grpc.UnaryServerInterceptor {
15+
opts := buildOptions(options...)
1816

1917
return func(
2018
ctx context.Context,
2119
req interface{},
2220
info *grpc.UnaryServerInfo,
2321
handler grpc.UnaryHandler,
24-
) (_ interface{}, err error) {
22+
) (resp interface{}, err error) {
2523
hub := sentry.GetHubFromContext(ctx)
2624
if hub == nil {
2725
hub = sentry.CurrentHub().Clone()
@@ -32,53 +30,20 @@ func UnaryServerInterceptor(opts UnaryServerInterceptorOptions) grpc.UnaryServer
3230
if r := recover(); r != nil {
3331
hub.RecoverWithContext(ctx, r)
3432

35-
if opts.Repanic {
33+
if opts.repanic {
3634
panic(r)
3735
}
3836

3937
err = status.Errorf(codes.Internal, "%s", r)
4038
}
4139
}()
4240

43-
resp, err := handler(ctx, req)
41+
resp, err = handler(ctx, req)
4442

45-
if opts.ReportOn(err) {
43+
if opts.reportOn(err) {
4644
hub.CaptureException(err)
4745
}
4846

4947
return resp, err
5048
}
5149
}
52-
53-
// UnaryServerInterceptor configure UnaryServerInterceptor.
54-
type UnaryServerInterceptorOptions struct {
55-
// Repanic configures whether to panic again after recovering from a
56-
// panic. Use this option if you have other panic handlers.
57-
Repanic bool
58-
59-
// ReportOn configures whether to report an error. Defaults to
60-
// ReportAlways.
61-
ReportOn ReportOn
62-
}
63-
64-
// ReportOn decides error should be reported to sentry.
65-
type ReportOn func(error) bool
66-
67-
// ReportAlways returns true if err is non-nil.
68-
func ReportAlways(err error) bool {
69-
return err != nil
70-
}
71-
72-
// ReportOnCodes returns true if error code matches on of the given codes.
73-
func ReportOnCodes(cc ...codes.Code) ReportOn {
74-
return func(err error) bool {
75-
c := status.Code(err)
76-
for i := range cc {
77-
if c == cc[i] {
78-
return true
79-
}
80-
}
81-
82-
return false
83-
}
84-
}

grpc/server_test.go

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ func TestUnaryServerInterceptor(t *testing.T) {
2121
for _, tt := range []struct {
2222
name string
2323
ctx context.Context
24-
opts sentrygrpc.UnaryServerInterceptorOptions
24+
opts []sentrygrpc.Option
2525
handler func(
2626
context.Context,
2727
*grpchealth.HealthCheckRequest,
@@ -32,7 +32,6 @@ func TestUnaryServerInterceptor(t *testing.T) {
3232
{
3333
name: "does not report when err is nil",
3434
ctx: context.Background(),
35-
opts: sentrygrpc.UnaryServerInterceptorOptions{},
3635
handler: func(
3736
ctx context.Context,
3837
_ *grpchealth.HealthCheckRequest,
@@ -44,7 +43,6 @@ func TestUnaryServerInterceptor(t *testing.T) {
4443
{
4544
name: "reports all errors by default",
4645
ctx: context.Background(),
47-
opts: sentrygrpc.UnaryServerInterceptorOptions{},
4846
handler: func(
4947
context.Context,
5048
*grpchealth.HealthCheckRequest,
@@ -67,10 +65,12 @@ func TestUnaryServerInterceptor(t *testing.T) {
6765
{
6866
name: "reports errors that ReportOn returns true",
6967
ctx: context.Background(),
70-
opts: sentrygrpc.UnaryServerInterceptorOptions{
71-
ReportOn: func(err error) bool {
72-
return errors.Is(err, grpc.ErrServerStopped)
73-
},
68+
opts: []sentrygrpc.Option{
69+
sentrygrpc.WithReportOn(
70+
func(err error) bool {
71+
return errors.Is(err, grpc.ErrServerStopped)
72+
},
73+
),
7474
},
7575
handler: func(
7676
context.Context,
@@ -94,10 +94,12 @@ func TestUnaryServerInterceptor(t *testing.T) {
9494
{
9595
name: "does not report errors that ReportOn returns false",
9696
ctx: context.Background(),
97-
opts: sentrygrpc.UnaryServerInterceptorOptions{
98-
ReportOn: func(err error) bool {
99-
return false
100-
},
97+
opts: []sentrygrpc.Option{
98+
sentrygrpc.WithReportOn(
99+
func(err error) bool {
100+
return false
101+
},
102+
),
101103
},
102104
handler: func(
103105
context.Context,
@@ -110,7 +112,6 @@ func TestUnaryServerInterceptor(t *testing.T) {
110112
{
111113
name: "recovers from panic and returns internal error",
112114
ctx: context.Background(),
113-
opts: sentrygrpc.UnaryServerInterceptorOptions{},
114115
handler: func(
115116
context.Context,
116117
*grpchealth.HealthCheckRequest,
@@ -128,7 +129,6 @@ func TestUnaryServerInterceptor(t *testing.T) {
128129
{
129130
name: "sets hub on context",
130131
ctx: context.Background(),
131-
opts: sentrygrpc.UnaryServerInterceptorOptions{},
132132
handler: func(
133133
ctx context.Context,
134134
_ *grpchealth.HealthCheckRequest,
@@ -165,7 +165,7 @@ func TestUnaryServerInterceptor(t *testing.T) {
165165
}
166166
defer lis.Close()
167167

168-
opt := grpc.UnaryInterceptor(sentrygrpc.UnaryServerInterceptor(tt.opts))
168+
opt := grpc.UnaryInterceptor(sentrygrpc.UnaryServerInterceptor(tt.opts...))
169169
server := grpc.NewServer(opt)
170170
defer server.Stop()
171171

@@ -267,26 +267,28 @@ func TestReportOnCodes(t *testing.T) {
267267

268268
t.Run(tt.name, func(t *testing.T) {
269269
if w, g := tt.want, sentrygrpc.ReportOnCodes(tt.codes...)(tt.err); w != g {
270-
t.Fatalf("ReportOnCodes: want %t, got %t", w, g)
270+
t.Fatalf("want %t, got %t", w, g)
271271
}
272272
})
273273
}
274274
}
275275

276276
func ExampleUnaryServerInterceptor() {
277-
opts := sentrygrpc.UnaryServerInterceptorOptions{
277+
opts := []sentrygrpc.Option{
278278
// Reports on OutOfRange or Internal error.
279-
ReportOn: sentrygrpc.ReportOnCodes(
280-
codes.OutOfRange,
281-
codes.Internal,
279+
sentrygrpc.WithReportOn(
280+
sentrygrpc.ReportOnCodes(
281+
codes.OutOfRange,
282+
codes.Internal,
283+
),
282284
),
283285
// Recovers from panic, reports it and returns internal error.
284-
Repanic: false,
286+
sentrygrpc.WithRepanic(false),
285287
}
286288

287289
// This middleware sets *sentry.Hub to context. You can set user to
288290
// hub's scope in the later interceptor for example.
289-
sentry := sentrygrpc.UnaryServerInterceptor(opts)
291+
sentry := sentrygrpc.UnaryServerInterceptor(opts...)
290292

291293
server := grpc.NewServer(grpc.UnaryInterceptor(sentry))
292294
defer server.Stop()

0 commit comments

Comments
 (0)