You've already forked opentelemetry-go
mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2026-06-03 18:35:08 +02:00
28df982c8b
Part of https://github.com/open-telemetry/opentelemetry-go/issues/8110 Related to https://github.com/open-telemetry/opentelemetry-go/issues/5882. I'm hoping to find a better way to support experimental Options types in our API packages. This is one approach to consider. This contains no public API changes. It introduces a type: `ExperimentalOption` in `/metric/internal/x`, which can be used by our experimental options defined outside of the module. Options that embed this interface are ignored by `New*Config` builder functions in the metrics API to prevent them from panicing when used. Only SDKs that explicitly support the experimental option in question will respect it. Alternative SDKs will ignore the experimental options. We would still need to treat ExperimentalOption as a stable artifact, since the SDK will indirectly depend on it. See https://github.com/open-telemetry/opentelemetry-go/compare/main...dashpole:opentelemetry-go:attributes_advisory for how this would be used to support the advisory attributes parameter.
388 lines
10 KiB
Go
388 lines
10 KiB
Go
// Copyright The OpenTelemetry Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package metric // import "go.opentelemetry.io/otel/metric"
|
|
|
|
import (
|
|
"go.opentelemetry.io/otel/attribute"
|
|
)
|
|
|
|
// Observable is used as a grouping mechanism for all instruments that are
|
|
// updated within a Callback.
|
|
type Observable interface {
|
|
observable()
|
|
}
|
|
|
|
// InstrumentOption applies options to all instruments.
|
|
type InstrumentOption interface {
|
|
Int64CounterOption
|
|
Int64UpDownCounterOption
|
|
Int64HistogramOption
|
|
Int64GaugeOption
|
|
Int64ObservableCounterOption
|
|
Int64ObservableUpDownCounterOption
|
|
Int64ObservableGaugeOption
|
|
|
|
Float64CounterOption
|
|
Float64UpDownCounterOption
|
|
Float64HistogramOption
|
|
Float64GaugeOption
|
|
Float64ObservableCounterOption
|
|
Float64ObservableUpDownCounterOption
|
|
Float64ObservableGaugeOption
|
|
}
|
|
|
|
// HistogramOption applies options to histogram instruments.
|
|
type HistogramOption interface {
|
|
Int64HistogramOption
|
|
Float64HistogramOption
|
|
}
|
|
|
|
type descOpt string
|
|
|
|
func (o descOpt) applyFloat64Counter(c Float64CounterConfig) Float64CounterConfig {
|
|
c.description = string(o)
|
|
return c
|
|
}
|
|
|
|
func (o descOpt) applyFloat64UpDownCounter(c Float64UpDownCounterConfig) Float64UpDownCounterConfig {
|
|
c.description = string(o)
|
|
return c
|
|
}
|
|
|
|
func (o descOpt) applyFloat64Histogram(c Float64HistogramConfig) Float64HistogramConfig {
|
|
c.description = string(o)
|
|
return c
|
|
}
|
|
|
|
func (o descOpt) applyFloat64Gauge(c Float64GaugeConfig) Float64GaugeConfig {
|
|
c.description = string(o)
|
|
return c
|
|
}
|
|
|
|
func (o descOpt) applyFloat64ObservableCounter(c Float64ObservableCounterConfig) Float64ObservableCounterConfig {
|
|
c.description = string(o)
|
|
return c
|
|
}
|
|
|
|
func (o descOpt) applyFloat64ObservableUpDownCounter(
|
|
c Float64ObservableUpDownCounterConfig,
|
|
) Float64ObservableUpDownCounterConfig {
|
|
c.description = string(o)
|
|
return c
|
|
}
|
|
|
|
func (o descOpt) applyFloat64ObservableGauge(c Float64ObservableGaugeConfig) Float64ObservableGaugeConfig {
|
|
c.description = string(o)
|
|
return c
|
|
}
|
|
|
|
func (o descOpt) applyInt64Counter(c Int64CounterConfig) Int64CounterConfig {
|
|
c.description = string(o)
|
|
return c
|
|
}
|
|
|
|
func (o descOpt) applyInt64UpDownCounter(c Int64UpDownCounterConfig) Int64UpDownCounterConfig {
|
|
c.description = string(o)
|
|
return c
|
|
}
|
|
|
|
func (o descOpt) applyInt64Histogram(c Int64HistogramConfig) Int64HistogramConfig {
|
|
c.description = string(o)
|
|
return c
|
|
}
|
|
|
|
func (o descOpt) applyInt64Gauge(c Int64GaugeConfig) Int64GaugeConfig {
|
|
c.description = string(o)
|
|
return c
|
|
}
|
|
|
|
func (o descOpt) applyInt64ObservableCounter(c Int64ObservableCounterConfig) Int64ObservableCounterConfig {
|
|
c.description = string(o)
|
|
return c
|
|
}
|
|
|
|
func (o descOpt) applyInt64ObservableUpDownCounter(
|
|
c Int64ObservableUpDownCounterConfig,
|
|
) Int64ObservableUpDownCounterConfig {
|
|
c.description = string(o)
|
|
return c
|
|
}
|
|
|
|
func (o descOpt) applyInt64ObservableGauge(c Int64ObservableGaugeConfig) Int64ObservableGaugeConfig {
|
|
c.description = string(o)
|
|
return c
|
|
}
|
|
|
|
// WithDescription sets the instrument description.
|
|
func WithDescription(desc string) InstrumentOption { return descOpt(desc) }
|
|
|
|
type unitOpt string
|
|
|
|
func (o unitOpt) applyFloat64Counter(c Float64CounterConfig) Float64CounterConfig {
|
|
c.unit = string(o)
|
|
return c
|
|
}
|
|
|
|
func (o unitOpt) applyFloat64UpDownCounter(c Float64UpDownCounterConfig) Float64UpDownCounterConfig {
|
|
c.unit = string(o)
|
|
return c
|
|
}
|
|
|
|
func (o unitOpt) applyFloat64Histogram(c Float64HistogramConfig) Float64HistogramConfig {
|
|
c.unit = string(o)
|
|
return c
|
|
}
|
|
|
|
func (o unitOpt) applyFloat64Gauge(c Float64GaugeConfig) Float64GaugeConfig {
|
|
c.unit = string(o)
|
|
return c
|
|
}
|
|
|
|
func (o unitOpt) applyFloat64ObservableCounter(c Float64ObservableCounterConfig) Float64ObservableCounterConfig {
|
|
c.unit = string(o)
|
|
return c
|
|
}
|
|
|
|
func (o unitOpt) applyFloat64ObservableUpDownCounter(
|
|
c Float64ObservableUpDownCounterConfig,
|
|
) Float64ObservableUpDownCounterConfig {
|
|
c.unit = string(o)
|
|
return c
|
|
}
|
|
|
|
func (o unitOpt) applyFloat64ObservableGauge(c Float64ObservableGaugeConfig) Float64ObservableGaugeConfig {
|
|
c.unit = string(o)
|
|
return c
|
|
}
|
|
|
|
func (o unitOpt) applyInt64Counter(c Int64CounterConfig) Int64CounterConfig {
|
|
c.unit = string(o)
|
|
return c
|
|
}
|
|
|
|
func (o unitOpt) applyInt64UpDownCounter(c Int64UpDownCounterConfig) Int64UpDownCounterConfig {
|
|
c.unit = string(o)
|
|
return c
|
|
}
|
|
|
|
func (o unitOpt) applyInt64Histogram(c Int64HistogramConfig) Int64HistogramConfig {
|
|
c.unit = string(o)
|
|
return c
|
|
}
|
|
|
|
func (o unitOpt) applyInt64Gauge(c Int64GaugeConfig) Int64GaugeConfig {
|
|
c.unit = string(o)
|
|
return c
|
|
}
|
|
|
|
func (o unitOpt) applyInt64ObservableCounter(c Int64ObservableCounterConfig) Int64ObservableCounterConfig {
|
|
c.unit = string(o)
|
|
return c
|
|
}
|
|
|
|
func (o unitOpt) applyInt64ObservableUpDownCounter(
|
|
c Int64ObservableUpDownCounterConfig,
|
|
) Int64ObservableUpDownCounterConfig {
|
|
c.unit = string(o)
|
|
return c
|
|
}
|
|
|
|
func (o unitOpt) applyInt64ObservableGauge(c Int64ObservableGaugeConfig) Int64ObservableGaugeConfig {
|
|
c.unit = string(o)
|
|
return c
|
|
}
|
|
|
|
// WithUnit sets the instrument unit.
|
|
//
|
|
// The unit u should be defined using the appropriate [UCUM](https://ucum.org) case-sensitive code.
|
|
func WithUnit(u string) InstrumentOption { return unitOpt(u) }
|
|
|
|
// WithExplicitBucketBoundaries sets the instrument explicit bucket boundaries.
|
|
//
|
|
// This option is considered "advisory", and may be ignored by API implementations.
|
|
func WithExplicitBucketBoundaries(bounds ...float64) HistogramOption { return bucketOpt(bounds) }
|
|
|
|
type bucketOpt []float64
|
|
|
|
func (o bucketOpt) applyFloat64Histogram(c Float64HistogramConfig) Float64HistogramConfig {
|
|
c.explicitBucketBoundaries = o
|
|
return c
|
|
}
|
|
|
|
func (o bucketOpt) applyInt64Histogram(c Int64HistogramConfig) Int64HistogramConfig {
|
|
c.explicitBucketBoundaries = o
|
|
return c
|
|
}
|
|
|
|
// AddOption applies options to an addition measurement. See
|
|
// [MeasurementOption] for other options that can be used as an AddOption.
|
|
type AddOption interface {
|
|
applyAdd(AddConfig) AddConfig
|
|
}
|
|
|
|
// AddConfig contains options for an addition measurement.
|
|
type AddConfig struct {
|
|
attrs attribute.Set
|
|
}
|
|
|
|
// NewAddConfig returns a new [AddConfig] with all opts applied.
|
|
func NewAddConfig(opts []AddOption) AddConfig {
|
|
config := AddConfig{attrs: *attribute.EmptySet()}
|
|
for _, o := range opts {
|
|
if _, ok := o.(experimentalOption); ok {
|
|
continue
|
|
}
|
|
config = o.applyAdd(config)
|
|
}
|
|
return config
|
|
}
|
|
|
|
// Attributes returns the configured attribute set.
|
|
func (c AddConfig) Attributes() attribute.Set {
|
|
return c.attrs
|
|
}
|
|
|
|
// RecordOption applies options to an addition measurement. See
|
|
// [MeasurementOption] for other options that can be used as a RecordOption.
|
|
type RecordOption interface {
|
|
applyRecord(RecordConfig) RecordConfig
|
|
}
|
|
|
|
// RecordConfig contains options for a recorded measurement.
|
|
type RecordConfig struct {
|
|
attrs attribute.Set
|
|
}
|
|
|
|
// NewRecordConfig returns a new [RecordConfig] with all opts applied.
|
|
func NewRecordConfig(opts []RecordOption) RecordConfig {
|
|
config := RecordConfig{attrs: *attribute.EmptySet()}
|
|
for _, o := range opts {
|
|
if _, ok := o.(experimentalOption); ok {
|
|
continue
|
|
}
|
|
config = o.applyRecord(config)
|
|
}
|
|
return config
|
|
}
|
|
|
|
// Attributes returns the configured attribute set.
|
|
func (c RecordConfig) Attributes() attribute.Set {
|
|
return c.attrs
|
|
}
|
|
|
|
// ObserveOption applies options to an addition measurement. See
|
|
// [MeasurementOption] for other options that can be used as a ObserveOption.
|
|
type ObserveOption interface {
|
|
applyObserve(ObserveConfig) ObserveConfig
|
|
}
|
|
|
|
// ObserveConfig contains options for an observed measurement.
|
|
type ObserveConfig struct {
|
|
attrs attribute.Set
|
|
}
|
|
|
|
// NewObserveConfig returns a new [ObserveConfig] with all opts applied.
|
|
func NewObserveConfig(opts []ObserveOption) ObserveConfig {
|
|
config := ObserveConfig{attrs: *attribute.EmptySet()}
|
|
for _, o := range opts {
|
|
if _, ok := o.(experimentalOption); ok {
|
|
continue
|
|
}
|
|
config = o.applyObserve(config)
|
|
}
|
|
return config
|
|
}
|
|
|
|
// Attributes returns the configured attribute set.
|
|
func (c ObserveConfig) Attributes() attribute.Set {
|
|
return c.attrs
|
|
}
|
|
|
|
// MeasurementOption applies options to all instrument measurement.
|
|
type MeasurementOption interface {
|
|
AddOption
|
|
RecordOption
|
|
ObserveOption
|
|
}
|
|
|
|
type attrOpt struct {
|
|
set attribute.Set
|
|
}
|
|
|
|
// mergeSets returns the union of keys between a and b. Any duplicate keys will
|
|
// use the value associated with b.
|
|
func mergeSets(a, b attribute.Set) attribute.Set {
|
|
// NewMergeIterator uses the first value for any duplicates.
|
|
iter := attribute.NewMergeIterator(&b, &a)
|
|
merged := make([]attribute.KeyValue, 0, a.Len()+b.Len())
|
|
for iter.Next() {
|
|
merged = append(merged, iter.Attribute())
|
|
}
|
|
return attribute.NewSet(merged...)
|
|
}
|
|
|
|
func (o attrOpt) applyAdd(c AddConfig) AddConfig {
|
|
switch {
|
|
case o.set.Len() == 0:
|
|
case c.attrs.Len() == 0:
|
|
c.attrs = o.set
|
|
default:
|
|
c.attrs = mergeSets(c.attrs, o.set)
|
|
}
|
|
return c
|
|
}
|
|
|
|
func (o attrOpt) applyRecord(c RecordConfig) RecordConfig {
|
|
switch {
|
|
case o.set.Len() == 0:
|
|
case c.attrs.Len() == 0:
|
|
c.attrs = o.set
|
|
default:
|
|
c.attrs = mergeSets(c.attrs, o.set)
|
|
}
|
|
return c
|
|
}
|
|
|
|
func (o attrOpt) applyObserve(c ObserveConfig) ObserveConfig {
|
|
switch {
|
|
case o.set.Len() == 0:
|
|
case c.attrs.Len() == 0:
|
|
c.attrs = o.set
|
|
default:
|
|
c.attrs = mergeSets(c.attrs, o.set)
|
|
}
|
|
return c
|
|
}
|
|
|
|
// WithAttributeSet sets the attribute Set associated with a measurement is
|
|
// made with.
|
|
//
|
|
// If multiple WithAttributeSet or WithAttributes options are passed the
|
|
// attributes will be merged together in the order they are passed. Attributes
|
|
// with duplicate keys will use the last value passed.
|
|
func WithAttributeSet(attributes attribute.Set) MeasurementOption {
|
|
return attrOpt{set: attributes}
|
|
}
|
|
|
|
// WithAttributes converts attributes into an attribute Set and sets the Set to
|
|
// be associated with a measurement. This is shorthand for:
|
|
//
|
|
// cp := make([]attribute.KeyValue, len(attributes))
|
|
// copy(cp, attributes)
|
|
// WithAttributeSet(attribute.NewSet(cp...))
|
|
//
|
|
// [attribute.NewSet] may modify the passed attributes so this will make a copy
|
|
// of attributes before creating a set in order to ensure this function is
|
|
// concurrent safe. This makes this option function less optimized in
|
|
// comparison to [WithAttributeSet]. Therefore, [WithAttributeSet] should be
|
|
// preferred for performance sensitive code.
|
|
//
|
|
// See [WithAttributeSet] for information about how multiple WithAttributes are
|
|
// merged.
|
|
func WithAttributes(attributes ...attribute.KeyValue) MeasurementOption {
|
|
cp := make([]attribute.KeyValue, len(attributes))
|
|
copy(cp, attributes)
|
|
return attrOpt{set: attribute.NewSet(cp...)}
|
|
}
|