From 1a8c2c3dff9e09b959aa26ae32669f763bb7a78c Mon Sep 17 00:00:00 2001 From: David Ashpole Date: Thu, 10 Feb 2022 17:13:13 -0500 Subject: [PATCH] allow users to override useragent (#322) --- exporter/metric/metric.go | 3 +- exporter/metric/metric_test.go | 137 +++++++++++++++++++-------------- 2 files changed, 80 insertions(+), 60 deletions(-) diff --git a/exporter/metric/metric.go b/exporter/metric/metric.go index 686dae919..d744df208 100644 --- a/exporter/metric/metric.go +++ b/exporter/metric/metric.go @@ -35,6 +35,7 @@ import ( monitoring "cloud.google.com/go/monitoring/apiv3/v2" "google.golang.org/api/option" + apioption "google.golang.org/api/option" googlemetricpb "google.golang.org/genproto/googleapis/api/metric" monitoredrespb "google.golang.org/genproto/googleapis/api/monitoredres" monitoringpb "google.golang.org/genproto/googleapis/monitoring/v3" @@ -127,7 +128,7 @@ func newMetricExporter(o *options) (*metricExporter, error) { return nil, errBlankProjectID } - clientOpts := append(o.MonitoringClientOptions, option.WithUserAgent(userAgent)) + clientOpts := append([]apioption.ClientOption{option.WithUserAgent(userAgent)}, o.MonitoringClientOptions...) ctx := o.Context if ctx == nil { ctx = context.Background() diff --git a/exporter/metric/metric_test.go b/exporter/metric/metric_test.go index 57e3dd8af..9ef341a04 100644 --- a/exporter/metric/metric_test.go +++ b/exporter/metric/metric_test.go @@ -552,70 +552,89 @@ func (m *mock) CreateMetricDescriptor(ctx context.Context, req *monitoringpb.Cre } func TestExportMetricsWithUserAgent(t *testing.T) { - server := grpc.NewServer() - t.Cleanup(server.Stop) - - // Channel to shove user agent strings from createTimeSeries - ch := make(chan []string, 1) - - m := mock{ - createTimeSeries: func(ctx context.Context, r *monitoringpb.CreateTimeSeriesRequest) (*emptypb.Empty, error) { - md, _ := metadata.FromIncomingContext(ctx) - ch <- md.Get("User-Agent") - return &emptypb.Empty{}, nil + for _, tc := range []struct { + desc string + extraOpts []option.ClientOption + expectedUserAgentRegex string + }{ + { + desc: "default", + expectedUserAgentRegex: "opentelemetry-go .*; google-cloud-metric-exporter .*", }, - createMetricDescriptor: func(ctx context.Context, req *monitoringpb.CreateMetricDescriptorRequest) (*googlemetricpb.MetricDescriptor, error) { - md, _ := metadata.FromIncomingContext(ctx) - ch <- md.Get("User-Agent") - return req.MetricDescriptor, nil + { + desc: "override user agent", + extraOpts: []option.ClientOption{option.WithUserAgent("test-user-agent")}, + expectedUserAgentRegex: "test-user-agent", }, - } - // Make sure all the calls have the right user agents. - // We have to run this in parallel because BOTH calls happen seamlessly when exporting metrics. - go func() { - for { - ua := <-ch - require.Regexp(t, "opentelemetry-go .*; google-cloud-metric-exporter .*", ua[0]) - } - }() - monitoringpb.RegisterMetricServiceServer(server, &m) - - lis, err := net.Listen("tcp", "127.0.0.1:0") - require.NoError(t, err) - go server.Serve(lis) - - clientOpts := []option.ClientOption{ - option.WithEndpoint(lis.Addr().String()), - option.WithoutAuthentication(), - option.WithGRPCDialOption(grpc.WithTransportCredentials(insecure.NewCredentials())), - } - res := &resource.Resource{} - aggSel := processortest.AggregatorSelector() - proc := processor.NewFactory(aggSel, aggregation.CumulativeTemporalitySelector()) - ctx := context.Background() - - opts := []Option{ - WithProjectID("PROJECT_ID_NOT_REAL"), - WithMonitoringClientOptions(clientOpts...), - WithMetricDescriptorTypeFormatter(formatter), - } + } { + t.Run(tc.desc, func(t *testing.T) { + server := grpc.NewServer() + t.Cleanup(server.Stop) + + // Channel to shove user agent strings from createTimeSeries + ch := make(chan []string, 1) + + m := mock{ + createTimeSeries: func(ctx context.Context, r *monitoringpb.CreateTimeSeriesRequest) (*emptypb.Empty, error) { + md, _ := metadata.FromIncomingContext(ctx) + ch <- md.Get("User-Agent") + return &emptypb.Empty{}, nil + }, + createMetricDescriptor: func(ctx context.Context, req *monitoringpb.CreateMetricDescriptorRequest) (*googlemetricpb.MetricDescriptor, error) { + md, _ := metadata.FromIncomingContext(ctx) + ch <- md.Get("User-Agent") + return req.MetricDescriptor, nil + }, + } + // Make sure all the calls have the right user agents. + // We have to run this in parallel because BOTH calls happen seamlessly when exporting metrics. + go func() { + for { + ua := <-ch + require.Regexp(t, tc.expectedUserAgentRegex, ua[0]) + } + }() + monitoringpb.RegisterMetricServiceServer(server, &m) + + lis, err := net.Listen("tcp", "127.0.0.1:0") + require.NoError(t, err) + go server.Serve(lis) + + clientOpts := []option.ClientOption{ + option.WithEndpoint(lis.Addr().String()), + option.WithoutAuthentication(), + option.WithGRPCDialOption(grpc.WithTransportCredentials(insecure.NewCredentials())), + } + clientOpts = append(clientOpts, tc.extraOpts...) + res := &resource.Resource{} + aggSel := processortest.AggregatorSelector() + proc := processor.NewFactory(aggSel, aggregation.CumulativeTemporalitySelector()) + ctx := context.Background() + + opts := []Option{ + WithProjectID("PROJECT_ID_NOT_REAL"), + WithMonitoringClientOptions(clientOpts...), + WithMetricDescriptorTypeFormatter(formatter), + } - exporter, err := NewRawExporter(opts...) - if err != nil { - t.Errorf("Error occurred when creating exporter: %v", err) - } - cont := controller.New(proc, - controller.WithExporter(exporter), - controller.WithResource(res), - ) + exporter, err := NewRawExporter(opts...) + if err != nil { + t.Errorf("Error occurred when creating exporter: %v", err) + } + cont := controller.New(proc, + controller.WithExporter(exporter), + controller.WithResource(res), + ) - assert.NoError(t, cont.Start(ctx)) - meter := cont.Meter("test") + assert.NoError(t, cont.Start(ctx)) + meter := cont.Meter("test") - counter := metric.Must(meter).NewInt64Counter("name.lastvalue") + counter := metric.Must(meter).NewInt64Counter("name.lastvalue") - counter.Add(ctx, 1) - require.NoError(t, cont.Stop(ctx)) + counter.Add(ctx, 1) + require.NoError(t, cont.Stop(ctx)) - // User agent checking happens above in parallel to this flow. + // User agent checking happens above in parallel to this flow. + }) + } }