1// Copyright The OpenTelemetry Authors
2// SPDX-License-Identifier: Apache-2.0
3
4package metric // import "go.opentelemetry.io/otel/metric"
5
6import "go.opentelemetry.io/otel/attribute"
7
8// Observable is used as a grouping mechanism for all instruments that are
9// updated within a Callback.
10type Observable interface {
11 observable()
12}
13
14// InstrumentOption applies options to all instruments.
15type InstrumentOption interface {
16 Int64CounterOption
17 Int64UpDownCounterOption
18 Int64HistogramOption
19 Int64GaugeOption
20 Int64ObservableCounterOption
21 Int64ObservableUpDownCounterOption
22 Int64ObservableGaugeOption
23
24 Float64CounterOption
25 Float64UpDownCounterOption
26 Float64HistogramOption
27 Float64GaugeOption
28 Float64ObservableCounterOption
29 Float64ObservableUpDownCounterOption
30 Float64ObservableGaugeOption
31}
32
33// HistogramOption applies options to histogram instruments.
34type HistogramOption interface {
35 Int64HistogramOption
36 Float64HistogramOption
37}
38
39type descOpt string
40
41func (o descOpt) applyFloat64Counter(c Float64CounterConfig) Float64CounterConfig {
42 c.description = string(o)
43 return c
44}
45
46func (o descOpt) applyFloat64UpDownCounter(c Float64UpDownCounterConfig) Float64UpDownCounterConfig {
47 c.description = string(o)
48 return c
49}
50
51func (o descOpt) applyFloat64Histogram(c Float64HistogramConfig) Float64HistogramConfig {
52 c.description = string(o)
53 return c
54}
55
56func (o descOpt) applyFloat64Gauge(c Float64GaugeConfig) Float64GaugeConfig {
57 c.description = string(o)
58 return c
59}
60
61func (o descOpt) applyFloat64ObservableCounter(c Float64ObservableCounterConfig) Float64ObservableCounterConfig {
62 c.description = string(o)
63 return c
64}
65
66func (o descOpt) applyFloat64ObservableUpDownCounter(c Float64ObservableUpDownCounterConfig) Float64ObservableUpDownCounterConfig {
67 c.description = string(o)
68 return c
69}
70
71func (o descOpt) applyFloat64ObservableGauge(c Float64ObservableGaugeConfig) Float64ObservableGaugeConfig {
72 c.description = string(o)
73 return c
74}
75
76func (o descOpt) applyInt64Counter(c Int64CounterConfig) Int64CounterConfig {
77 c.description = string(o)
78 return c
79}
80
81func (o descOpt) applyInt64UpDownCounter(c Int64UpDownCounterConfig) Int64UpDownCounterConfig {
82 c.description = string(o)
83 return c
84}
85
86func (o descOpt) applyInt64Histogram(c Int64HistogramConfig) Int64HistogramConfig {
87 c.description = string(o)
88 return c
89}
90
91func (o descOpt) applyInt64Gauge(c Int64GaugeConfig) Int64GaugeConfig {
92 c.description = string(o)
93 return c
94}
95
96func (o descOpt) applyInt64ObservableCounter(c Int64ObservableCounterConfig) Int64ObservableCounterConfig {
97 c.description = string(o)
98 return c
99}
100
101func (o descOpt) applyInt64ObservableUpDownCounter(c Int64ObservableUpDownCounterConfig) Int64ObservableUpDownCounterConfig {
102 c.description = string(o)
103 return c
104}
105
106func (o descOpt) applyInt64ObservableGauge(c Int64ObservableGaugeConfig) Int64ObservableGaugeConfig {
107 c.description = string(o)
108 return c
109}
110
111// WithDescription sets the instrument description.
112func WithDescription(desc string) InstrumentOption { return descOpt(desc) }
113
114type unitOpt string
115
116func (o unitOpt) applyFloat64Counter(c Float64CounterConfig) Float64CounterConfig {
117 c.unit = string(o)
118 return c
119}
120
121func (o unitOpt) applyFloat64UpDownCounter(c Float64UpDownCounterConfig) Float64UpDownCounterConfig {
122 c.unit = string(o)
123 return c
124}
125
126func (o unitOpt) applyFloat64Histogram(c Float64HistogramConfig) Float64HistogramConfig {
127 c.unit = string(o)
128 return c
129}
130
131func (o unitOpt) applyFloat64Gauge(c Float64GaugeConfig) Float64GaugeConfig {
132 c.unit = string(o)
133 return c
134}
135
136func (o unitOpt) applyFloat64ObservableCounter(c Float64ObservableCounterConfig) Float64ObservableCounterConfig {
137 c.unit = string(o)
138 return c
139}
140
141func (o unitOpt) applyFloat64ObservableUpDownCounter(c Float64ObservableUpDownCounterConfig) Float64ObservableUpDownCounterConfig {
142 c.unit = string(o)
143 return c
144}
145
146func (o unitOpt) applyFloat64ObservableGauge(c Float64ObservableGaugeConfig) Float64ObservableGaugeConfig {
147 c.unit = string(o)
148 return c
149}
150
151func (o unitOpt) applyInt64Counter(c Int64CounterConfig) Int64CounterConfig {
152 c.unit = string(o)
153 return c
154}
155
156func (o unitOpt) applyInt64UpDownCounter(c Int64UpDownCounterConfig) Int64UpDownCounterConfig {
157 c.unit = string(o)
158 return c
159}
160
161func (o unitOpt) applyInt64Histogram(c Int64HistogramConfig) Int64HistogramConfig {
162 c.unit = string(o)
163 return c
164}
165
166func (o unitOpt) applyInt64Gauge(c Int64GaugeConfig) Int64GaugeConfig {
167 c.unit = string(o)
168 return c
169}
170
171func (o unitOpt) applyInt64ObservableCounter(c Int64ObservableCounterConfig) Int64ObservableCounterConfig {
172 c.unit = string(o)
173 return c
174}
175
176func (o unitOpt) applyInt64ObservableUpDownCounter(c Int64ObservableUpDownCounterConfig) Int64ObservableUpDownCounterConfig {
177 c.unit = string(o)
178 return c
179}
180
181func (o unitOpt) applyInt64ObservableGauge(c Int64ObservableGaugeConfig) Int64ObservableGaugeConfig {
182 c.unit = string(o)
183 return c
184}
185
186// WithUnit sets the instrument unit.
187//
188// The unit u should be defined using the appropriate [UCUM](https://ucum.org) case-sensitive code.
189func WithUnit(u string) InstrumentOption { return unitOpt(u) }
190
191// WithExplicitBucketBoundaries sets the instrument explicit bucket boundaries.
192//
193// This option is considered "advisory", and may be ignored by API implementations.
194func WithExplicitBucketBoundaries(bounds ...float64) HistogramOption { return bucketOpt(bounds) }
195
196type bucketOpt []float64
197
198func (o bucketOpt) applyFloat64Histogram(c Float64HistogramConfig) Float64HistogramConfig {
199 c.explicitBucketBoundaries = o
200 return c
201}
202
203func (o bucketOpt) applyInt64Histogram(c Int64HistogramConfig) Int64HistogramConfig {
204 c.explicitBucketBoundaries = o
205 return c
206}
207
208// AddOption applies options to an addition measurement. See
209// [MeasurementOption] for other options that can be used as an AddOption.
210type AddOption interface {
211 applyAdd(AddConfig) AddConfig
212}
213
214// AddConfig contains options for an addition measurement.
215type AddConfig struct {
216 attrs attribute.Set
217}
218
219// NewAddConfig returns a new [AddConfig] with all opts applied.
220func NewAddConfig(opts []AddOption) AddConfig {
221 config := AddConfig{attrs: *attribute.EmptySet()}
222 for _, o := range opts {
223 config = o.applyAdd(config)
224 }
225 return config
226}
227
228// Attributes returns the configured attribute set.
229func (c AddConfig) Attributes() attribute.Set {
230 return c.attrs
231}
232
233// RecordOption applies options to an addition measurement. See
234// [MeasurementOption] for other options that can be used as a RecordOption.
235type RecordOption interface {
236 applyRecord(RecordConfig) RecordConfig
237}
238
239// RecordConfig contains options for a recorded measurement.
240type RecordConfig struct {
241 attrs attribute.Set
242}
243
244// NewRecordConfig returns a new [RecordConfig] with all opts applied.
245func NewRecordConfig(opts []RecordOption) RecordConfig {
246 config := RecordConfig{attrs: *attribute.EmptySet()}
247 for _, o := range opts {
248 config = o.applyRecord(config)
249 }
250 return config
251}
252
253// Attributes returns the configured attribute set.
254func (c RecordConfig) Attributes() attribute.Set {
255 return c.attrs
256}
257
258// ObserveOption applies options to an addition measurement. See
259// [MeasurementOption] for other options that can be used as a ObserveOption.
260type ObserveOption interface {
261 applyObserve(ObserveConfig) ObserveConfig
262}
263
264// ObserveConfig contains options for an observed measurement.
265type ObserveConfig struct {
266 attrs attribute.Set
267}
268
269// NewObserveConfig returns a new [ObserveConfig] with all opts applied.
270func NewObserveConfig(opts []ObserveOption) ObserveConfig {
271 config := ObserveConfig{attrs: *attribute.EmptySet()}
272 for _, o := range opts {
273 config = o.applyObserve(config)
274 }
275 return config
276}
277
278// Attributes returns the configured attribute set.
279func (c ObserveConfig) Attributes() attribute.Set {
280 return c.attrs
281}
282
283// MeasurementOption applies options to all instrument measurement.
284type MeasurementOption interface {
285 AddOption
286 RecordOption
287 ObserveOption
288}
289
290type attrOpt struct {
291 set attribute.Set
292}
293
294// mergeSets returns the union of keys between a and b. Any duplicate keys will
295// use the value associated with b.
296func mergeSets(a, b attribute.Set) attribute.Set {
297 // NewMergeIterator uses the first value for any duplicates.
298 iter := attribute.NewMergeIterator(&b, &a)
299 merged := make([]attribute.KeyValue, 0, a.Len()+b.Len())
300 for iter.Next() {
301 merged = append(merged, iter.Attribute())
302 }
303 return attribute.NewSet(merged...)
304}
305
306func (o attrOpt) applyAdd(c AddConfig) AddConfig {
307 switch {
308 case o.set.Len() == 0:
309 case c.attrs.Len() == 0:
310 c.attrs = o.set
311 default:
312 c.attrs = mergeSets(c.attrs, o.set)
313 }
314 return c
315}
316
317func (o attrOpt) applyRecord(c RecordConfig) RecordConfig {
318 switch {
319 case o.set.Len() == 0:
320 case c.attrs.Len() == 0:
321 c.attrs = o.set
322 default:
323 c.attrs = mergeSets(c.attrs, o.set)
324 }
325 return c
326}
327
328func (o attrOpt) applyObserve(c ObserveConfig) ObserveConfig {
329 switch {
330 case o.set.Len() == 0:
331 case c.attrs.Len() == 0:
332 c.attrs = o.set
333 default:
334 c.attrs = mergeSets(c.attrs, o.set)
335 }
336 return c
337}
338
339// WithAttributeSet sets the attribute Set associated with a measurement is
340// made with.
341//
342// If multiple WithAttributeSet or WithAttributes options are passed the
343// attributes will be merged together in the order they are passed. Attributes
344// with duplicate keys will use the last value passed.
345func WithAttributeSet(attributes attribute.Set) MeasurementOption {
346 return attrOpt{set: attributes}
347}
348
349// WithAttributes converts attributes into an attribute Set and sets the Set to
350// be associated with a measurement. This is shorthand for:
351//
352// cp := make([]attribute.KeyValue, len(attributes))
353// copy(cp, attributes)
354// WithAttributeSet(attribute.NewSet(cp...))
355//
356// [attribute.NewSet] may modify the passed attributes so this will make a copy
357// of attributes before creating a set in order to ensure this function is
358// concurrent safe. This makes this option function less optimized in
359// comparison to [WithAttributeSet]. Therefore, [WithAttributeSet] should be
360// preferred for performance sensitive code.
361//
362// See [WithAttributeSet] for information about how multiple WithAttributes are
363// merged.
364func WithAttributes(attributes ...attribute.KeyValue) MeasurementOption {
365 cp := make([]attribute.KeyValue, len(attributes))
366 copy(cp, attributes)
367 return attrOpt{set: attribute.NewSet(cp...)}
368}