Skip to content

Commit c3b75c9

Browse files
authored
feat: add tracing to proto validation (#2950)
1 parent c3eea34 commit c3b75c9

File tree

7 files changed

+42
-5
lines changed

7 files changed

+42
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
66
## [Unreleased]
77
### Changed
88
- Updated CI so that Postgres tests run against v18 which is GA and not against v13 which is EOL (https://github.com/authzed/spicedb/pull/2926)
9+
- Added tracing to request validation (https://github.com/authzed/spicedb/pull/2950)
910

1011
### Fixed
1112
- Regression introduced in 1.49.2: missing spans in ReadSchema calls (https://github.com/authzed/spicedb/pull/2947)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
// Package handwrittenvalidation defines middleware that runs custom-made validations on incoming requests.
1+
// Package handwrittenvalidation defines middleware that runs validations on incoming requests.
22
package handwrittenvalidation
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package interceptorwrapper
2+
3+
import (
4+
"context"
5+
6+
"go.opentelemetry.io/otel"
7+
"google.golang.org/grpc"
8+
)
9+
10+
var tracer = otel.Tracer("spicedb/internal/middleware")
11+
12+
// WrapUnaryServerInterceptorWithSpans returns a new interceptor that wraps the given interceptor
13+
// with a span, measuring the duration of the interceptor's pre-handler logic.
14+
func WrapUnaryServerInterceptorWithSpans(
15+
inner grpc.UnaryServerInterceptor,
16+
spanName string,
17+
) grpc.UnaryServerInterceptor {
18+
return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
19+
_, span := tracer.Start(ctx, spanName)
20+
// NOTE: this shim is what lets us measure how long the interceptor is doing work.
21+
// It's the handler that we pass to the wrapped interceptor, so `span.End()` will be
22+
// called when the handler itself is called.
23+
shimHandler := func(ctx context.Context, req any) (any, error) {
24+
span.End()
25+
return handler(ctx, req)
26+
}
27+
resp, err := inner(ctx, req, info, shimHandler)
28+
if span.IsRecording() {
29+
span.End()
30+
}
31+
return resp, err
32+
}
33+
}

internal/services/v1/experimental.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
log "github.com/authzed/spicedb/internal/logging"
2525
"github.com/authzed/spicedb/internal/middleware"
2626
"github.com/authzed/spicedb/internal/middleware/handwrittenvalidation"
27+
"github.com/authzed/spicedb/internal/middleware/interceptorwrapper"
2728
"github.com/authzed/spicedb/internal/middleware/perfinsights"
2829
"github.com/authzed/spicedb/internal/middleware/streamtimeout"
2930
"github.com/authzed/spicedb/internal/middleware/usagemetrics"
@@ -99,7 +100,7 @@ func NewExperimentalServer(dispatch dispatch.Dispatcher, permServerConfig Permis
99100
return &experimentalServer{
100101
WithServiceSpecificInterceptors: shared.WithServiceSpecificInterceptors{
101102
Unary: middleware.ChainUnaryServer(
102-
grpcvalidate.UnaryServerInterceptor(validator),
103+
interceptorwrapper.WrapUnaryServerInterceptorWithSpans(grpcvalidate.UnaryServerInterceptor(validator), "protovalidate"),
103104
handwrittenvalidation.UnaryServerInterceptor,
104105
usagemetrics.UnaryServerInterceptor(),
105106
perfinsights.UnaryServerInterceptor(permServerConfig.PerformanceInsightMetricsEnabled),

internal/services/v1/relationships.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/authzed/spicedb/internal/dispatch"
2020
"github.com/authzed/spicedb/internal/middleware"
2121
"github.com/authzed/spicedb/internal/middleware/handwrittenvalidation"
22+
"github.com/authzed/spicedb/internal/middleware/interceptorwrapper"
2223
"github.com/authzed/spicedb/internal/middleware/perfinsights"
2324
"github.com/authzed/spicedb/internal/middleware/streamtimeout"
2425
"github.com/authzed/spicedb/internal/middleware/usagemetrics"
@@ -153,7 +154,7 @@ func NewPermissionsServer(
153154
config: configWithDefaults,
154155
WithServiceSpecificInterceptors: shared.WithServiceSpecificInterceptors{
155156
Unary: middleware.ChainUnaryServer(
156-
grpcvalidate.UnaryServerInterceptor(validator),
157+
interceptorwrapper.WrapUnaryServerInterceptorWithSpans(grpcvalidate.UnaryServerInterceptor(validator), "protovalidate"),
157158
handwrittenvalidation.UnaryServerInterceptor,
158159
usagemetrics.UnaryServerInterceptor(),
159160
perfinsights.UnaryServerInterceptor(configWithDefaults.PerformanceInsightMetricsEnabled),

internal/services/v1/schema.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
log "github.com/authzed/spicedb/internal/logging"
1313
"github.com/authzed/spicedb/internal/middleware"
14+
"github.com/authzed/spicedb/internal/middleware/interceptorwrapper"
1415
"github.com/authzed/spicedb/internal/middleware/perfinsights"
1516
"github.com/authzed/spicedb/internal/middleware/usagemetrics"
1617
"github.com/authzed/spicedb/internal/services/shared"
@@ -50,7 +51,7 @@ func NewSchemaServer(config SchemaServerConfig) v1.SchemaServiceServer {
5051
return &schemaServer{
5152
WithServiceSpecificInterceptors: shared.WithServiceSpecificInterceptors{
5253
Unary: middleware.ChainUnaryServer(
53-
grpcvalidate.UnaryServerInterceptor(validator),
54+
interceptorwrapper.WrapUnaryServerInterceptorWithSpans(grpcvalidate.UnaryServerInterceptor(validator), "protovalidate"),
5455
usagemetrics.UnaryServerInterceptor(),
5556
perfinsights.UnaryServerInterceptor(config.PerformanceInsightMetricsEnabled),
5657
),

internal/services/v1/watch.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func (ws *watchServer) Watch(req *v1.WatchRequest, stream v1.WatchService_WatchS
5252
}
5353
}
5454

55-
objectTypes := mapz.NewSet[string](req.GetOptionalObjectTypes()...)
55+
objectTypes := mapz.NewSet(req.GetOptionalObjectTypes()...)
5656

5757
ctx := stream.Context()
5858
dl := datalayer.MustFromContext(ctx)

0 commit comments

Comments
 (0)