From a75ade4edbe8fe4b8323c6a862242ffc6c68155c Mon Sep 17 00:00:00 2001 From: Anthony Mirabella Date: Fri, 4 Jun 2021 14:19:15 -0400 Subject: [PATCH] sdk/resource: honor OTEL_SERVICE_NAME in fromEnv resource detector (#1969) * sdk/resource: honor OTEL_SERVICE_NAME in fromEnv resource detector Signed-off-by: Anthony J Mirabella * go fmt is still my friend, even if I forget about it occasionally Signed-off-by: Anthony J Mirabella * Fix import ordering Signed-off-by: Anthony J Mirabella --- CHANGELOG.md | 1 + sdk/resource/env.go | 32 ++++++++++++++++++++++++-------- sdk/resource/env_test.go | 28 +++++++++++++++++++++++----- 3 files changed, 48 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 82e7ea7ff18..6d7b3fbb773 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm This method returns the number of list-members the `TraceState` holds. (#1937) - Creates package `go.opentelemetry.io/otel/exporters/otlp/otlptrace` that defines a trace exporter that uses a `otlptrace.Client` to send data. Creates package `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc` implementing a gRPC `otlptrace.Client` and offers convenience functions, `NewExportPipeline` and `InstallNewPipeline`, to setup and install a `otlptrace.Exporter` in tracing .(#1922) +- The `OTEL_SERVICE_NAME` environment variable is the preferred source for `service.name`, used by the environment resource detector if a service name is present both there and in `OTEL_RESOURCE_ATTRIBUTES`. (#1969) ### Changed diff --git a/sdk/resource/env.go b/sdk/resource/env.go index 35b99c129e2..4b5fe497a07 100644 --- a/sdk/resource/env.go +++ b/sdk/resource/env.go @@ -21,10 +21,16 @@ import ( "strings" "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/semconv" ) -// envVar is the environment variable name OpenTelemetry Resource information can be assigned to. -const envVar = "OTEL_RESOURCE_ATTRIBUTES" +const ( + // resourceAttrKey is the environment variable name OpenTelemetry Resource information will be read from. + resourceAttrKey = "OTEL_RESOURCE_ATTRIBUTES" + + // svcNameKey is the environment variable name that Service Name information will be read from. + svcNameKey = "OTEL_SERVICE_NAME" +) var ( // errMissingValue is returned when a resource value is missing. @@ -33,9 +39,7 @@ var ( // fromEnv is a Detector that implements the Detector and collects // resources from environment. This Detector is included as a -// builtin. If these resource attributes are not wanted, use the -// WithFromEnv(nil) or WithoutBuiltin() options to explicitly disable -// them. +// builtin. type fromEnv struct{} // compile time assertion that FromEnv implements Detector interface @@ -43,12 +47,24 @@ var _ Detector = fromEnv{} // Detect collects resources from environment func (fromEnv) Detect(context.Context) (*Resource, error) { - attrs := strings.TrimSpace(os.Getenv(envVar)) + attrs := strings.TrimSpace(os.Getenv(resourceAttrKey)) + svcName := strings.TrimSpace(os.Getenv(svcNameKey)) - if attrs == "" { + if attrs == "" && svcName == "" { return Empty(), nil } - return constructOTResources(attrs) + + var res *Resource + + if svcName != "" { + res = NewWithAttributes(semconv.ServiceNameKey.String(svcName)) + } + + r2, err := constructOTResources(attrs) + + // Ensure that the resource with the service name from OTEL_SERVICE_NAME + // takes precedence, if it was defined. + return Merge(r2, res), err } func constructOTResources(s string) (*Resource, error) { diff --git a/sdk/resource/env_test.go b/sdk/resource/env_test.go index 78bd68346b2..6aeca346ab9 100644 --- a/sdk/resource/env_test.go +++ b/sdk/resource/env_test.go @@ -24,11 +24,12 @@ import ( "go.opentelemetry.io/otel/attribute" ottest "go.opentelemetry.io/otel/internal/internaltest" + "go.opentelemetry.io/otel/semconv" ) func TestDetectOnePair(t *testing.T) { store, err := ottest.SetEnvVariables(map[string]string{ - envVar: "key=value", + resourceAttrKey: "key=value", }) require.NoError(t, err) defer func() { require.NoError(t, store.Restore()) }() @@ -41,8 +42,8 @@ func TestDetectOnePair(t *testing.T) { func TestDetectMultiPairs(t *testing.T) { store, err := ottest.SetEnvVariables(map[string]string{ - "x": "1", - envVar: "key=value, k = v , a= x, a=z", + "x": "1", + resourceAttrKey: "key=value, k = v , a= x, a=z", }) require.NoError(t, err) defer func() { require.NoError(t, store.Restore()) }() @@ -60,7 +61,7 @@ func TestDetectMultiPairs(t *testing.T) { func TestEmpty(t *testing.T) { store, err := ottest.SetEnvVariables(map[string]string{ - envVar: " ", + resourceAttrKey: " ", }) require.NoError(t, err) defer func() { require.NoError(t, store.Restore()) }() @@ -73,7 +74,7 @@ func TestEmpty(t *testing.T) { func TestMissingKeyError(t *testing.T) { store, err := ottest.SetEnvVariables(map[string]string{ - envVar: "key=value,key", + resourceAttrKey: "key=value,key", }) require.NoError(t, err) defer func() { require.NoError(t, store.Restore()) }() @@ -86,3 +87,20 @@ func TestMissingKeyError(t *testing.T) { attribute.String("key", "value"), )) } + +func TestDetectServiceNameFromEnv(t *testing.T) { + store, err := ottest.SetEnvVariables(map[string]string{ + resourceAttrKey: "key=value,service.name=foo", + svcNameKey: "bar", + }) + require.NoError(t, err) + defer func() { require.NoError(t, store.Restore()) }() + + detector := &fromEnv{} + res, err := detector.Detect(context.Background()) + require.NoError(t, err) + assert.Equal(t, res, NewWithAttributes( + attribute.String("key", "value"), + semconv.ServiceNameKey.String("bar"), + )) +}