Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased]
### Changed
- 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)
- Added tracing to request validation (https://github.com/authzed/spicedb/pull/2950)

### Fixed
- Regression introduced in 1.49.2: missing spans in ReadSchema calls (https://github.com/authzed/spicedb/pull/2947)
Expand Down
2 changes: 1 addition & 1 deletion internal/middleware/handwrittenvalidation/doc.go
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
// Package handwrittenvalidation defines middleware that runs custom-made validations on incoming requests.
// Package handwrittenvalidation defines middleware that runs validations on incoming requests.
package handwrittenvalidation
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe i should rename the package...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also might be able to get rid of this package? I haven't actually looked into it

33 changes: 33 additions & 0 deletions internal/middleware/interceptorwrapper/interceptorwrapper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package interceptorwrapper

import (
"context"

"go.opentelemetry.io/otel"
"google.golang.org/grpc"
)

var tracer = otel.Tracer("spicedb/internal/middleware")

// WrapUnaryServerInterceptorWithSpans returns a new interceptor that wraps the given interceptor
// with a span, measuring the duration of the interceptor's pre-handler logic.
func WrapUnaryServerInterceptorWithSpans(
Copy link
Contributor Author

@miparnisari miparnisari Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tstirrat15 is the idea to wrap more interceptors with this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the idea - it's here if we want it.

inner grpc.UnaryServerInterceptor,
spanName string,
) grpc.UnaryServerInterceptor {
return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
_, span := tracer.Start(ctx, spanName)
// NOTE: this shim is what lets us measure how long the interceptor is doing work.
// It's the handler that we pass to the wrapped interceptor, so `span.End()` will be
// called when the handler itself is called.
shimHandler := func(ctx context.Context, req any) (any, error) {
span.End()
return handler(ctx, req)
}
resp, err := inner(ctx, req, info, shimHandler)
if span.IsRecording() {
span.End()
}

Check warning on line 30 in internal/middleware/interceptorwrapper/interceptorwrapper.go

View check run for this annotation

Codecov / codecov/patch

internal/middleware/interceptorwrapper/interceptorwrapper.go#L29-L30

Added lines #L29 - L30 were not covered by tests
return resp, err
}
}
3 changes: 2 additions & 1 deletion internal/services/v1/experimental.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
log "github.com/authzed/spicedb/internal/logging"
"github.com/authzed/spicedb/internal/middleware"
"github.com/authzed/spicedb/internal/middleware/handwrittenvalidation"
"github.com/authzed/spicedb/internal/middleware/interceptorwrapper"
"github.com/authzed/spicedb/internal/middleware/perfinsights"
"github.com/authzed/spicedb/internal/middleware/streamtimeout"
"github.com/authzed/spicedb/internal/middleware/usagemetrics"
Expand Down Expand Up @@ -99,7 +100,7 @@ func NewExperimentalServer(dispatch dispatch.Dispatcher, permServerConfig Permis
return &experimentalServer{
WithServiceSpecificInterceptors: shared.WithServiceSpecificInterceptors{
Unary: middleware.ChainUnaryServer(
grpcvalidate.UnaryServerInterceptor(validator),
interceptorwrapper.WrapUnaryServerInterceptorWithSpans(grpcvalidate.UnaryServerInterceptor(validator), "protovalidate"),
handwrittenvalidation.UnaryServerInterceptor,
usagemetrics.UnaryServerInterceptor(),
perfinsights.UnaryServerInterceptor(permServerConfig.PerformanceInsightMetricsEnabled),
Expand Down
3 changes: 2 additions & 1 deletion internal/services/v1/relationships.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/authzed/spicedb/internal/dispatch"
"github.com/authzed/spicedb/internal/middleware"
"github.com/authzed/spicedb/internal/middleware/handwrittenvalidation"
"github.com/authzed/spicedb/internal/middleware/interceptorwrapper"
"github.com/authzed/spicedb/internal/middleware/perfinsights"
"github.com/authzed/spicedb/internal/middleware/streamtimeout"
"github.com/authzed/spicedb/internal/middleware/usagemetrics"
Expand Down Expand Up @@ -153,7 +154,7 @@ func NewPermissionsServer(
config: configWithDefaults,
WithServiceSpecificInterceptors: shared.WithServiceSpecificInterceptors{
Unary: middleware.ChainUnaryServer(
grpcvalidate.UnaryServerInterceptor(validator),
interceptorwrapper.WrapUnaryServerInterceptorWithSpans(grpcvalidate.UnaryServerInterceptor(validator), "protovalidate"),
handwrittenvalidation.UnaryServerInterceptor,
usagemetrics.UnaryServerInterceptor(),
perfinsights.UnaryServerInterceptor(configWithDefaults.PerformanceInsightMetricsEnabled),
Expand Down
3 changes: 2 additions & 1 deletion internal/services/v1/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

log "github.com/authzed/spicedb/internal/logging"
"github.com/authzed/spicedb/internal/middleware"
"github.com/authzed/spicedb/internal/middleware/interceptorwrapper"
"github.com/authzed/spicedb/internal/middleware/perfinsights"
"github.com/authzed/spicedb/internal/middleware/usagemetrics"
"github.com/authzed/spicedb/internal/services/shared"
Expand Down Expand Up @@ -50,7 +51,7 @@ func NewSchemaServer(config SchemaServerConfig) v1.SchemaServiceServer {
return &schemaServer{
WithServiceSpecificInterceptors: shared.WithServiceSpecificInterceptors{
Unary: middleware.ChainUnaryServer(
grpcvalidate.UnaryServerInterceptor(validator),
interceptorwrapper.WrapUnaryServerInterceptorWithSpans(grpcvalidate.UnaryServerInterceptor(validator), "protovalidate"),
usagemetrics.UnaryServerInterceptor(),
perfinsights.UnaryServerInterceptor(config.PerformanceInsightMetricsEnabled),
),
Expand Down
2 changes: 1 addition & 1 deletion internal/services/v1/watch.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func (ws *watchServer) Watch(req *v1.WatchRequest, stream v1.WatchService_WatchS
}
}

objectTypes := mapz.NewSet[string](req.GetOptionalObjectTypes()...)
objectTypes := mapz.NewSet(req.GetOptionalObjectTypes()...)

ctx := stream.Context()
dl := datalayer.MustFromContext(ctx)
Expand Down
Loading