...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package 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
31 resourceAttrKey = "OTEL_RESOURCE_ATTRIBUTES"
32
33
34 svcNameKey = "OTEL_SERVICE_NAME"
35 )
36
37
38 var errMissingValue = fmt.Errorf("%w: missing value", ErrPartialResource)
39
40
41
42
43 type fromEnv struct{}
44
45
46 var _ Detector = fromEnv{}
47
48
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
66
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
95
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