Skip to content
Draft
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
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,9 @@ require (
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0
go.opentelemetry.io/otel v1.38.0
go.opentelemetry.io/otel/exporters/prometheus v0.57.0
go.opentelemetry.io/otel/sdk v1.38.0
go.opentelemetry.io/otel/sdk/metric v1.38.0
go.opentelemetry.io/otel/trace v1.38.0
go.uber.org/atomic v1.11.0
go.uber.org/goleak v1.3.0
Expand Down Expand Up @@ -429,7 +431,6 @@ require (
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0 // indirect
go.opentelemetry.io/otel/metric v1.38.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
go.uber.org/automaxprocs v1.6.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2563,6 +2563,8 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0u
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0 h1:FyjCyI9jVEfqhUh2MoSkmolPjfh5fp2hnV0b0irxH4Q=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0/go.mod h1:hYwym2nDEeZfG/motx0p7L7J1N1vyzIThemQsb4g2qY=
go.opentelemetry.io/otel/exporters/prometheus v0.57.0 h1:AHh/lAP1BHrY5gBwk8ncc25FXWm/gmmY3BX258z5nuk=
go.opentelemetry.io/otel/exporters/prometheus v0.57.0/go.mod h1:QpFWz1QxqevfjwzYdbMb4Y1NnlJvqSGwyuU0B4iuc9c=
go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8=
go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM=
go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY=
Expand Down
64 changes: 51 additions & 13 deletions internal/datastore/spanner/spanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
otelprom "go.opentelemetry.io/otel/exporters/prometheus"
"go.opentelemetry.io/otel/sdk/metric"
otelres "go.opentelemetry.io/otel/sdk/resource"
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
"go.opentelemetry.io/otel/trace"
"google.golang.org/api/option"
"google.golang.org/grpc"
Expand Down Expand Up @@ -101,6 +105,7 @@
tableSizesStatsTable string
filterMaximumIDCount uint16
uniqueID atomic.Pointer[string]
meterProvider *metric.MeterProvider
}

// NewSpannerDatastore returns a datastore backed by cloud spanner
Expand All @@ -125,9 +130,23 @@
log.Info().Str("spanner-emulator-host", os.Getenv("SPANNER_EMULATOR_HOST")).Msg("running against spanner emulator")
}

var meterProvider *metric.MeterProvider
if config.datastoreMetricsOption == DatastoreMetricsOptionOpenTelemetry {
log.Info().Msg("enabling OpenTelemetry metrics for Spanner datastore")
spanner.EnableOpenTelemetryMetrics()

res, err := otelres.Merge(otelres.Default(),
otelres.NewWithAttributes(semconv.SchemaURL,
semconv.ServiceName("spicedb"),
))
if err != nil {
return nil, fmt.Errorf("failed to create otel metrics resource: %w", err)

Check warning on line 143 in internal/datastore/spanner/spanner.go

View check run for this annotation

Codecov / codecov/patch

internal/datastore/spanner/spanner.go#L138-L143

Added lines #L138 - L143 were not covered by tests
}

meterProvider, err = getMeterProviderWithPromExporter(res)
if err != nil {
return nil, fmt.Errorf("failed to enable Spanner prometheus metrics: %w", err)

Check warning on line 148 in internal/datastore/spanner/spanner.go

View check run for this annotation

Codecov / codecov/patch

internal/datastore/spanner/spanner.go#L146-L148

Added lines #L146 - L148 were not covered by tests
}
}

if config.datastoreMetricsOption == DatastoreMetricsOptionLegacyPrometheus {
Expand All @@ -136,23 +155,21 @@
if err != nil {
return nil, fmt.Errorf("failed to enable spanner session metrics: %w", err)
}

err = spanner.EnableGfeLatencyAndHeaderMissingCountViews() // nolint: staticcheck
if err != nil {
return nil, fmt.Errorf("failed to enable spanner GFE metrics: %w", err)
}
}

