...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package resource
16
17 import (
18 "context"
19 "errors"
20 "sync"
21
22 "go.opentelemetry.io/otel"
23 "go.opentelemetry.io/otel/attribute"
24 )
25
26
27
28
29
30
31
32
33 type Resource struct {
34 attrs attribute.Set
35 schemaURL string
36 }
37
38 var (
39 defaultResource *Resource
40 defaultResourceOnce sync.Once
41 )
42
43 var errMergeConflictSchemaURL = errors.New("cannot merge resource due to conflicting Schema URL")
44
45
46 func New(ctx context.Context, opts ...Option) (*Resource, error) {
47 cfg := config{}
48 for _, opt := range opts {
49 cfg = opt.apply(cfg)
50 }
51
52 r := &Resource{schemaURL: cfg.schemaURL}
53 return r, detect(ctx, r, cfg.detectors)
54 }
55
56
57
58
59
60 func NewWithAttributes(schemaURL string, attrs ...attribute.KeyValue) *Resource {
61 resource := NewSchemaless(attrs...)
62 resource.schemaURL = schemaURL
63 return resource
64 }
65
66
67
68
69
70 func NewSchemaless(attrs ...attribute.KeyValue) *Resource {
71 if len(attrs) == 0 {
72 return &Resource{}
73 }
74
75
76
77 s, _ := attribute.NewSetWithFiltered(attrs, func(kv attribute.KeyValue) bool {
78 return kv.Valid()
79 })
80
81
82 if s.Len() == 0 {
83 return &Resource{}
84 }
85
86 return &Resource{attrs: s}
87 }
88
89
90
91
92
93
94 func (r *Resource) String() string {
95 if r == nil {
96 return ""
97 }
98 return r.attrs.Encoded(attribute.DefaultEncoder())
99 }
100
101
102 func (r *Resource) MarshalLog() interface{} {
103 return struct {
104 Attributes attribute.Set
105 SchemaURL string
106 }{
107 Attributes: r.attrs,
108 SchemaURL: r.schemaURL,
109 }
110 }
111
112
113
114 func (r *Resource) Attributes() []attribute.KeyValue {
115 if r == nil {
116 r = Empty()
117 }
118 return r.attrs.ToSlice()
119 }
120
121
122 func (r *Resource) SchemaURL() string {
123 if r == nil {
124 return ""
125 }
126 return r.schemaURL
127 }
128
129
130
131 func (r *Resource) Iter() attribute.Iterator {
132 if r == nil {
133 r = Empty()
134 }
135 return r.attrs.Iter()
136 }
137
138
139 func (r *Resource) Equal(eq *Resource) bool {
140 if r == nil {
141 r = Empty()
142 }
143 if eq == nil {
144 eq = Empty()
145 }
146 return r.Equivalent() == eq.Equivalent()
147 }
148
149
150
151
152
153
154
155
156
157
158
159 func Merge(a, b *Resource) (*Resource, error) {
160 if a == nil && b == nil {
161 return Empty(), nil
162 }
163 if a == nil {
164 return b, nil
165 }
166 if b == nil {
167 return a, nil
168 }
169
170
171 var schemaURL string
172 switch true {
173 case a.schemaURL == "":
174 schemaURL = b.schemaURL
175 case b.schemaURL == "":
176 schemaURL = a.schemaURL
177 case a.schemaURL == b.schemaURL:
178 schemaURL = a.schemaURL
179 default:
180 return Empty(), errMergeConflictSchemaURL
181 }
182
183
184
185 mi := attribute.NewMergeIterator(b.Set(), a.Set())
186 combine := make([]attribute.KeyValue, 0, a.Len()+b.Len())
187 for mi.Next() {
188 combine = append(combine, mi.Attribute())
189 }
190 merged := NewWithAttributes(schemaURL, combine...)
191 return merged, nil
192 }
193
194
195
196 func Empty() *Resource {
197 return &Resource{}
198 }
199
200
201
202 func Default() *Resource {
203 defaultResourceOnce.Do(func() {
204 var err error
205 defaultResource, err = Detect(
206 context.Background(),
207 defaultServiceNameDetector{},
208 fromEnv{},
209 telemetrySDK{},
210 )
211 if err != nil {
212 otel.Handle(err)
213 }
214
215 if defaultResource == nil {
216 defaultResource = &Resource{}
217 }
218 })
219 return defaultResource
220 }
221
222
223
224 func Environment() *Resource {
225 detector := &fromEnv{}
226 resource, err := detector.Detect(context.Background())
227 if err != nil {
228 otel.Handle(err)
229 }
230 return resource
231 }
232
233
234
235
236 func (r *Resource) Equivalent() attribute.Distinct {
237 return r.Set().Equivalent()
238 }
239
240
241 func (r *Resource) Set() *attribute.Set {
242 if r == nil {
243 r = Empty()
244 }
245 return &r.attrs
246 }
247
248
249
250 func (r *Resource) MarshalJSON() ([]byte, error) {
251 if r == nil {
252 r = Empty()
253 }
254 return r.attrs.MarshalJSON()
255 }
256
257
258 func (r *Resource) Len() int {
259 if r == nil {
260 return 0
261 }
262 return r.attrs.Len()
263 }
264
265
266 func (r *Resource) Encoded(enc attribute.Encoder) string {
267 if r == nil {
268 return ""
269 }
270 return r.attrs.Encoded(enc)
271 }
272
View as plain text