diff --git a/gcp/observability/observability.go b/gcp/observability/observability.go index 40242692e8d2..1ab20d4cab5b 100644 --- a/gcp/observability/observability.go +++ b/gcp/observability/observability.go @@ -64,7 +64,7 @@ func Start(ctx context.Context) error { } // Enabling tracing and metrics via OpenCensus - if err := startOpenCensus(config, nil); err != nil { + if err := startOpenCensus(config); err != nil { return fmt.Errorf("failed to instrument OpenCensus: %v", err) } diff --git a/gcp/observability/observability_test.go b/gcp/observability/observability_test.go index c5fa59c6648f..18e3fd0f88fc 100644 --- a/gcp/observability/observability_test.go +++ b/gcp/observability/observability_test.go @@ -129,7 +129,6 @@ func (fle *fakeLoggingExporter) Close() error { type test struct { t *testing.T fle *fakeLoggingExporter - fe *fakeOpenCensusExporter testServer testgrpc.TestServiceServer // nil means none // srv and srvAddr are set once startServer is called. @@ -229,8 +228,7 @@ func (te *test) enableOpenCensus() { EnableCloudMonitoring: true, GlobalTraceSamplingRate: 1.0, } - te.fe = &fakeOpenCensusExporter{SeenViews: make(map[string]string), t: te.t} - startOpenCensus(config, te.fe) + startOpenCensus(config) } func checkEventCommon(t *testing.T, seen *grpclogrecordpb.GrpcLogRecord) { @@ -783,6 +781,16 @@ func (s) TestNoEnvSet(t *testing.T) { func (s) TestOpenCensusIntegration(t *testing.T) { te := newTest(t) defer te.tearDown() + fe := &fakeOpenCensusExporter{SeenViews: make(map[string]string), t: te.t} + + defer func(ne func(config *configpb.ObservabilityConfig) (tracingMetricsExporter, error)) { + newExporter = ne + }(newExporter) + + newExporter = func(config *configpb.ObservabilityConfig) (tracingMetricsExporter, error) { + return fe, nil + } + te.enableOpenCensus() te.startServer(&testServer{}) tc := testgrpc.NewTestServiceClient(te.clientConn()) @@ -807,17 +815,17 @@ func (s) TestOpenCensusIntegration(t *testing.T) { defer cancel() for ctx.Err() == nil { errs = nil - te.fe.mu.RLock() - if value := te.fe.SeenViews["grpc.io/client/completed_rpcs"]; value != TypeOpenCensusViewCount { + fe.mu.RLock() + if value := fe.SeenViews["grpc.io/client/completed_rpcs"]; value != TypeOpenCensusViewCount { errs = append(errs, fmt.Errorf("unexpected type for grpc.io/client/completed_rpcs: %s != %s", value, TypeOpenCensusViewCount)) } - if value := te.fe.SeenViews["grpc.io/server/completed_rpcs"]; value != TypeOpenCensusViewCount { + if value := fe.SeenViews["grpc.io/server/completed_rpcs"]; value != TypeOpenCensusViewCount { errs = append(errs, fmt.Errorf("unexpected type for grpc.io/server/completed_rpcs: %s != %s", value, TypeOpenCensusViewCount)) } - if te.fe.SeenSpans <= 0 { - errs = append(errs, fmt.Errorf("unexpected number of seen spans: %v <= 0", te.fe.SeenSpans)) + if fe.SeenSpans <= 0 { + errs = append(errs, fmt.Errorf("unexpected number of seen spans: %v <= 0", fe.SeenSpans)) } - te.fe.mu.RUnlock() + fe.mu.RUnlock() if len(errs) == 0 { break } diff --git a/gcp/observability/opencensus.go b/gcp/observability/opencensus.go index c303eb87f76b..410b90a1bc64 100644 --- a/gcp/observability/opencensus.go +++ b/gcp/observability/opencensus.go @@ -38,26 +38,41 @@ var ( defaultMetricsReportingInterval = time.Second * 30 ) +type tracingMetricsExporter interface { + trace.Exporter + view.Exporter +} + +// globals to stub out in tests +var newExporter = newStackdriverExporter + +func newStackdriverExporter(config *configpb.ObservabilityConfig) (tracingMetricsExporter, error) { + // Create the Stackdriver exporter, which is shared between tracing and stats + mr := monitoredresource.Autodetect() + logger.Infof("Detected MonitoredResource:: %+v", mr) + var err error + exporter, err := stackdriver.NewExporter(stackdriver.Options{ + ProjectID: config.DestinationProjectId, + MonitoredResource: mr, + }) + if err != nil { + return nil, fmt.Errorf("failed to create Stackdriver exporter: %v", err) + } + return exporter, nil +} + // This method accepts config and exporter; the exporter argument is exposed to // assist unit testing of the OpenCensus behavior. -func startOpenCensus(config *configpb.ObservabilityConfig, exporter interface{}) error { +func startOpenCensus(config *configpb.ObservabilityConfig) error { // If both tracing and metrics are disabled, there's no point inject default // StatsHandler. if config == nil || (!config.EnableCloudTrace && !config.EnableCloudMonitoring) { return nil } - if exporter == nil { - // Create the Stackdriver exporter, which is shared between tracing and stats - mr := monitoredresource.Autodetect() - logger.Infof("Detected MonitoredResource:: %+v", mr) - var err error - if exporter, err = stackdriver.NewExporter(stackdriver.Options{ - ProjectID: config.DestinationProjectId, - MonitoredResource: mr, - }); err != nil { - return fmt.Errorf("failed to create Stackdriver exporter: %v", err) - } + exporter, err := newExporter(config) + if err != nil { + return err } var so trace.StartOptions