// Register Spanner client gRPC metrics (include round-trip latency, received/sent bytes...)
if err := view.Register(ocgrpc.DefaultClientViews...); err != nil {
return nil, fmt.Errorf("failed to enable gRPC metrics for Spanner client: %w", err)
}
// Register Spanner client gRPC metrics (include round-trip latency, received/sent bytes...)
if err := view.Register(ocgrpc.DefaultClientViews...); err != nil {
return nil, fmt.Errorf("failed to enable gRPC metrics for Spanner client: %w", err)

Check warning on line 166 in internal/datastore/spanner/spanner.go

View check run for this annotation

Codecov / codecov/patch

internal/datastore/spanner/spanner.go#L165-L166

Added lines #L165 - L166 were not covered by tests
}

_, err = ocprom.NewExporter(ocprom.Options{
Namespace: "spicedb",
Registerer: prometheus.DefaultRegisterer,
})
if err != nil {
return nil, fmt.Errorf("failed to enable spanner GFE latency stats: %w", err)
_, err = ocprom.NewExporter(ocprom.Options{

Check failure on line 169 in internal/datastore/spanner/spanner.go

View workflow job for this annotation

GitHub Actions / Lint Everything

ineffectual assignment to err (ineffassign)
Namespace: "spicedb",
Registerer: prometheus.DefaultRegisterer,
})

Check warning on line 172 in internal/datastore/spanner/spanner.go

View check run for this annotation

Codecov / codecov/patch

internal/datastore/spanner/spanner.go#L169-L172

Added lines #L169 - L172 were not covered by tests
}

cfg := spanner.DefaultSessionPoolConfig
Expand All @@ -178,8 +195,9 @@
context.Background(),
database,
spanner.ClientConfig{
SessionPoolConfig: cfg,
DisableNativeMetrics: config.datastoreMetricsOption != DatastoreMetricsOptionNative,
SessionPoolConfig: cfg,
DisableNativeMetrics: config.datastoreMetricsOption != DatastoreMetricsOptionNative,
OpenTelemetryMeterProvider: meterProvider,
},
spannerOpts...,
)
Expand Down Expand Up @@ -246,6 +264,7 @@
tableSizesStatsTable: tableSizesStatsTable,
filterMaximumIDCount: config.filterMaximumIDCount,
schema: *schema,
meterProvider: meterProvider,
}
// Optimized revision and revision checking use a stale read for the
// current timestamp.
Expand All @@ -256,6 +275,20 @@
return ds, nil
}

func getMeterProviderWithPromExporter(res *otelres.Resource) (*metric.MeterProvider, error) {
exporter, err := otelprom.New()
if err != nil {
return nil, err

Check warning on line 281 in internal/datastore/spanner/spanner.go

View check run for this annotation

Codecov / codecov/patch

internal/datastore/spanner/spanner.go#L278-L281

Added lines #L278 - L281 were not covered by tests
}

meterProvider := metric.NewMeterProvider(
metric.WithResource(res),
metric.WithReader(exporter),
)

Check warning on line 287 in internal/datastore/spanner/spanner.go

View check run for this annotation

Codecov / codecov/patch

internal/datastore/spanner/spanner.go#L284-L287

Added lines #L284 - L287 were not covered by tests

return meterProvider, nil

Check warning on line 289 in internal/datastore/spanner/spanner.go

View check run for this annotation

Codecov / codecov/patch

internal/datastore/spanner/spanner.go#L289

Added line #L289 was not covered by tests
}

type traceableRTX struct {
delegate readTX
}
Expand Down Expand Up @@ -415,6 +448,11 @@

func (sd *spannerDatastore) Close() error {
sd.client.Close()

if sd.meterProvider != nil {
return sd.meterProvider.ForceFlush(context.TODO())

Check warning on line 453 in internal/datastore/spanner/spanner.go

View check run for this annotation

Codecov / codecov/patch

internal/datastore/spanner/spanner.go#L453

Added line #L453 was not covered by tests
}

return nil
}

Expand Down
Loading