Skip to content

Commit

Permalink
sdk/resource: honor OTEL_SERVICE_NAME in fromEnv resource detector (#…
Browse files Browse the repository at this point in the history
…1969)

* sdk/resource: honor OTEL_SERVICE_NAME in fromEnv resource detector

Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>

* go fmt is still my friend, even if I forget about it occasionally

Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>

* Fix import ordering

Signed-off-by: Anthony J Mirabella <a9@aneurysm9.com>
  • Loading branch information
Aneurysm9 committed Jun 4, 2021
1 parent aed4580 commit a75ade4
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 13 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -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

Expand Down
32 changes: 24 additions & 8 deletions sdk/resource/env.go
Expand Up @@ -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.
Expand All @@ -33,22 +39,32 @@ 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
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) {
Expand Down
28 changes: 23 additions & 5 deletions sdk/resource/env_test.go
Expand Up @@ -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()) }()
Expand All @@ -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()) }()
Expand All @@ -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()) }()
Expand All @@ -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()) }()
Expand All @@ -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"),
))
}

0 comments on commit a75ade4

Please sign in to comment.