diff --git a/instrumentation/opentelemetry/init.go b/instrumentation/opentelemetry/init.go index c4b70f2..0949fce 100644 --- a/instrumentation/opentelemetry/init.go +++ b/instrumentation/opentelemetry/init.go @@ -351,12 +351,12 @@ func InitWithSpanProcessorWrapperAndZap(cfg *config.AgentConfig, wrapper SpanPro return func() { mu.Lock() defer mu.Unlock() - for serviceName, tracerProvider := range traceProviders { + for envServicePair, tracerProvider := range traceProviders { err := tracerProvider.Shutdown(context.Background()) if err != nil { log.Printf("error while shutting down tracer provider: %v\n", err) } - delete(traceProviders, serviceName) + delete(traceProviders, envServicePair) } traceProviders = map[string]*sdktrace.TracerProvider{} err := tp.Shutdown(context.Background()) @@ -405,8 +405,13 @@ func RegisterServiceWithSpanProcessorWrapper(serviceName string, resourceAttribu return NoopStartSpan, noop.NewTracerProvider(), nil } - if _, ok := traceProviders[serviceName]; ok { - return nil, noop.NewTracerProvider(), fmt.Errorf("service %v already initialized", serviceName) + environment, ok := resourceAttributes[environmentKey] + if !ok { + environment = defaultEnvironment + } + envServicePair := encodeEnvServicePair(environment, serviceName) + if _, ok := traceProviders[envServicePair]; ok { + return nil, noop.NewTracerProvider(), fmt.Errorf("service %v environment %v already initialized", serviceName, environment) } exporter, err := exporterFactory() @@ -435,7 +440,7 @@ func RegisterServiceWithSpanProcessorWrapper(serviceName string, resourceAttribu sdktrace.WithResource(resources), ) - traceProviders[serviceName] = tp + traceProviders[envServicePair] = tp return startSpan(func() trace.TracerProvider { return tp }), tp, nil diff --git a/instrumentation/opentelemetry/init_additional.go b/instrumentation/opentelemetry/init_additional.go index f932768..ee900f4 100644 --- a/instrumentation/opentelemetry/init_additional.go +++ b/instrumentation/opentelemetry/init_additional.go @@ -13,6 +13,11 @@ import ( "go.opentelemetry.io/otel/sdk/trace" ) +const ( + environmentKey = "deployment.environment" + defaultEnvironment = "default" +) + // InitAsAdditional initializes opentelemetry tracing and returns a span processor and a shutdown // function to flush data immediately on a termination signal. // This is ideal for when we use goagent along with other opentelemetry setups. @@ -151,3 +156,7 @@ func MakeRemoveGoAgentAttrs(attrsRemovalPrefixes []string) func(sp trace.SpanExp return &attrsRemover{sp, attrsRemovalPrefixes} } } + +func encodeEnvServicePair(environment string, serviceName string) string { + return environment + "::SEP::" + serviceName +} diff --git a/instrumentation/opentelemetry/init_test.go b/instrumentation/opentelemetry/init_test.go index be40584..1bcd5d5 100644 --- a/instrumentation/opentelemetry/init_test.go +++ b/instrumentation/opentelemetry/init_test.go @@ -441,3 +441,34 @@ func TestConfigFactory(t *testing.T) { factory := makeConfigFactory(cfg) assert.Same(t, cfg, factory()) } + +func TestMultipleRegisterService(t *testing.T) { + cfg := config.Load() + cfg.ServiceName = config.String("my_example_svc") + cfg.DataCapture.HttpHeaders.Request = config.Bool(true) + cfg.Reporting.TraceReporterType = config.TraceReporterType_LOGGING + + shutdown := Init(cfg) + defer shutdown() + + _, _, err := RegisterService("custom_service_1", map[string]string{environmentKey: "env_1"}) + assert.Nil(t, err) + + _, _, err = RegisterService("custom_service_2", map[string]string{environmentKey: "env_1"}) + assert.Nil(t, err) + + _, _, err = RegisterService("custom_service_2", map[string]string{environmentKey: "env_2"}) + assert.Nil(t, err) + + _, _, err = RegisterService("custom_service_1", map[string]string{environmentKey: "env_1"}) + assert.NotNil(t, err) + + _, _, err = RegisterService("custom_service_1", map[string]string{}) + assert.Nil(t, err) + + _, _, err = RegisterService("custom_service_2", map[string]string{}) + assert.Nil(t, err) + + _, _, err = RegisterService("custom_service_1", map[string]string{}) + assert.NotNil(t, err) +}