gotosocial/vendor/go.opentelemetry.io/otel/sdk/resource/env.go

96 lines
2.5 KiB
Go
Raw Normal View History

2023-05-09 20:19:48 +03:00
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
2023-05-09 20:19:48 +03:00
package resource // import "go.opentelemetry.io/otel/sdk/resource"
import (
"context"
"fmt"
"net/url"
"os"
"strings"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
2024-08-26 19:05:54 +03:00
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
2023-05-09 20:19:48 +03:00
)
const (
// resourceAttrKey is the environment variable name OpenTelemetry Resource information will be read from.
2023-11-13 13:08:02 +03:00
resourceAttrKey = "OTEL_RESOURCE_ATTRIBUTES" //nolint:gosec // False positive G101: Potential hardcoded credentials
2023-05-09 20:19:48 +03:00
// svcNameKey is the environment variable name that Service Name information will be read from.
svcNameKey = "OTEL_SERVICE_NAME"
)
2023-11-13 13:08:02 +03:00
// errMissingValue is returned when a resource value is missing.
var errMissingValue = fmt.Errorf("%w: missing value", ErrPartialResource)
2023-05-09 20:19:48 +03:00
// fromEnv is a Detector that implements the Detector and collects
// resources from environment. This Detector is included as a
// 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(resourceAttrKey))
svcName := strings.TrimSpace(os.Getenv(svcNameKey))
if attrs == "" && svcName == "" {
return Empty(), nil
}
var res *Resource
if svcName != "" {
res = NewSchemaless(semconv.ServiceName(svcName))
}
r2, err := constructOTResources(attrs)
// Ensure that the resource with the service name from OTEL_SERVICE_NAME
// takes precedence, if it was defined.
res, err2 := Merge(r2, res)
if err == nil {
err = err2
} else if err2 != nil {
err = fmt.Errorf("detecting resources: %s", []string{err.Error(), err2.Error()})
}
return res, err
}
func constructOTResources(s string) (*Resource, error) {
if s == "" {
return Empty(), nil
}
pairs := strings.Split(s, ",")
var attrs []attribute.KeyValue
2023-05-09 20:19:48 +03:00
var invalid []string
for _, p := range pairs {
k, v, found := strings.Cut(p, "=")
if !found {
2023-05-09 20:19:48 +03:00
invalid = append(invalid, p)
continue
}
key := strings.TrimSpace(k)
2023-11-13 13:08:02 +03:00
val, err := url.PathUnescape(strings.TrimSpace(v))
2023-05-09 20:19:48 +03:00
if err != nil {
// Retain original value if decoding fails, otherwise it will be
// an empty string.
val = v
2023-05-09 20:19:48 +03:00
otel.Handle(err)
}
attrs = append(attrs, attribute.String(key, val))
2023-05-09 20:19:48 +03:00
}
var err error
if len(invalid) > 0 {
err = fmt.Errorf("%w: %v", errMissingValue, invalid)
}
return NewSchemaless(attrs...), err
}