diff --git a/spanner/client.go b/spanner/client.go index 6f048643f6df..1e21f5934029 100644 --- a/spanner/client.go +++ b/spanner/client.go @@ -507,8 +507,7 @@ func newClientWithConfig(ctx context.Context, database string, config ClientConf metricsProvider = noop.NewMeterProvider() } - // Create a OpenTelemetry metrics configuration - metricsTracerFactory, err := newBuiltinMetricsTracerFactory(ctx, database, metricsProvider, opts...) + metricsTracerFactory, err := newBuiltinMetricsTracerFactory(ctx, database, metricsProvider, config.Compression, opts...) if err != nil { return nil, err } diff --git a/spanner/metrics.go b/spanner/metrics.go index ffa57aa39d3e..a765e004f15a 100644 --- a/spanner/metrics.go +++ b/spanner/metrics.go @@ -21,11 +21,10 @@ import ( "errors" "fmt" "hash/fnv" - "strings" - "log" "os" "strconv" + "strings" "time" "github.com/google/uuid" @@ -198,7 +197,7 @@ type builtinMetricsTracerFactory struct { attemptCount metric.Int64Counter // Counter for the number of attempts. } -func newBuiltinMetricsTracerFactory(ctx context.Context, dbpath string, metricsProvider metric.MeterProvider, opts ...option.ClientOption) (*builtinMetricsTracerFactory, error) { +func newBuiltinMetricsTracerFactory(ctx context.Context, dbpath string, metricsProvider metric.MeterProvider, compression string, opts ...option.ClientOption) (*builtinMetricsTracerFactory, error) { clientUID, err := generateClientUID() if err != nil { log.Printf("built-in metrics: generateClientUID failed: %v. Using empty string in the %v metric atteribute", err, metricLabelKeyClientUID) @@ -229,7 +228,7 @@ func newBuiltinMetricsTracerFactory(ctx context.Context, dbpath string, metricsP var meterProvider *sdkmetric.MeterProvider if metricsProvider == nil { // Create default meter provider - mpOptions, err := builtInMeterProviderOptions(project, opts...) + mpOptions, err := builtInMeterProviderOptions(project, compression, opts...) if err != nil { return tracerFactory, err } @@ -252,9 +251,9 @@ func newBuiltinMetricsTracerFactory(ctx context.Context, dbpath string, metricsP return tracerFactory, err } -func builtInMeterProviderOptions(project string, opts ...option.ClientOption) ([]sdkmetric.Option, error) { +func builtInMeterProviderOptions(project, compression string, opts ...option.ClientOption) ([]sdkmetric.Option, error) { allOpts := createExporterOptions(opts...) - defaultExporter, err := newMonitoringExporter(context.Background(), project, allOpts...) + defaultExporter, err := newMonitoringExporter(context.Background(), project, compression, allOpts...) if err != nil { return nil, err } diff --git a/spanner/metrics_monitoring_exporter.go b/spanner/metrics_monitoring_exporter.go index d70365935f6e..d776ae62bf86 100644 --- a/spanner/metrics_monitoring_exporter.go +++ b/spanner/metrics_monitoring_exporter.go @@ -39,6 +39,7 @@ import ( googlemetricpb "google.golang.org/genproto/googleapis/api/metric" monitoredrespb "google.golang.org/genproto/googleapis/api/monitoredres" "google.golang.org/grpc/codes" + "google.golang.org/grpc/encoding/gzip" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/timestamppb" ) @@ -76,21 +77,22 @@ func (e errUnexpectedAggregationKind) Error() string { // Google Cloud Monitoring. // Default exporter for built-in metrics type monitoringExporter struct { - shutdown chan struct{} - client *monitoring.MetricClient - shutdownOnce sync.Once - projectID string + shutdown chan struct{} + client *monitoring.MetricClient + shutdownOnce sync.Once + projectID, compression string } -func newMonitoringExporter(ctx context.Context, project string, opts ...option.ClientOption) (*monitoringExporter, error) { +func newMonitoringExporter(ctx context.Context, project, compression string, opts ...option.ClientOption) (*monitoringExporter, error) { client, err := monitoring.NewMetricClient(ctx, opts...) if err != nil { return nil, err } return &monitoringExporter{ - client: client, - shutdown: make(chan struct{}), - projectID: project, + client: client, + shutdown: make(chan struct{}), + projectID: project, + compression: compression, }, nil } @@ -137,19 +139,21 @@ func (me *monitoringExporter) exportTimeSeries(ctx context.Context, rm *otelmetr } name := fmt.Sprintf("projects/%s", me.projectID) - + ctx = callctx.SetHeaders(ctx, "x-goog-api-client", "gccl/"+internal.Version) + if me.compression == gzip.Name { + ctx = callctx.SetHeaders(ctx, requestsCompressionHeader, gzip.Name) + } errs := []error{err} for i := 0; i < len(tss); i += sendBatchSize { j := i + sendBatchSize if j >= len(tss) { j = len(tss) } - req := &monitoringpb.CreateTimeSeriesRequest{ Name: name, TimeSeries: tss[i:j], } - err = me.client.CreateServiceTimeSeries(callctx.SetHeaders(ctx, "x-goog-api-client", "gccl/"+internal.Version), req) + err = me.client.CreateServiceTimeSeries(ctx, req) if err != nil { if status.Code(err) == codes.PermissionDenied { err = fmt.Errorf("%w Need monitoring metric writer permission on project=%s. Follow https://cloud.google.com/spanner/docs/view-manage-client-side-metrics#access-client-side-metrics to set up permissions", diff --git a/spanner/read_test.go b/spanner/read_test.go index 99ab2362a1ee..9f6f3602595b 100644 --- a/spanner/read_test.go +++ b/spanner/read_test.go @@ -1778,7 +1778,7 @@ func TestIteratorStopEarly(t *testing.T) { } func TestIteratorWithError(t *testing.T) { - metricsTracerFactory, err := newBuiltinMetricsTracerFactory(context.Background(), "projects/my-project/instances/my-instance/databases/my-database", noop.NewMeterProvider()) + metricsTracerFactory, err := newBuiltinMetricsTracerFactory(context.Background(), "projects/my-project/instances/my-instance/databases/my-database", noop.NewMeterProvider(), "identity") if err != nil { t.Fatalf("failed to create metrics tracer factory: %v", err) }