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