...

Source file src/go.opentelemetry.io/otel/sdk/resource/env.go

Documentation: go.opentelemetry.io/otel/sdk/resource

     1  // Copyright The OpenTelemetry Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package resource // import "go.opentelemetry.io/otel/sdk/resource"
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"net/url"
    21  	"os"
    22  	"strings"
    23  
    24  	"go.opentelemetry.io/otel"
    25  	"go.opentelemetry.io/otel/attribute"
    26  	semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
    27  )
    28  
    29  const (
    30  	// resourceAttrKey is the environment variable name OpenTelemetry Resource information will be read from.
    31  	resourceAttrKey = "OTEL_RESOURCE_ATTRIBUTES" //nolint:gosec // False positive G101: Potential hardcoded credentials
    32  
    33  	// svcNameKey is the environment variable name that Service Name information will be read from.
    34  	svcNameKey = "OTEL_SERVICE_NAME"
    35  )
    36  
    37  // errMissingValue is returned when a resource value is missing.
    38  var errMissingValue = fmt.Errorf("%w: missing value", ErrPartialResource)
    39  
    40  // fromEnv is a Detector that implements the Detector and collects
    41  // resources from environment.  This Detector is included as a
    42  // builtin.
    43  type fromEnv struct{}
    44  
    45  // compile time assertion that FromEnv implements Detector interface.
    46  var _ Detector = fromEnv{}
    47  
    48  // Detect collects resources from environment.
    49  func (fromEnv) Detect(context.Context) (*Resource, error) {
    50  	attrs := strings.TrimSpace(os.Getenv(resourceAttrKey))
    51  	svcName := strings.TrimSpace(os.Getenv(svcNameKey))
    52  
    53  	if attrs == "" && svcName == "" {
    54  		return Empty(), nil
    55  	}
    56  
    57  	var res *Resource
    58  
    59  	if svcName != "" {
    60  		res = NewSchemaless(semconv.ServiceName(svcName))
    61  	}
    62  
    63  	r2, err := constructOTResources(attrs)
    64  
    65  	// Ensure that the resource with the service name from OTEL_SERVICE_NAME
    66  	// takes precedence, if it was defined.
    67  	res, err2 := Merge(r2, res)
    68  
    69  	if err == nil {
    70  		err = err2
    71  	} else if err2 != nil {
    72  		err = fmt.Errorf("detecting resources: %s", []string{err.Error(), err2.Error()})
    73  	}
    74  
    75  	return res, err
    76  }
    77  
    78  func constructOTResources(s string) (*Resource, error) {
    79  	if s == "" {
    80  		return Empty(), nil
    81  	}
    82  	pairs := strings.Split(s, ",")
    83  	var attrs []attribute.KeyValue
    84  	var invalid []string
    85  	for _, p := range pairs {
    86  		k, v, found := strings.Cut(p, "=")
    87  		if !found {
    88  			invalid = append(invalid, p)
    89  			continue
    90  		}
    91  		key := strings.TrimSpace(k)
    92  		val, err := url.PathUnescape(strings.TrimSpace(v))
    93  		if err != nil {
    94  			// Retain original value if decoding fails, otherwise it will be
    95  			// an empty string.
    96  			val = v
    97  			otel.Handle(err)
    98  		}
    99  		attrs = append(attrs, attribute.String(key, val))
   100  	}
   101  	var err error
   102  	if len(invalid) > 0 {
   103  		err = fmt.Errorf("%w: %v", errMissingValue, invalid)
   104  	}
   105  	return NewSchemaless(attrs...), err
   106  }
   107  

View as plain text