From 403d92ddc09231dee6d4802fba4c9891d00d8962 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Tue, 4 Apr 2023 17:21:57 -0700 Subject: [PATCH 01/16] Add options to measurement methods --- metric/instrument/asyncfloat64.go | 5 +- metric/instrument/asyncfloat64_test.go | 3 +- metric/instrument/asyncint64.go | 5 +- metric/instrument/asyncint64_test.go | 3 +- metric/instrument/instrument.go | 210 +++++++++++++++++++++++++ metric/instrument/syncfloat64.go | 7 +- metric/instrument/syncint64.go | 7 +- metric/meter.go | 9 +- 8 files changed, 226 insertions(+), 23 deletions(-) diff --git a/metric/instrument/asyncfloat64.go b/metric/instrument/asyncfloat64.go index 356c969b6b1..b16fcebc14e 100644 --- a/metric/instrument/asyncfloat64.go +++ b/metric/instrument/asyncfloat64.go @@ -17,7 +17,6 @@ package instrument // import "go.opentelemetry.io/otel/metric/instrument" import ( "context" - "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric/embedded" ) @@ -207,8 +206,8 @@ type Float64ObservableGaugeOption interface { type Float64Observer interface { embedded.Float64Observer - // Observe records the float64 value with attributes. - Observe(value float64, attributes ...attribute.KeyValue) + // Observe records the float64 value. + Observe(value float64, opts ...Float64ObserveOption) } // Float64Callback is a function registered with a Meter that makes diff --git a/metric/instrument/asyncfloat64_test.go b/metric/instrument/asyncfloat64_test.go index 5a23c2845f7..6b8f6dd551c 100644 --- a/metric/instrument/asyncfloat64_test.go +++ b/metric/instrument/asyncfloat64_test.go @@ -21,7 +21,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric/embedded" ) @@ -89,6 +88,6 @@ type float64Observer struct { got float64 } -func (o *float64Observer) Observe(v float64, _ ...attribute.KeyValue) { +func (o *float64Observer) Observe(v float64, _ ...Float64ObserveOption) { o.got = v } diff --git a/metric/instrument/asyncint64.go b/metric/instrument/asyncint64.go index 05bfc8dbe0f..f51a9961b78 100644 --- a/metric/instrument/asyncint64.go +++ b/metric/instrument/asyncint64.go @@ -17,7 +17,6 @@ package instrument // import "go.opentelemetry.io/otel/metric/instrument" import ( "context" - "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric/embedded" ) @@ -206,8 +205,8 @@ type Int64ObservableGaugeOption interface { type Int64Observer interface { embedded.Int64Observer - // Observe records the int64 value with attributes. - Observe(value int64, attributes ...attribute.KeyValue) + // Observe records the int64 value. + Observe(value int64, opts ...Int64ObserveOption) } // Int64Callback is a function registered with a Meter that makes observations diff --git a/metric/instrument/asyncint64_test.go b/metric/instrument/asyncint64_test.go index b52f0730d5d..e4a3f682faa 100644 --- a/metric/instrument/asyncint64_test.go +++ b/metric/instrument/asyncint64_test.go @@ -21,7 +21,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric/embedded" ) @@ -89,6 +88,6 @@ type int64Observer struct { got int64 } -func (o *int64Observer) Observe(v int64, _ ...attribute.KeyValue) { +func (o *int64Observer) Observe(v int64, _ ...Int64ObserveOption) { o.got = v } diff --git a/metric/instrument/instrument.go b/metric/instrument/instrument.go index 3eaeb302767..efb6b043a2b 100644 --- a/metric/instrument/instrument.go +++ b/metric/instrument/instrument.go @@ -14,6 +14,8 @@ package instrument // import "go.opentelemetry.io/otel/metric/instrument" +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 { @@ -166,3 +168,211 @@ func (o unitOpt) applyInt64ObservableGauge(c Int64ObservableGaugeConfig) Int64Ob // WithUnit sets the instrument unit. func WithUnit(u string) Option { return unitOpt(u) } + +// Int64AddOption applies options to an addition measurement. See +// [MeasurementOption] for other options that can be used as a Int64AddOption. +type Int64AddOption interface { + applyInt64Add(Int64AddConfig) Int64AddConfig +} + +// Int64AddConfig contains options for an int64 addition measurement. +type Int64AddConfig struct { + attrs attribute.Set +} + +// NewInt64AddConfig returns a new [Int64AddConfig] with all opts applied. +func NewInt64AddConfig(opts ...Int64AddOption) Int64AddConfig { + var config Int64AddConfig + for _, o := range opts { + config = o.applyInt64Add(config) + } + return config +} + +// Attributes returns the configured attribute set. +func (c Int64AddConfig) Attributes() attribute.Set { + return c.attrs +} + +// Float64AddOption applies options to an addition measurement. See +// [MeasurementOption] for other options that can be used as a +// Float64AddOption. +type Float64AddOption interface { + applyFloat64Add(Float64AddConfig) Float64AddConfig +} + +// Float64AddConfig contains options for an float64 addition measurement. +type Float64AddConfig struct { + attrs attribute.Set +} + +// NewFloat64AddConfig returns a new [Float64AddConfig] with all opts applied. +func NewFloat64AddConfig(opts ...Float64AddOption) Float64AddConfig { + var config Float64AddConfig + for _, o := range opts { + config = o.applyFloat64Add(config) + } + return config +} + +// Attributes returns the configured attribute set. +func (c Float64AddConfig) Attributes() attribute.Set { + return c.attrs +} + +// Int64RecordOption applies options to an addition measurement. See +// [MeasurementOption] for other options that can be used as a +// Int64RecordOption. +type Int64RecordOption interface { + applyInt64Record(Int64RecordConfig) Int64RecordConfig +} + +// Int64RecordConfig contains options for an int64 recorded measurement. +type Int64RecordConfig struct { + attrs attribute.Set +} + +// NewInt64RecordConfig returns a new [Int64RecordConfig] with all opts +// applied. +func NewInt64RecordConfig(opts ...Int64RecordOption) Int64RecordConfig { + var config Int64RecordConfig + for _, o := range opts { + config = o.applyInt64Record(config) + } + return config +} + +// Attributes returns the configured attribute set. +func (c Int64RecordConfig) Attributes() attribute.Set { + return c.attrs +} + +// Float64RecordOption applies options to an addition measurement. See +// [MeasurementOption] for other options that can be used as a +// Float64RecordOption. +type Float64RecordOption interface { + applyFloat64Record(Float64RecordConfig) Float64RecordConfig +} + +// Float64RecordConfig contains options for an float64 recorded measurement. +type Float64RecordConfig struct { + attrs attribute.Set +} + +// NewFloat64RecordConfig returns a new [Float64RecordConfig] with all opts +// applied. +func NewFloat64RecordConfig(opts ...Float64RecordOption) Float64RecordConfig { + var config Float64RecordConfig + for _, o := range opts { + config = o.applyFloat64Record(config) + } + return config +} + +// Attributes returns the configured attribute set. +func (c Float64RecordConfig) Attributes() attribute.Set { + return c.attrs +} + +// Int64ObserveOption applies options to an addition measurement. See +// [MeasurementOption] for other options that can be used as a +// Int64ObserveOption. +type Int64ObserveOption interface { + applyInt64Observe(Int64ObserveConfig) Int64ObserveConfig +} + +// Int64ObserveConfig contains options for an int64 observed measurement. +type Int64ObserveConfig struct { + attrs attribute.Set +} + +// NewInt64ObserveConfig returns a new [Int64ObserveConfig] with all opts +// applied. +func NewInt64ObserveConfig(opts ...Int64ObserveOption) Int64ObserveConfig { + var config Int64ObserveConfig + for _, o := range opts { + config = o.applyInt64Observe(config) + } + return config +} + +// Attributes returns the configured attribute set. +func (c Int64ObserveConfig) Attributes() attribute.Set { + return c.attrs +} + +// Float64ObserveOption applies options to an addition measurement. See +// [MeasurementOption] for other options that can be used as a +// Float64ObserveOption. +type Float64ObserveOption interface { + applyFloat64Observe(Float64ObserveConfig) Float64ObserveConfig +} + +// Float64ObserveConfig contains options for an float64 observed measurement. +type Float64ObserveConfig struct { + attrs attribute.Set +} + +// NewFloat64ObserveConfig returns a new [Float64ObserveConfig] with all opts +// applied. +func NewFloat64ObserveConfig(opts ...Float64ObserveOption) Float64ObserveConfig { + var config Float64ObserveConfig + for _, o := range opts { + config = o.applyFloat64Observe(config) + } + return config +} + +// Attributes returns the configured attribute set. +func (c Float64ObserveConfig) Attributes() attribute.Set { + return c.attrs +} + +// MeasurementOption applies options to all instrument measurement. +type MeasurementOption interface { + Int64AddOption + Float64AddOption + Int64RecordOption + Float64RecordOption + Int64ObserveOption + Float64ObserveOption +} + +type attrOpt struct { + set attribute.Set +} + +func (o attrOpt) applyInt64Add(c Int64AddConfig) Int64AddConfig { + c.attrs = o.set + return c +} + +func (o attrOpt) applyFloat64Add(c Float64AddConfig) Float64AddConfig { + c.attrs = o.set + return c +} + +func (o attrOpt) applyInt64Record(c Int64RecordConfig) Int64RecordConfig { + c.attrs = o.set + return c +} + +func (o attrOpt) applyFloat64Record(c Float64RecordConfig) Float64RecordConfig { + c.attrs = o.set + return c +} + +func (o attrOpt) applyInt64Observe(c Int64ObserveConfig) Int64ObserveConfig { + c.attrs = o.set + return c +} + +func (o attrOpt) applyFloat64Observe(c Float64ObserveConfig) Float64ObserveConfig { + c.attrs = o.set + return c +} + +// WithAttributes sets the attributes a measurement is made with. +func WithAttributes(attributes attribute.Set) MeasurementOption { + return attrOpt{set: attributes} +} diff --git a/metric/instrument/syncfloat64.go b/metric/instrument/syncfloat64.go index 03b3bf6ac2d..d2be2c7a284 100644 --- a/metric/instrument/syncfloat64.go +++ b/metric/instrument/syncfloat64.go @@ -17,7 +17,6 @@ package instrument // import "go.opentelemetry.io/otel/metric/instrument" import ( "context" - "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric/embedded" ) @@ -31,7 +30,7 @@ type Float64Counter interface { embedded.Float64Counter // Add records a change to the counter. - Add(ctx context.Context, incr float64, attrs ...attribute.KeyValue) + Add(ctx context.Context, incr float64, opts ...Float64AddOption) } // Float64CounterConfig contains options for synchronous counter instruments that @@ -78,7 +77,7 @@ type Float64UpDownCounter interface { embedded.Float64UpDownCounter // Add records a change to the counter. - Add(ctx context.Context, incr float64, attrs ...attribute.KeyValue) + Add(ctx context.Context, incr float64, opts ...Float64AddOption) } // Float64UpDownCounterConfig contains options for synchronous counter @@ -126,7 +125,7 @@ type Float64Histogram interface { embedded.Float64Histogram // Record adds an additional value to the distribution. - Record(ctx context.Context, incr float64, attrs ...attribute.KeyValue) + Record(ctx context.Context, incr float64, opts ...Float64RecordOption) } // Float64HistogramConfig contains options for synchronous counter instruments diff --git a/metric/instrument/syncint64.go b/metric/instrument/syncint64.go index 22d0718c87c..1eeb1a26d86 100644 --- a/metric/instrument/syncint64.go +++ b/metric/instrument/syncint64.go @@ -17,7 +17,6 @@ package instrument // import "go.opentelemetry.io/otel/metric/instrument" import ( "context" - "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric/embedded" ) @@ -31,7 +30,7 @@ type Int64Counter interface { embedded.Int64Counter // Add records a change to the counter. - Add(ctx context.Context, incr int64, attrs ...attribute.KeyValue) + Add(ctx context.Context, incr int64, opts ...Int64AddOption) } // Int64CounterConfig contains options for synchronous counter instruments that @@ -78,7 +77,7 @@ type Int64UpDownCounter interface { embedded.Int64UpDownCounter // Add records a change to the counter. - Add(ctx context.Context, incr int64, attrs ...attribute.KeyValue) + Add(ctx context.Context, incr int64, opts ...Int64AddOption) } // Int64UpDownCounterConfig contains options for synchronous counter @@ -126,7 +125,7 @@ type Int64Histogram interface { embedded.Int64Histogram // Record adds an additional value to the distribution. - Record(ctx context.Context, incr int64, attrs ...attribute.KeyValue) + Record(ctx context.Context, incr int64, opts ...Int64RecordOption) } // Int64HistogramConfig contains options for synchronous counter instruments diff --git a/metric/meter.go b/metric/meter.go index 5e7ca5bea5e..12223208cd2 100644 --- a/metric/meter.go +++ b/metric/meter.go @@ -17,7 +17,6 @@ package metric // import "go.opentelemetry.io/otel/metric" import ( "context" - "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric/embedded" "go.opentelemetry.io/otel/metric/instrument" ) @@ -141,10 +140,10 @@ type Callback func(context.Context, Observer) error type Observer interface { embedded.Observer - // ObserveFloat64 records the float64 value with attributes for obsrv. - ObserveFloat64(obsrv instrument.Float64Observable, value float64, attributes ...attribute.KeyValue) - // ObserveInt64 records the int64 value with attributes for obsrv. - ObserveInt64(obsrv instrument.Int64Observable, value int64, attributes ...attribute.KeyValue) + // ObserveFloat64 records the float64 value for obsrv. + ObserveFloat64(obsrv instrument.Float64Observable, value float64, opts ...instrument.Float64ObserveOption) + // ObserveInt64 records the int64 value for obsrv. + ObserveInt64(obsrv instrument.Int64Observable, value int64, opts ...instrument.Int64ObserveOption) } // Registration is an token representing the unique registration of a callback From fa171f1e6746a41efc106a92a1dd82d82aea3aa5 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Wed, 5 Apr 2023 09:55:20 -0700 Subject: [PATCH 02/16] Update noop --- metric/noop/noop.go | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/metric/noop/noop.go b/metric/noop/noop.go index b4eaf4d6406..b786cdca1ce 100644 --- a/metric/noop/noop.go +++ b/metric/noop/noop.go @@ -26,7 +26,6 @@ package noop // import "go.opentelemetry.io/otel/metric/noop" import ( "context" - "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/metric/embedded" "go.opentelemetry.io/otel/metric/instrument" @@ -153,11 +152,11 @@ func (Meter) RegisterCallback(metric.Callback, ...instrument.Observable) (metric type Observer struct{ embedded.Observer } // ObserveFloat64 performs no operation. -func (Observer) ObserveFloat64(instrument.Float64Observable, float64, ...attribute.KeyValue) { +func (Observer) ObserveFloat64(instrument.Float64Observable, float64, ...instrument.Float64ObserveOption) { } // ObserveInt64 performs no operation. -func (Observer) ObserveInt64(instrument.Int64Observable, int64, ...attribute.KeyValue) { +func (Observer) ObserveInt64(instrument.Int64Observable, int64, ...instrument.Int64ObserveOption) { } // Registration is the registration of a Callback with a No-Op Meter. @@ -173,42 +172,42 @@ func (Registration) Unregister() error { return nil } type Int64Counter struct{ embedded.Int64Counter } // Add performs no operation. -func (Int64Counter) Add(context.Context, int64, ...attribute.KeyValue) {} +func (Int64Counter) Add(context.Context, int64, ...instrument.Int64AddOption) {} // Float64Counter is an OpenTelemetry Counter used to record float64 // measurements. It produces no telemetry. type Float64Counter struct{ embedded.Float64Counter } // Add performs no operation. -func (Float64Counter) Add(context.Context, float64, ...attribute.KeyValue) {} +func (Float64Counter) Add(context.Context, float64, ...instrument.Float64AddOption) {} // Int64UpDownCounter is an OpenTelemetry UpDownCounter used to record int64 // measurements. It produces no telemetry. type Int64UpDownCounter struct{ embedded.Int64UpDownCounter } // Add performs no operation. -func (Int64UpDownCounter) Add(context.Context, int64, ...attribute.KeyValue) {} +func (Int64UpDownCounter) Add(context.Context, int64, ...instrument.Int64AddOption) {} // Float64UpDownCounter is an OpenTelemetry UpDownCounter used to record // float64 measurements. It produces no telemetry. type Float64UpDownCounter struct{ embedded.Float64UpDownCounter } // Add performs no operation. -func (Float64UpDownCounter) Add(context.Context, float64, ...attribute.KeyValue) {} +func (Float64UpDownCounter) Add(context.Context, float64, ...instrument.Float64AddOption) {} // Int64Histogram is an OpenTelemetry Histogram used to record int64 // measurements. It produces no telemetry. type Int64Histogram struct{ embedded.Int64Histogram } // Record performs no operation. -func (Int64Histogram) Record(context.Context, int64, ...attribute.KeyValue) {} +func (Int64Histogram) Record(context.Context, int64, ...instrument.Int64RecordOption) {} // Float64Histogram is an OpenTelemetry Histogram used to record float64 // measurements. It produces no telemetry. type Float64Histogram struct{ embedded.Float64Histogram } // Record performs no operation. -func (Float64Histogram) Record(context.Context, float64, ...attribute.KeyValue) {} +func (Float64Histogram) Record(context.Context, float64, ...instrument.Float64RecordOption) {} // Int64ObservableCounter is an OpenTelemetry ObservableCounter used to record // int64 measurements. It produces no telemetry. @@ -256,11 +255,11 @@ type Float64ObservableUpDownCounter struct { type Int64Observer struct{ embedded.Int64Observer } // Observe performs no operation. -func (Int64Observer) Observe(int64, ...attribute.KeyValue) {} +func (Int64Observer) Observe(int64, ...instrument.Int64ObserveOption) {} // Float64Observer is a recorder of float64 measurements that performs no // operation. type Float64Observer struct{ embedded.Float64Observer } // Observe performs no operation. -func (Float64Observer) Observe(float64, ...attribute.KeyValue) {} +func (Float64Observer) Observe(float64, ...instrument.Float64ObserveOption) {} From 401d082ef3b2b5e70a9ff5f6cb2a7f237a3cf675 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Wed, 5 Apr 2023 10:25:39 -0700 Subject: [PATCH 03/16] Update global impl --- internal/global/instruments.go | 25 ++++++++------- internal/global/instruments_test.go | 47 ++++++++++++++++------------- internal/global/meter_types_test.go | 5 ++- 3 files changed, 40 insertions(+), 37 deletions(-) diff --git a/internal/global/instruments.go b/internal/global/instruments.go index 8a185187829..d714f2374c1 100644 --- a/internal/global/instruments.go +++ b/internal/global/instruments.go @@ -18,7 +18,6 @@ import ( "context" "sync/atomic" - "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/metric/embedded" "go.opentelemetry.io/otel/metric/instrument" @@ -224,9 +223,9 @@ func (i *sfCounter) setDelegate(m metric.Meter) { i.delegate.Store(ctr) } -func (i *sfCounter) Add(ctx context.Context, incr float64, attrs ...attribute.KeyValue) { +func (i *sfCounter) Add(ctx context.Context, incr float64, opts ...instrument.Float64AddOption) { if ctr := i.delegate.Load(); ctr != nil { - ctr.(instrument.Float64Counter).Add(ctx, incr, attrs...) + ctr.(instrument.Float64Counter).Add(ctx, incr, opts...) } } @@ -250,9 +249,9 @@ func (i *sfUpDownCounter) setDelegate(m metric.Meter) { i.delegate.Store(ctr) } -func (i *sfUpDownCounter) Add(ctx context.Context, incr float64, attrs ...attribute.KeyValue) { +func (i *sfUpDownCounter) Add(ctx context.Context, incr float64, opts ...instrument.Float64AddOption) { if ctr := i.delegate.Load(); ctr != nil { - ctr.(instrument.Float64UpDownCounter).Add(ctx, incr, attrs...) + ctr.(instrument.Float64UpDownCounter).Add(ctx, incr, opts...) } } @@ -276,9 +275,9 @@ func (i *sfHistogram) setDelegate(m metric.Meter) { i.delegate.Store(ctr) } -func (i *sfHistogram) Record(ctx context.Context, x float64, attrs ...attribute.KeyValue) { +func (i *sfHistogram) Record(ctx context.Context, x float64, opts ...instrument.Float64RecordOption) { if ctr := i.delegate.Load(); ctr != nil { - ctr.(instrument.Float64Histogram).Record(ctx, x, attrs...) + ctr.(instrument.Float64Histogram).Record(ctx, x, opts...) } } @@ -302,9 +301,9 @@ func (i *siCounter) setDelegate(m metric.Meter) { i.delegate.Store(ctr) } -func (i *siCounter) Add(ctx context.Context, x int64, attrs ...attribute.KeyValue) { +func (i *siCounter) Add(ctx context.Context, x int64, opts ...instrument.Int64AddOption) { if ctr := i.delegate.Load(); ctr != nil { - ctr.(instrument.Int64Counter).Add(ctx, x, attrs...) + ctr.(instrument.Int64Counter).Add(ctx, x, opts...) } } @@ -328,9 +327,9 @@ func (i *siUpDownCounter) setDelegate(m metric.Meter) { i.delegate.Store(ctr) } -func (i *siUpDownCounter) Add(ctx context.Context, x int64, attrs ...attribute.KeyValue) { +func (i *siUpDownCounter) Add(ctx context.Context, x int64, opts ...instrument.Int64AddOption) { if ctr := i.delegate.Load(); ctr != nil { - ctr.(instrument.Int64UpDownCounter).Add(ctx, x, attrs...) + ctr.(instrument.Int64UpDownCounter).Add(ctx, x, opts...) } } @@ -354,8 +353,8 @@ func (i *siHistogram) setDelegate(m metric.Meter) { i.delegate.Store(ctr) } -func (i *siHistogram) Record(ctx context.Context, x int64, attrs ...attribute.KeyValue) { +func (i *siHistogram) Record(ctx context.Context, x int64, opts ...instrument.Int64RecordOption) { if ctr := i.delegate.Load(); ctr != nil { - ctr.(instrument.Int64Histogram).Record(ctx, x, attrs...) + ctr.(instrument.Int64Histogram).Record(ctx, x, opts...) } } diff --git a/internal/global/instruments_test.go b/internal/global/instruments_test.go index 6b5af6715ea..358617679df 100644 --- a/internal/global/instruments_test.go +++ b/internal/global/instruments_test.go @@ -18,18 +18,17 @@ import ( "context" "testing" - "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/metric/embedded" "go.opentelemetry.io/otel/metric/instrument" "go.opentelemetry.io/otel/metric/noop" ) -func testFloat64Race(interact func(context.Context, float64, ...attribute.KeyValue), setDelegate func(metric.Meter)) { +func testFloat64Race(interact func(float64), setDelegate func(metric.Meter)) { finish := make(chan struct{}) go func() { for { - interact(context.Background(), 1) + interact(1) select { case <-finish: return @@ -42,11 +41,11 @@ func testFloat64Race(interact func(context.Context, float64, ...attribute.KeyVal close(finish) } -func testInt64Race(interact func(context.Context, int64, ...attribute.KeyValue), setDelegate func(metric.Meter)) { +func testInt64Race(interact func(int64), setDelegate func(metric.Meter)) { finish := make(chan struct{}) go func() { for { - interact(context.Background(), 1) + interact(1) select { case <-finish: return @@ -64,19 +63,19 @@ func TestAsyncInstrumentSetDelegateRace(t *testing.T) { t.Run("Float64", func(t *testing.T) { t.Run("Counter", func(t *testing.T) { delegate := &afCounter{} - f := func(context.Context, float64, ...attribute.KeyValue) { _ = delegate.Unwrap() } + f := func(float64) { _ = delegate.Unwrap() } testFloat64Race(f, delegate.setDelegate) }) t.Run("UpDownCounter", func(t *testing.T) { delegate := &afUpDownCounter{} - f := func(context.Context, float64, ...attribute.KeyValue) { _ = delegate.Unwrap() } + f := func(float64) { _ = delegate.Unwrap() } testFloat64Race(f, delegate.setDelegate) }) t.Run("Gauge", func(t *testing.T) { delegate := &afGauge{} - f := func(context.Context, float64, ...attribute.KeyValue) { _ = delegate.Unwrap() } + f := func(float64) { _ = delegate.Unwrap() } testFloat64Race(f, delegate.setDelegate) }) }) @@ -86,19 +85,19 @@ func TestAsyncInstrumentSetDelegateRace(t *testing.T) { t.Run("Int64", func(t *testing.T) { t.Run("Counter", func(t *testing.T) { delegate := &aiCounter{} - f := func(context.Context, int64, ...attribute.KeyValue) { _ = delegate.Unwrap() } + f := func(int64) { _ = delegate.Unwrap() } testInt64Race(f, delegate.setDelegate) }) t.Run("UpDownCounter", func(t *testing.T) { delegate := &aiUpDownCounter{} - f := func(context.Context, int64, ...attribute.KeyValue) { _ = delegate.Unwrap() } + f := func(int64) { _ = delegate.Unwrap() } testInt64Race(f, delegate.setDelegate) }) t.Run("Gauge", func(t *testing.T) { delegate := &aiGauge{} - f := func(context.Context, int64, ...attribute.KeyValue) { _ = delegate.Unwrap() } + f := func(int64) { _ = delegate.Unwrap() } testInt64Race(f, delegate.setDelegate) }) }) @@ -109,17 +108,20 @@ func TestSyncInstrumentSetDelegateRace(t *testing.T) { t.Run("Float64", func(t *testing.T) { t.Run("Counter", func(t *testing.T) { delegate := &sfCounter{} - testFloat64Race(delegate.Add, delegate.setDelegate) + f := func(v float64) { delegate.Add(context.Background(), v) } + testFloat64Race(f, delegate.setDelegate) }) t.Run("UpDownCounter", func(t *testing.T) { delegate := &sfUpDownCounter{} - testFloat64Race(delegate.Add, delegate.setDelegate) + f := func(v float64) { delegate.Add(context.Background(), v) } + testFloat64Race(f, delegate.setDelegate) }) t.Run("Histogram", func(t *testing.T) { delegate := &sfHistogram{} - testFloat64Race(delegate.Record, delegate.setDelegate) + f := func(v float64) { delegate.Record(context.Background(), v) } + testFloat64Race(f, delegate.setDelegate) }) }) @@ -128,17 +130,20 @@ func TestSyncInstrumentSetDelegateRace(t *testing.T) { t.Run("Int64", func(t *testing.T) { t.Run("Counter", func(t *testing.T) { delegate := &siCounter{} - testInt64Race(delegate.Add, delegate.setDelegate) + f := func(v int64) { delegate.Add(context.Background(), v) } + testInt64Race(f, delegate.setDelegate) }) t.Run("UpDownCounter", func(t *testing.T) { delegate := &siUpDownCounter{} - testInt64Race(delegate.Add, delegate.setDelegate) + f := func(v int64) { delegate.Add(context.Background(), v) } + testInt64Race(f, delegate.setDelegate) }) t.Run("Histogram", func(t *testing.T) { delegate := &siHistogram{} - testInt64Race(delegate.Record, delegate.setDelegate) + f := func(v int64) { delegate.Record(context.Background(), v) } + testInt64Race(f, delegate.setDelegate) }) }) } @@ -158,10 +163,10 @@ type testCountingFloatInstrument struct { func (i *testCountingFloatInstrument) observe() { i.count++ } -func (i *testCountingFloatInstrument) Add(context.Context, float64, ...attribute.KeyValue) { +func (i *testCountingFloatInstrument) Add(context.Context, float64, ...instrument.Float64AddOption) { i.count++ } -func (i *testCountingFloatInstrument) Record(context.Context, float64, ...attribute.KeyValue) { +func (i *testCountingFloatInstrument) Record(context.Context, float64, ...instrument.Float64RecordOption) { i.count++ } @@ -180,9 +185,9 @@ type testCountingIntInstrument struct { func (i *testCountingIntInstrument) observe() { i.count++ } -func (i *testCountingIntInstrument) Add(context.Context, int64, ...attribute.KeyValue) { +func (i *testCountingIntInstrument) Add(context.Context, int64, ...instrument.Int64AddOption) { i.count++ } -func (i *testCountingIntInstrument) Record(context.Context, int64, ...attribute.KeyValue) { +func (i *testCountingIntInstrument) Record(context.Context, int64, ...instrument.Int64RecordOption) { i.count++ } diff --git a/internal/global/meter_types_test.go b/internal/global/meter_types_test.go index 3529d92db8c..61ddf9faf8d 100644 --- a/internal/global/meter_types_test.go +++ b/internal/global/meter_types_test.go @@ -17,7 +17,6 @@ package global // import "go.opentelemetry.io/otel/internal/global" import ( "context" - "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/metric/embedded" "go.opentelemetry.io/otel/metric/instrument" @@ -157,14 +156,14 @@ type observationRecorder struct { ctx context.Context } -func (o observationRecorder) ObserveFloat64(i instrument.Float64Observable, value float64, attr ...attribute.KeyValue) { +func (o observationRecorder) ObserveFloat64(i instrument.Float64Observable, value float64, _ ...instrument.Float64ObserveOption) { iImpl, ok := i.(*testCountingFloatInstrument) if ok { iImpl.observe() } } -func (o observationRecorder) ObserveInt64(i instrument.Int64Observable, value int64, attr ...attribute.KeyValue) { +func (o observationRecorder) ObserveInt64(i instrument.Int64Observable, value int64, _ ...instrument.Int64ObserveOption) { iImpl, ok := i.(*testCountingIntInstrument) if ok { iImpl.observe() From 5439d493ca7a622fab5473589d3aef46adb93c3f Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Wed, 5 Apr 2023 11:29:13 -0700 Subject: [PATCH 04/16] Update SDK impl --- sdk/metric/benchmark_test.go | 30 +++- sdk/metric/instrument.go | 69 +++++---- sdk/metric/instrument_test.go | 8 +- .../internal/aggregator_example_test.go | 4 +- sdk/metric/meter.go | 77 +++++++--- sdk/metric/meter_test.go | 140 ++++++++---------- 6 files changed, 187 insertions(+), 141 deletions(-) diff --git a/sdk/metric/benchmark_test.go b/sdk/metric/benchmark_test.go index 9a30cd1749d..3b0ad1de135 100644 --- a/sdk/metric/benchmark_test.go +++ b/sdk/metric/benchmark_test.go @@ -43,18 +43,23 @@ func BenchmarkCounterAddNoAttrs(b *testing.B) { } func BenchmarkCounterAddOneAttr(b *testing.B) { + s := attribute.NewSet(attribute.String("K", "V")) ctx, _, cntr := benchCounter(b) for i := 0; i < b.N; i++ { - cntr.Add(ctx, 1, attribute.String("K", "V")) + cntr.Add(ctx, 1, instrument.WithAttributes(s)) } } func BenchmarkCounterAddOneInvalidAttr(b *testing.B) { + s := attribute.NewSet( + attribute.String("", "V"), + attribute.String("K", "V"), + ) ctx, _, cntr := benchCounter(b) for i := 0; i < b.N; i++ { - cntr.Add(ctx, 1, attribute.String("", "V"), attribute.String("K", "V")) + cntr.Add(ctx, 1, instrument.WithAttributes(s)) } } @@ -62,7 +67,8 @@ func BenchmarkCounterAddSingleUseAttrs(b *testing.B) { ctx, _, cntr := benchCounter(b) for i := 0; i < b.N; i++ { - cntr.Add(ctx, 1, attribute.Int("K", i)) + s := attribute.NewSet(attribute.Int("K", i)) + cntr.Add(ctx, 1, instrument.WithAttributes(s)) } } @@ -70,7 +76,11 @@ func BenchmarkCounterAddSingleUseInvalidAttrs(b *testing.B) { ctx, _, cntr := benchCounter(b) for i := 0; i < b.N; i++ { - cntr.Add(ctx, 1, attribute.Int("", i), attribute.Int("K", i)) + s := attribute.NewSet( + attribute.Int("", i), + attribute.Int("K", i), + ) + cntr.Add(ctx, 1, instrument.WithAttributes(s)) } } @@ -83,15 +93,20 @@ func BenchmarkCounterAddSingleUseFilteredAttrs(b *testing.B) { )) for i := 0; i < b.N; i++ { - cntr.Add(ctx, 1, attribute.Int("L", i), attribute.Int("K", i)) + s := attribute.NewSet( + attribute.Int("L", i), + attribute.Int("K", i), + ) + cntr.Add(ctx, 1, instrument.WithAttributes(s)) } } func BenchmarkCounterCollectOneAttr(b *testing.B) { + s := attribute.NewSet(attribute.Int("K", 1)) ctx, rdr, cntr := benchCounter(b) for i := 0; i < b.N; i++ { - cntr.Add(ctx, 1, attribute.Int("K", 1)) + cntr.Add(ctx, 1, instrument.WithAttributes(s)) _ = rdr.Collect(ctx, nil) } @@ -102,7 +117,8 @@ func BenchmarkCounterCollectTenAttrs(b *testing.B) { for i := 0; i < b.N; i++ { for j := 0; j < 10; j++ { - cntr.Add(ctx, 1, attribute.Int("K", j)) + s := attribute.NewSet(attribute.Int("K", j)) + cntr.Add(ctx, 1, instrument.WithAttributes(s)) } _ = rdr.Collect(ctx, nil) } diff --git a/sdk/metric/instrument.go b/sdk/metric/instrument.go index 9e8de50cffe..eb90984d31d 100644 --- a/sdk/metric/instrument.go +++ b/sdk/metric/instrument.go @@ -170,40 +170,63 @@ type streamID struct { Number string } -type instrumentImpl[N int64 | float64] struct { - aggregators []internal.Aggregator[N] +type int64Inst struct { + aggregators []internal.Aggregator[int64] - embedded.Float64Counter - embedded.Float64UpDownCounter - embedded.Float64Histogram embedded.Int64Counter embedded.Int64UpDownCounter embedded.Int64Histogram } -var _ instrument.Float64Counter = (*instrumentImpl[float64])(nil) -var _ instrument.Float64UpDownCounter = (*instrumentImpl[float64])(nil) -var _ instrument.Float64Histogram = (*instrumentImpl[float64])(nil) -var _ instrument.Int64Counter = (*instrumentImpl[int64])(nil) -var _ instrument.Int64UpDownCounter = (*instrumentImpl[int64])(nil) -var _ instrument.Int64Histogram = (*instrumentImpl[int64])(nil) +var _ instrument.Int64Counter = (*int64Inst)(nil) +var _ instrument.Int64UpDownCounter = (*int64Inst)(nil) +var _ instrument.Int64Histogram = (*int64Inst)(nil) + +func (i *int64Inst) Add(ctx context.Context, val int64, opts ...instrument.Int64AddOption) { + c := instrument.NewInt64AddConfig(opts...) + i.aggregate(ctx, val, c.Attributes()) +} + +func (i *int64Inst) Record(ctx context.Context, val int64, opts ...instrument.Int64RecordOption) { + c := instrument.NewInt64RecordConfig(opts...) + i.aggregate(ctx, val, c.Attributes()) +} + +func (i *int64Inst) aggregate(ctx context.Context, val int64, s attribute.Set) { + if err := ctx.Err(); err != nil { + return + } + for _, agg := range i.aggregators { + agg.Aggregate(val, s) + } +} + +type float64Inst struct { + aggregators []internal.Aggregator[float64] + + embedded.Float64Counter + embedded.Float64UpDownCounter + embedded.Float64Histogram +} + +var _ instrument.Float64Counter = (*float64Inst)(nil) +var _ instrument.Float64UpDownCounter = (*float64Inst)(nil) +var _ instrument.Float64Histogram = (*float64Inst)(nil) -func (i *instrumentImpl[N]) Add(ctx context.Context, val N, attrs ...attribute.KeyValue) { - i.aggregate(ctx, val, attrs) +func (i *float64Inst) Add(ctx context.Context, val float64, opts ...instrument.Float64AddOption) { + c := instrument.NewFloat64AddConfig(opts...) + i.aggregate(ctx, val, c.Attributes()) } -func (i *instrumentImpl[N]) Record(ctx context.Context, val N, attrs ...attribute.KeyValue) { - i.aggregate(ctx, val, attrs) +func (i *float64Inst) Record(ctx context.Context, val float64, opts ...instrument.Float64RecordOption) { + c := instrument.NewFloat64RecordConfig(opts...) + i.aggregate(ctx, val, c.Attributes()) } -func (i *instrumentImpl[N]) aggregate(ctx context.Context, val N, attrs []attribute.KeyValue) { +func (i *float64Inst) aggregate(ctx context.Context, val float64, s attribute.Set) { if err := ctx.Err(); err != nil { return } - // Do not use single attribute.Sortable and attribute.NewSetWithSortable, - // this method needs to be concurrent safe. Let the sync.Pool in the - // attribute package handle allocations of the Sortable. - s := attribute.NewSet(attrs...) for _, agg := range i.aggregators { agg.Aggregate(val, s) } @@ -277,11 +300,7 @@ func newObservable[N int64 | float64](scope instrumentation.Scope, kind Instrume } // observe records the val for the set of attrs. -func (o *observable[N]) observe(val N, attrs []attribute.KeyValue) { - // Do not use single attribute.Sortable and attribute.NewSetWithSortable, - // this method needs to be concurrent safe. Let the sync.Pool in the - // attribute package handle allocations of the Sortable. - s := attribute.NewSet(attrs...) +func (o *observable[N]) observe(val N, s attribute.Set) { for _, agg := range o.aggregators { agg.Aggregate(val, s) } diff --git a/sdk/metric/instrument_test.go b/sdk/metric/instrument_test.go index 4315effbfd0..0a8f5924473 100644 --- a/sdk/metric/instrument_test.go +++ b/sdk/metric/instrument_test.go @@ -23,16 +23,16 @@ import ( ) func BenchmarkInstrument(b *testing.B) { - attr := func(id int) []attribute.KeyValue { - return []attribute.KeyValue{ + attr := func(id int) attribute.Set { + return attribute.NewSet( attribute.String("user", "Alice"), attribute.Bool("admin", true), attribute.Int("id", id), - } + ) } b.Run("instrumentImpl/aggregate", func(b *testing.B) { - inst := instrumentImpl[int64]{aggregators: []internal.Aggregator[int64]{ + inst := int64Inst{aggregators: []internal.Aggregator[int64]{ internal.NewLastValue[int64](), internal.NewCumulativeSum[int64](true), internal.NewDeltaSum[int64](true), diff --git a/sdk/metric/internal/aggregator_example_test.go b/sdk/metric/internal/aggregator_example_test.go index 297d0f5118e..952dd5c6309 100644 --- a/sdk/metric/internal/aggregator_example_test.go +++ b/sdk/metric/internal/aggregator_example_test.go @@ -94,8 +94,8 @@ type inst struct { embedded.Int64Histogram } -func (inst) Add(context.Context, int64, ...attribute.KeyValue) {} -func (inst) Record(context.Context, int64, ...attribute.KeyValue) {} +func (inst) Add(context.Context, int64, ...instrument.Int64AddOption) {} +func (inst) Record(context.Context, int64, ...instrument.Int64RecordOption) {} func Example() { m := meter{} diff --git a/sdk/metric/meter.go b/sdk/metric/meter.go index 72b37ea6634..1f656a73cf2 100644 --- a/sdk/metric/meter.go +++ b/sdk/metric/meter.go @@ -19,7 +19,6 @@ import ( "errors" "fmt" - "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/internal/global" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/metric/embedded" @@ -38,8 +37,8 @@ type meter struct { scope instrumentation.Scope pipes pipelines - int64IP *instProvider[int64] - float64IP *instProvider[float64] + int64IP *int64InstProvider + float64IP *float64InstProvider } func newMeter(s instrumentation.Scope, p pipelines) *meter { @@ -50,8 +49,8 @@ func newMeter(s instrumentation.Scope, p pipelines) *meter { return &meter{ scope: s, pipes: p, - int64IP: newInstProvider[int64](s, p, &viewCache), - float64IP: newInstProvider[float64](s, p, &viewCache), + int64IP: newInt64InstProvider(s, p, &viewCache), + float64IP: newFloat64InstProvider(s, p, &viewCache), } } @@ -297,7 +296,7 @@ var ( errUnregObserver = errors.New("observable instrument not registered for callback") ) -func (r observer) ObserveFloat64(o instrument.Float64Observable, v float64, a ...attribute.KeyValue) { +func (r observer) ObserveFloat64(o instrument.Float64Observable, v float64, opts ...instrument.Float64ObserveOption) { var oImpl float64Observable switch conv := o.(type) { case float64Observable: @@ -326,10 +325,11 @@ func (r observer) ObserveFloat64(o instrument.Float64Observable, v float64, a .. ) return } - oImpl.observe(v, a) + c := instrument.NewFloat64ObserveConfig(opts...) + oImpl.observe(v, c.Attributes()) } -func (r observer) ObserveInt64(o instrument.Int64Observable, v int64, a ...attribute.KeyValue) { +func (r observer) ObserveInt64(o instrument.Int64Observable, v int64, opts ...instrument.Int64ObserveOption) { var oImpl int64Observable switch conv := o.(type) { case int64Observable: @@ -358,7 +358,8 @@ func (r observer) ObserveInt64(o instrument.Int64Observable, v int64, a ...attri ) return } - oImpl.observe(v, a) + c := instrument.NewInt64ObserveConfig(opts...) + oImpl.observe(v, c.Attributes()) } type noopRegister struct{ embedded.Registration } @@ -367,18 +368,18 @@ func (noopRegister) Unregister() error { return nil } -// instProvider provides all OpenTelemetry instruments. -type instProvider[N int64 | float64] struct { +// int64InstProvider provides int64 OpenTelemetry instruments. +type int64InstProvider struct { scope instrumentation.Scope pipes pipelines - resolve resolver[N] + resolve resolver[int64] } -func newInstProvider[N int64 | float64](s instrumentation.Scope, p pipelines, c *cache[string, streamID]) *instProvider[N] { - return &instProvider[N]{scope: s, pipes: p, resolve: newResolver[N](p, c)} +func newInt64InstProvider(s instrumentation.Scope, p pipelines, c *cache[string, streamID]) *int64InstProvider { + return &int64InstProvider{scope: s, pipes: p, resolve: newResolver[int64](p, c)} } -func (p *instProvider[N]) aggs(kind InstrumentKind, name, desc, u string) ([]internal.Aggregator[N], error) { +func (p *int64InstProvider) aggs(kind InstrumentKind, name, desc, u string) ([]internal.Aggregator[int64], error) { inst := Instrument{ Name: name, Description: desc, @@ -390,12 +391,40 @@ func (p *instProvider[N]) aggs(kind InstrumentKind, name, desc, u string) ([]int } // lookup returns the resolved instrumentImpl. -func (p *instProvider[N]) lookup(kind InstrumentKind, name, desc, u string) (*instrumentImpl[N], error) { +func (p *int64InstProvider) lookup(kind InstrumentKind, name, desc, u string) (*int64Inst, error) { aggs, err := p.aggs(kind, name, desc, u) - return &instrumentImpl[N]{aggregators: aggs}, err + return &int64Inst{aggregators: aggs}, err } -type int64ObservProvider struct{ *instProvider[int64] } +// float64InstProvider provides float64 OpenTelemetry instruments. +type float64InstProvider struct { + scope instrumentation.Scope + pipes pipelines + resolve resolver[float64] +} + +func newFloat64InstProvider(s instrumentation.Scope, p pipelines, c *cache[string, streamID]) *float64InstProvider { + return &float64InstProvider{scope: s, pipes: p, resolve: newResolver[float64](p, c)} +} + +func (p *float64InstProvider) aggs(kind InstrumentKind, name, desc, u string) ([]internal.Aggregator[float64], error) { + inst := Instrument{ + Name: name, + Description: desc, + Unit: u, + Kind: kind, + Scope: p.scope, + } + return p.resolve.Aggregators(inst) +} + +// lookup returns the resolved instrumentImpl. +func (p *float64InstProvider) lookup(kind InstrumentKind, name, desc, u string) (*float64Inst, error) { + aggs, err := p.aggs(kind, name, desc, u) + return &float64Inst{aggregators: aggs}, err +} + +type int64ObservProvider struct{ *int64InstProvider } func (p int64ObservProvider) lookup(kind InstrumentKind, name, desc, u string) (int64Observable, error) { aggs, err := p.aggs(kind, name, desc, u) @@ -423,11 +452,12 @@ type int64Observer struct { int64Observable } -func (o int64Observer) Observe(val int64, attrs ...attribute.KeyValue) { - o.observe(val, attrs) +func (o int64Observer) Observe(val int64, opts ...instrument.Int64ObserveOption) { + c := instrument.NewInt64ObserveConfig(opts...) + o.observe(val, c.Attributes()) } -type float64ObservProvider struct{ *instProvider[float64] } +type float64ObservProvider struct{ *float64InstProvider } func (p float64ObservProvider) lookup(kind InstrumentKind, name, desc, u string) (float64Observable, error) { aggs, err := p.aggs(kind, name, desc, u) @@ -455,6 +485,7 @@ type float64Observer struct { float64Observable } -func (o float64Observer) Observe(val float64, attrs ...attribute.KeyValue) { - o.observe(val, attrs) +func (o float64Observer) Observe(val float64, opts ...instrument.Float64ObserveOption) { + c := instrument.NewFloat64ObserveConfig(opts...) + o.observe(val, c.Attributes()) } diff --git a/sdk/metric/meter_test.go b/sdk/metric/meter_test.go index ef8c579d534..d0b965832c7 100644 --- a/sdk/metric/meter_test.go +++ b/sdk/metric/meter_test.go @@ -168,7 +168,8 @@ func TestCallbackUnregisterConcurrency(t *testing.T) { // Instruments should produce correct ResourceMetrics. func TestMeterCreatesInstruments(t *testing.T) { - attrs := []attribute.KeyValue{attribute.String("name", "alice")} + attrs := attribute.NewSet(attribute.String("name", "alice")) + opt := instrument.WithAttributes(attrs) testCases := []struct { name string fn func(*testing.T, metric.Meter) @@ -178,7 +179,7 @@ func TestMeterCreatesInstruments(t *testing.T) { name: "ObservableInt64Count", fn: func(t *testing.T, m metric.Meter) { cback := func(_ context.Context, o instrument.Int64Observer) error { - o.Observe(4, attrs...) + o.Observe(4, opt) return nil } ctr, err := m.Int64ObservableCounter("aint", instrument.WithInt64Callback(cback)) @@ -195,7 +196,7 @@ func TestMeterCreatesInstruments(t *testing.T) { Temporality: metricdata.CumulativeTemporality, IsMonotonic: true, DataPoints: []metricdata.DataPoint[int64]{ - {Attributes: attribute.NewSet(attrs...), Value: 4}, + {Attributes: attrs, Value: 4}, {Value: 3}, }, }, @@ -205,7 +206,7 @@ func TestMeterCreatesInstruments(t *testing.T) { name: "ObservableInt64UpDownCount", fn: func(t *testing.T, m metric.Meter) { cback := func(_ context.Context, o instrument.Int64Observer) error { - o.Observe(4, attrs...) + o.Observe(4, opt) return nil } ctr, err := m.Int64ObservableUpDownCounter("aint", instrument.WithInt64Callback(cback)) @@ -222,7 +223,7 @@ func TestMeterCreatesInstruments(t *testing.T) { Temporality: metricdata.CumulativeTemporality, IsMonotonic: false, DataPoints: []metricdata.DataPoint[int64]{ - {Attributes: attribute.NewSet(attrs...), Value: 4}, + {Attributes: attrs, Value: 4}, {Value: 11}, }, }, @@ -232,7 +233,7 @@ func TestMeterCreatesInstruments(t *testing.T) { name: "ObservableInt64Gauge", fn: func(t *testing.T, m metric.Meter) { cback := func(_ context.Context, o instrument.Int64Observer) error { - o.Observe(4, attrs...) + o.Observe(4, opt) return nil } gauge, err := m.Int64ObservableGauge("agauge", instrument.WithInt64Callback(cback)) @@ -247,7 +248,7 @@ func TestMeterCreatesInstruments(t *testing.T) { Name: "agauge", Data: metricdata.Gauge[int64]{ DataPoints: []metricdata.DataPoint[int64]{ - {Attributes: attribute.NewSet(attrs...), Value: 4}, + {Attributes: attrs, Value: 4}, {Value: 11}, }, }, @@ -257,7 +258,7 @@ func TestMeterCreatesInstruments(t *testing.T) { name: "ObservableFloat64Count", fn: func(t *testing.T, m metric.Meter) { cback := func(_ context.Context, o instrument.Float64Observer) error { - o.Observe(4, attrs...) + o.Observe(4, opt) return nil } ctr, err := m.Float64ObservableCounter("afloat", instrument.WithFloat64Callback(cback)) @@ -274,7 +275,7 @@ func TestMeterCreatesInstruments(t *testing.T) { Temporality: metricdata.CumulativeTemporality, IsMonotonic: true, DataPoints: []metricdata.DataPoint[float64]{ - {Attributes: attribute.NewSet(attrs...), Value: 4}, + {Attributes: attrs, Value: 4}, {Value: 3}, }, }, @@ -284,7 +285,7 @@ func TestMeterCreatesInstruments(t *testing.T) { name: "ObservableFloat64UpDownCount", fn: func(t *testing.T, m metric.Meter) { cback := func(_ context.Context, o instrument.Float64Observer) error { - o.Observe(4, attrs...) + o.Observe(4, opt) return nil } ctr, err := m.Float64ObservableUpDownCounter("afloat", instrument.WithFloat64Callback(cback)) @@ -301,7 +302,7 @@ func TestMeterCreatesInstruments(t *testing.T) { Temporality: metricdata.CumulativeTemporality, IsMonotonic: false, DataPoints: []metricdata.DataPoint[float64]{ - {Attributes: attribute.NewSet(attrs...), Value: 4}, + {Attributes: attrs, Value: 4}, {Value: 11}, }, }, @@ -311,7 +312,7 @@ func TestMeterCreatesInstruments(t *testing.T) { name: "ObservableFloat64Gauge", fn: func(t *testing.T, m metric.Meter) { cback := func(_ context.Context, o instrument.Float64Observer) error { - o.Observe(4, attrs...) + o.Observe(4, opt) return nil } gauge, err := m.Float64ObservableGauge("agauge", instrument.WithFloat64Callback(cback)) @@ -326,7 +327,7 @@ func TestMeterCreatesInstruments(t *testing.T) { Name: "agauge", Data: metricdata.Gauge[float64]{ DataPoints: []metricdata.DataPoint[float64]{ - {Attributes: attribute.NewSet(attrs...), Value: 4}, + {Attributes: attrs, Value: 4}, {Value: 11}, }, }, @@ -884,6 +885,12 @@ func TestAttributeFilter(t *testing.T) { } func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) { + fooBar := attribute.NewSet(attribute.String("foo", "bar")) + withFooBar := instrument.WithAttributes(fooBar) + v1 := attribute.NewSet(attribute.String("foo", "bar"), attribute.Int("version", 1)) + withV1 := instrument.WithAttributes(v1) + v2 := attribute.NewSet(attribute.String("foo", "bar"), attribute.Int("version", 2)) + withV2 := instrument.WithAttributes(v2) testcases := []struct { name string register func(t *testing.T, mtr metric.Meter) error @@ -897,9 +904,9 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) { return err } _, err = mtr.RegisterCallback(func(_ context.Context, o metric.Observer) error { - o.ObserveFloat64(ctr, 1.0, attribute.String("foo", "bar"), attribute.Int("version", 1)) - o.ObserveFloat64(ctr, 2.0, attribute.String("foo", "bar")) - o.ObserveFloat64(ctr, 1.0, attribute.String("foo", "bar"), attribute.Int("version", 2)) + o.ObserveFloat64(ctr, 1.0, withV1) + o.ObserveFloat64(ctr, 2.0, withFooBar) + o.ObserveFloat64(ctr, 1.0, withV2) return nil }, ctr) return err @@ -908,10 +915,7 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) { Name: "afcounter", Data: metricdata.Sum[float64]{ DataPoints: []metricdata.DataPoint[float64]{ - { - Attributes: attribute.NewSet(attribute.String("foo", "bar")), - Value: 4.0, - }, + {Attributes: fooBar, Value: 4.0}, }, Temporality: temporality, IsMonotonic: true, @@ -926,9 +930,9 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) { return err } _, err = mtr.RegisterCallback(func(_ context.Context, o metric.Observer) error { - o.ObserveFloat64(ctr, 1.0, attribute.String("foo", "bar"), attribute.Int("version", 1)) - o.ObserveFloat64(ctr, 2.0, attribute.String("foo", "bar")) - o.ObserveFloat64(ctr, 1.0, attribute.String("foo", "bar"), attribute.Int("version", 2)) + o.ObserveFloat64(ctr, 1.0, withV1) + o.ObserveFloat64(ctr, 2.0, withFooBar) + o.ObserveFloat64(ctr, 1.0, withV2) return nil }, ctr) return err @@ -955,8 +959,8 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) { return err } _, err = mtr.RegisterCallback(func(_ context.Context, o metric.Observer) error { - o.ObserveFloat64(ctr, 1.0, attribute.String("foo", "bar"), attribute.Int("version", 1)) - o.ObserveFloat64(ctr, 2.0, attribute.String("foo", "bar"), attribute.Int("version", 2)) + o.ObserveFloat64(ctr, 1.0, withV1) + o.ObserveFloat64(ctr, 2.0, withV2) return nil }, ctr) return err @@ -965,10 +969,7 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) { Name: "afgauge", Data: metricdata.Gauge[float64]{ DataPoints: []metricdata.DataPoint[float64]{ - { - Attributes: attribute.NewSet(attribute.String("foo", "bar")), - Value: 2.0, - }, + {Attributes: fooBar, Value: 2.0}, }, }, }, @@ -981,9 +982,9 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) { return err } _, err = mtr.RegisterCallback(func(_ context.Context, o metric.Observer) error { - o.ObserveInt64(ctr, 10, attribute.String("foo", "bar"), attribute.Int("version", 1)) - o.ObserveInt64(ctr, 20, attribute.String("foo", "bar")) - o.ObserveInt64(ctr, 10, attribute.String("foo", "bar"), attribute.Int("version", 2)) + o.ObserveInt64(ctr, 10, withV1) + o.ObserveInt64(ctr, 20, withFooBar) + o.ObserveInt64(ctr, 10, withV2) return nil }, ctr) return err @@ -992,10 +993,7 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) { Name: "aicounter", Data: metricdata.Sum[int64]{ DataPoints: []metricdata.DataPoint[int64]{ - { - Attributes: attribute.NewSet(attribute.String("foo", "bar")), - Value: 40, - }, + {Attributes: fooBar, Value: 40}, }, Temporality: temporality, IsMonotonic: true, @@ -1010,9 +1008,9 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) { return err } _, err = mtr.RegisterCallback(func(_ context.Context, o metric.Observer) error { - o.ObserveInt64(ctr, 10, attribute.String("foo", "bar"), attribute.Int("version", 1)) - o.ObserveInt64(ctr, 20, attribute.String("foo", "bar")) - o.ObserveInt64(ctr, 10, attribute.String("foo", "bar"), attribute.Int("version", 2)) + o.ObserveInt64(ctr, 10, withV1) + o.ObserveInt64(ctr, 20, withFooBar) + o.ObserveInt64(ctr, 10, withV2) return nil }, ctr) return err @@ -1021,10 +1019,7 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) { Name: "aiupdowncounter", Data: metricdata.Sum[int64]{ DataPoints: []metricdata.DataPoint[int64]{ - { - Attributes: attribute.NewSet(attribute.String("foo", "bar")), - Value: 40, - }, + {Attributes: fooBar, Value: 40}, }, Temporality: temporality, IsMonotonic: false, @@ -1039,8 +1034,8 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) { return err } _, err = mtr.RegisterCallback(func(_ context.Context, o metric.Observer) error { - o.ObserveInt64(ctr, 10, attribute.String("foo", "bar"), attribute.Int("version", 1)) - o.ObserveInt64(ctr, 20, attribute.String("foo", "bar"), attribute.Int("version", 2)) + o.ObserveInt64(ctr, 10, withV1) + o.ObserveInt64(ctr, 20, withV2) return nil }, ctr) return err @@ -1049,10 +1044,7 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) { Name: "aigauge", Data: metricdata.Gauge[int64]{ DataPoints: []metricdata.DataPoint[int64]{ - { - Attributes: attribute.NewSet(attribute.String("foo", "bar")), - Value: 20, - }, + {Attributes: fooBar, Value: 20}, }, }, }, @@ -1065,18 +1057,15 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) { return err } - ctr.Add(context.Background(), 1.0, attribute.String("foo", "bar"), attribute.Int("version", 1)) - ctr.Add(context.Background(), 2.0, attribute.String("foo", "bar"), attribute.Int("version", 2)) + ctr.Add(context.Background(), 1.0, withV1) + ctr.Add(context.Background(), 2.0, withV2) return nil }, wantMetric: metricdata.Metrics{ Name: "sfcounter", Data: metricdata.Sum[float64]{ DataPoints: []metricdata.DataPoint[float64]{ - { - Attributes: attribute.NewSet(attribute.String("foo", "bar")), - Value: 3.0, - }, + {Attributes: fooBar, Value: 3.0}, }, Temporality: temporality, IsMonotonic: true, @@ -1091,18 +1080,15 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) { return err } - ctr.Add(context.Background(), 1.0, attribute.String("foo", "bar"), attribute.Int("version", 1)) - ctr.Add(context.Background(), 2.0, attribute.String("foo", "bar"), attribute.Int("version", 2)) + ctr.Add(context.Background(), 1.0, withV1) + ctr.Add(context.Background(), 2.0, withV2) return nil }, wantMetric: metricdata.Metrics{ Name: "sfupdowncounter", Data: metricdata.Sum[float64]{ DataPoints: []metricdata.DataPoint[float64]{ - { - Attributes: attribute.NewSet(attribute.String("foo", "bar")), - Value: 3.0, - }, + {Attributes: fooBar, Value: 3.0}, }, Temporality: temporality, IsMonotonic: false, @@ -1117,8 +1103,8 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) { return err } - ctr.Record(context.Background(), 1.0, attribute.String("foo", "bar"), attribute.Int("version", 1)) - ctr.Record(context.Background(), 2.0, attribute.String("foo", "bar"), attribute.Int("version", 2)) + ctr.Record(context.Background(), 1.0, withV1) + ctr.Record(context.Background(), 2.0, withV2) return nil }, wantMetric: metricdata.Metrics{ @@ -1126,7 +1112,7 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) { Data: metricdata.Histogram[float64]{ DataPoints: []metricdata.HistogramDataPoint[float64]{ { - Attributes: attribute.NewSet(attribute.String("foo", "bar")), + Attributes: fooBar, Bounds: []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000}, BucketCounts: []uint64{0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, Count: 2, @@ -1147,18 +1133,15 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) { return err } - ctr.Add(context.Background(), 10, attribute.String("foo", "bar"), attribute.Int("version", 1)) - ctr.Add(context.Background(), 20, attribute.String("foo", "bar"), attribute.Int("version", 2)) + ctr.Add(context.Background(), 10, withV1) + ctr.Add(context.Background(), 20, withV2) return nil }, wantMetric: metricdata.Metrics{ Name: "sicounter", Data: metricdata.Sum[int64]{ DataPoints: []metricdata.DataPoint[int64]{ - { - Attributes: attribute.NewSet(attribute.String("foo", "bar")), - Value: 30, - }, + {Attributes: fooBar, Value: 30}, }, Temporality: temporality, IsMonotonic: true, @@ -1173,18 +1156,15 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) { return err } - ctr.Add(context.Background(), 10, attribute.String("foo", "bar"), attribute.Int("version", 1)) - ctr.Add(context.Background(), 20, attribute.String("foo", "bar"), attribute.Int("version", 2)) + ctr.Add(context.Background(), 10, withV1) + ctr.Add(context.Background(), 20, withV2) return nil }, wantMetric: metricdata.Metrics{ Name: "siupdowncounter", Data: metricdata.Sum[int64]{ DataPoints: []metricdata.DataPoint[int64]{ - { - Attributes: attribute.NewSet(attribute.String("foo", "bar")), - Value: 30, - }, + {Attributes: fooBar, Value: 30}, }, Temporality: temporality, IsMonotonic: false, @@ -1199,8 +1179,8 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) { return err } - ctr.Record(context.Background(), 1, attribute.String("foo", "bar"), attribute.Int("version", 1)) - ctr.Record(context.Background(), 2, attribute.String("foo", "bar"), attribute.Int("version", 2)) + ctr.Record(context.Background(), 1, withV1) + ctr.Record(context.Background(), 2, withV2) return nil }, wantMetric: metricdata.Metrics{ @@ -1208,7 +1188,7 @@ func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) { Data: metricdata.Histogram[int64]{ DataPoints: []metricdata.HistogramDataPoint[int64]{ { - Attributes: attribute.NewSet(attribute.String("foo", "bar")), + Attributes: fooBar, Bounds: []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000}, BucketCounts: []uint64{0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, Count: 2, @@ -1295,7 +1275,7 @@ func TestObservableExample(t *testing.T) { _, err := meter.Int64ObservableCounter(instName, instrument.WithInt64Callback( func(_ context.Context, o instrument.Int64Observer) error { for attrSet, val := range observations { - o.Observe(val, attrSet.ToSlice()...) + o.Observe(val, instrument.WithAttributes(attrSet)) } return nil }, From 37322abf8e46e54272a8ccf73214781bdfa68f28 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Wed, 5 Apr 2023 11:42:24 -0700 Subject: [PATCH 05/16] Fix metric API example --- metric/example_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/metric/example_test.go b/metric/example_test.go index c909410e9e4..41d835ec5b4 100644 --- a/metric/example_test.go +++ b/metric/example_test.go @@ -63,7 +63,8 @@ func ExampleMeter_asynchronous_single() { // // For demonstration purpose, a static value is used here. usage := 75000 - obsrv.Observe(int64(usage), attribute.Int("disk.id", 3)) + s := attribute.NewSet(attribute.Int("disk.id", 3)) + obsrv.Observe(int64(usage), instrument.WithAttributes(s)) return nil }), ) From afb5ec5b3a1d36f9240ef4b054dfb0a585c658a5 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Wed, 5 Apr 2023 11:42:35 -0700 Subject: [PATCH 06/16] Update prometheus exporter tests --- exporters/prometheus/exporter_test.go | 172 ++++++++++++++------------ 1 file changed, 95 insertions(+), 77 deletions(-) diff --git a/exporters/prometheus/exporter_test.go b/exporters/prometheus/exporter_test.go index a790b783bd8..4ec683c1cf1 100644 --- a/exporters/prometheus/exporter_test.go +++ b/exporters/prometheus/exporter_test.go @@ -46,67 +46,70 @@ func TestPrometheusExporter(t *testing.T) { name: "counter", expectedFile: "testdata/counter.txt", recordMetrics: func(ctx context.Context, meter otelmetric.Meter) { - attrs := []attribute.KeyValue{ + attrs := attribute.NewSet( attribute.Key("A").String("B"), attribute.Key("C").String("D"), attribute.Key("E").Bool(true), attribute.Key("F").Int(42), - } + ) + opt := instrument.WithAttributes(attrs) counter, err := meter.Float64Counter( "foo", instrument.WithDescription("a simple counter"), instrument.WithUnit("ms"), ) require.NoError(t, err) - counter.Add(ctx, 5, attrs...) - counter.Add(ctx, 10.3, attrs...) - counter.Add(ctx, 9, attrs...) + counter.Add(ctx, 5, opt) + counter.Add(ctx, 10.3, opt) + counter.Add(ctx, 9, opt) - attrs2 := []attribute.KeyValue{ + attrs2 := attribute.NewSet( attribute.Key("A").String("D"), attribute.Key("C").String("B"), attribute.Key("E").Bool(true), attribute.Key("F").Int(42), - } - counter.Add(ctx, 5, attrs2...) + ) + counter.Add(ctx, 5, instrument.WithAttributes(attrs2)) }, }, { name: "gauge", expectedFile: "testdata/gauge.txt", recordMetrics: func(ctx context.Context, meter otelmetric.Meter) { - attrs := []attribute.KeyValue{ + attrs := attribute.NewSet( attribute.Key("A").String("B"), attribute.Key("C").String("D"), - } + ) + opt := instrument.WithAttributes(attrs) gauge, err := meter.Float64UpDownCounter( "bar", instrument.WithDescription("a fun little gauge"), instrument.WithUnit("1"), ) require.NoError(t, err) - gauge.Add(ctx, 1.0, attrs...) - gauge.Add(ctx, -.25, attrs...) + gauge.Add(ctx, 1.0, opt) + gauge.Add(ctx, -.25, opt) }, }, { name: "histogram", expectedFile: "testdata/histogram.txt", recordMetrics: func(ctx context.Context, meter otelmetric.Meter) { - attrs := []attribute.KeyValue{ + attrs := attribute.NewSet( attribute.Key("A").String("B"), attribute.Key("C").String("D"), - } + ) + opt := instrument.WithAttributes(attrs) histogram, err := meter.Float64Histogram( "histogram_baz", instrument.WithDescription("a very nice histogram"), instrument.WithUnit("By"), ) require.NoError(t, err) - histogram.Record(ctx, 23, attrs...) - histogram.Record(ctx, 7, attrs...) - histogram.Record(ctx, 101, attrs...) - histogram.Record(ctx, 105, attrs...) + histogram.Record(ctx, 23, opt) + histogram.Record(ctx, 7, opt) + histogram.Record(ctx, 101, opt) + histogram.Record(ctx, 105, opt) }, }, { @@ -114,7 +117,7 @@ func TestPrometheusExporter(t *testing.T) { expectedFile: "testdata/sanitized_labels.txt", options: []Option{WithoutUnits()}, recordMetrics: func(ctx context.Context, meter otelmetric.Meter) { - attrs := []attribute.KeyValue{ + attrs := attribute.NewSet( // exact match, value should be overwritten attribute.Key("A.B").String("X"), attribute.Key("A.B").String("Q"), @@ -122,7 +125,8 @@ func TestPrometheusExporter(t *testing.T) { // unintended match due to sanitization, values should be concatenated attribute.Key("C.D").String("Y"), attribute.Key("C/D").String("Z"), - } + ) + opt := instrument.WithAttributes(attrs) counter, err := meter.Float64Counter( "foo", instrument.WithDescription("a sanitary counter"), @@ -130,37 +134,38 @@ func TestPrometheusExporter(t *testing.T) { instrument.WithUnit("By"), ) require.NoError(t, err) - counter.Add(ctx, 5, attrs...) - counter.Add(ctx, 10.3, attrs...) - counter.Add(ctx, 9, attrs...) + counter.Add(ctx, 5, opt) + counter.Add(ctx, 10.3, opt) + counter.Add(ctx, 9, opt) }, }, { name: "invalid instruments are renamed", expectedFile: "testdata/sanitized_names.txt", recordMetrics: func(ctx context.Context, meter otelmetric.Meter) { - attrs := []attribute.KeyValue{ + attrs := attribute.NewSet( attribute.Key("A").String("B"), attribute.Key("C").String("D"), - } + ) + opt := instrument.WithAttributes(attrs) // Valid. gauge, err := meter.Float64UpDownCounter("bar", instrument.WithDescription("a fun little gauge")) require.NoError(t, err) - gauge.Add(ctx, 100, attrs...) - gauge.Add(ctx, -25, attrs...) + gauge.Add(ctx, 100, opt) + gauge.Add(ctx, -25, opt) // Invalid, will be renamed. gauge, err = meter.Float64UpDownCounter("invalid.gauge.name", instrument.WithDescription("a gauge with an invalid name")) require.NoError(t, err) - gauge.Add(ctx, 100, attrs...) + gauge.Add(ctx, 100, opt) counter, err := meter.Float64Counter("0invalid.counter.name", instrument.WithDescription("a counter with an invalid name")) require.NoError(t, err) - counter.Add(ctx, 100, attrs...) + counter.Add(ctx, 100, opt) histogram, err := meter.Float64Histogram("invalid.hist.name", instrument.WithDescription("a histogram with an invalid name")) require.NoError(t, err) - histogram.Record(ctx, 23, attrs...) + histogram.Record(ctx, 23, opt) }, }, { @@ -168,17 +173,18 @@ func TestPrometheusExporter(t *testing.T) { emptyResource: true, expectedFile: "testdata/empty_resource.txt", recordMetrics: func(ctx context.Context, meter otelmetric.Meter) { - attrs := []attribute.KeyValue{ + attrs := attribute.NewSet( attribute.Key("A").String("B"), attribute.Key("C").String("D"), attribute.Key("E").Bool(true), attribute.Key("F").Int(42), - } + ) + opt := instrument.WithAttributes(attrs) counter, err := meter.Float64Counter("foo", instrument.WithDescription("a simple counter")) require.NoError(t, err) - counter.Add(ctx, 5, attrs...) - counter.Add(ctx, 10.3, attrs...) - counter.Add(ctx, 9, attrs...) + counter.Add(ctx, 5, opt) + counter.Add(ctx, 10.3, opt) + counter.Add(ctx, 9, opt) }, }, { @@ -189,17 +195,18 @@ func TestPrometheusExporter(t *testing.T) { }, expectedFile: "testdata/custom_resource.txt", recordMetrics: func(ctx context.Context, meter otelmetric.Meter) { - attrs := []attribute.KeyValue{ + attrs := attribute.NewSet( attribute.Key("A").String("B"), attribute.Key("C").String("D"), attribute.Key("E").Bool(true), attribute.Key("F").Int(42), - } + ) + opt := instrument.WithAttributes(attrs) counter, err := meter.Float64Counter("foo", instrument.WithDescription("a simple counter")) require.NoError(t, err) - counter.Add(ctx, 5, attrs...) - counter.Add(ctx, 10.3, attrs...) - counter.Add(ctx, 9, attrs...) + counter.Add(ctx, 5, opt) + counter.Add(ctx, 10.3, opt) + counter.Add(ctx, 9, opt) }, }, { @@ -207,17 +214,18 @@ func TestPrometheusExporter(t *testing.T) { options: []Option{WithoutTargetInfo()}, expectedFile: "testdata/without_target_info.txt", recordMetrics: func(ctx context.Context, meter otelmetric.Meter) { - attrs := []attribute.KeyValue{ + attrs := attribute.NewSet( attribute.Key("A").String("B"), attribute.Key("C").String("D"), attribute.Key("E").Bool(true), attribute.Key("F").Int(42), - } + ) + opt := instrument.WithAttributes(attrs) counter, err := meter.Float64Counter("foo", instrument.WithDescription("a simple counter")) require.NoError(t, err) - counter.Add(ctx, 5, attrs...) - counter.Add(ctx, 10.3, attrs...) - counter.Add(ctx, 9, attrs...) + counter.Add(ctx, 5, opt) + counter.Add(ctx, 10.3, opt) + counter.Add(ctx, 9, opt) }, }, { @@ -225,18 +233,19 @@ func TestPrometheusExporter(t *testing.T) { options: []Option{WithoutScopeInfo()}, expectedFile: "testdata/without_scope_info.txt", recordMetrics: func(ctx context.Context, meter otelmetric.Meter) { - attrs := []attribute.KeyValue{ + attrs := attribute.NewSet( attribute.Key("A").String("B"), attribute.Key("C").String("D"), - } + ) + opt := instrument.WithAttributes(attrs) gauge, err := meter.Int64UpDownCounter( "bar", instrument.WithDescription("a fun little gauge"), instrument.WithUnit("1"), ) require.NoError(t, err) - gauge.Add(ctx, 2, attrs...) - gauge.Add(ctx, -1, attrs...) + gauge.Add(ctx, 2, opt) + gauge.Add(ctx, -1, opt) }, }, { @@ -244,18 +253,19 @@ func TestPrometheusExporter(t *testing.T) { options: []Option{WithoutScopeInfo(), WithoutTargetInfo()}, expectedFile: "testdata/without_scope_and_target_info.txt", recordMetrics: func(ctx context.Context, meter otelmetric.Meter) { - attrs := []attribute.KeyValue{ + attrs := attribute.NewSet( attribute.Key("A").String("B"), attribute.Key("C").String("D"), - } + ) + opt := instrument.WithAttributes(attrs) counter, err := meter.Int64Counter( "bar", instrument.WithDescription("a fun little counter"), instrument.WithUnit("By"), ) require.NoError(t, err) - counter.Add(ctx, 2, attrs...) - counter.Add(ctx, 1, attrs...) + counter.Add(ctx, 2, opt) + counter.Add(ctx, 1, opt) }, }, { @@ -388,7 +398,8 @@ func TestMultiScopes(t *testing.T) { instrument.WithUnit("ms"), instrument.WithDescription("meter foo counter")) assert.NoError(t, err) - fooCounter.Add(ctx, 100, attribute.String("type", "foo")) + s := attribute.NewSet(attribute.String("type", "foo")) + fooCounter.Add(ctx, 100, instrument.WithAttributes(s)) barCounter, err := provider.Meter("meterbar", otelmetric.WithInstrumentationVersion("v0.1.0")). Int64Counter( @@ -396,7 +407,8 @@ func TestMultiScopes(t *testing.T) { instrument.WithUnit("ms"), instrument.WithDescription("meter bar counter")) assert.NoError(t, err) - barCounter.Add(ctx, 200, attribute.String("type", "bar")) + s = attribute.NewSet(attribute.String("type", "bar")) + barCounter.Add(ctx, 200, instrument.WithAttributes(s)) file, err := os.Open("testdata/multi_scopes.txt") require.NoError(t, err) @@ -407,6 +419,12 @@ func TestMultiScopes(t *testing.T) { } func TestDuplicateMetrics(t *testing.T) { + ab := attribute.NewSet(attribute.String("A", "B")) + withAB := instrument.WithAttributes(ab) + typeBar := attribute.NewSet(attribute.String("type", "bar")) + withTypeBar := instrument.WithAttributes(typeBar) + typeFoo := attribute.NewSet(attribute.String("type", "foo")) + withTypeFoo := instrument.WithAttributes(typeFoo) testCases := []struct { name string customResouceAttrs []attribute.KeyValue @@ -421,13 +439,13 @@ func TestDuplicateMetrics(t *testing.T) { instrument.WithUnit("By"), instrument.WithDescription("meter counter foo")) assert.NoError(t, err) - fooA.Add(ctx, 100, attribute.String("A", "B")) + fooA.Add(ctx, 100, withAB) fooB, err := meterB.Int64Counter("foo", instrument.WithUnit("By"), instrument.WithDescription("meter counter foo")) assert.NoError(t, err) - fooB.Add(ctx, 100, attribute.String("A", "B")) + fooB.Add(ctx, 100, withAB) }, possibleExpectedFiles: []string{"testdata/no_conflict_two_counters.txt"}, }, @@ -438,13 +456,13 @@ func TestDuplicateMetrics(t *testing.T) { instrument.WithUnit("By"), instrument.WithDescription("meter gauge foo")) assert.NoError(t, err) - fooA.Add(ctx, 100, attribute.String("A", "B")) + fooA.Add(ctx, 100, withAB) fooB, err := meterB.Int64UpDownCounter("foo", instrument.WithUnit("By"), instrument.WithDescription("meter gauge foo")) assert.NoError(t, err) - fooB.Add(ctx, 100, attribute.String("A", "B")) + fooB.Add(ctx, 100, withAB) }, possibleExpectedFiles: []string{"testdata/no_conflict_two_updowncounters.txt"}, }, @@ -455,13 +473,13 @@ func TestDuplicateMetrics(t *testing.T) { instrument.WithUnit("By"), instrument.WithDescription("meter histogram foo")) assert.NoError(t, err) - fooA.Record(ctx, 100, attribute.String("A", "B")) + fooA.Record(ctx, 100, withAB) fooB, err := meterB.Int64Histogram("foo", instrument.WithUnit("By"), instrument.WithDescription("meter histogram foo")) assert.NoError(t, err) - fooB.Record(ctx, 100, attribute.String("A", "B")) + fooB.Record(ctx, 100, withAB) }, possibleExpectedFiles: []string{"testdata/no_conflict_two_histograms.txt"}, }, @@ -472,13 +490,13 @@ func TestDuplicateMetrics(t *testing.T) { instrument.WithUnit("By"), instrument.WithDescription("meter a bar")) assert.NoError(t, err) - barA.Add(ctx, 100, attribute.String("type", "bar")) + barA.Add(ctx, 100, withTypeBar) barB, err := meterB.Int64Counter("bar", instrument.WithUnit("By"), instrument.WithDescription("meter b bar")) assert.NoError(t, err) - barB.Add(ctx, 100, attribute.String("type", "bar")) + barB.Add(ctx, 100, withTypeBar) }, possibleExpectedFiles: []string{ "testdata/conflict_help_two_counters_1.txt", @@ -492,13 +510,13 @@ func TestDuplicateMetrics(t *testing.T) { instrument.WithUnit("By"), instrument.WithDescription("meter a bar")) assert.NoError(t, err) - barA.Add(ctx, 100, attribute.String("type", "bar")) + barA.Add(ctx, 100, withTypeBar) barB, err := meterB.Int64UpDownCounter("bar", instrument.WithUnit("By"), instrument.WithDescription("meter b bar")) assert.NoError(t, err) - barB.Add(ctx, 100, attribute.String("type", "bar")) + barB.Add(ctx, 100, withTypeBar) }, possibleExpectedFiles: []string{ "testdata/conflict_help_two_updowncounters_1.txt", @@ -512,13 +530,13 @@ func TestDuplicateMetrics(t *testing.T) { instrument.WithUnit("By"), instrument.WithDescription("meter a bar")) assert.NoError(t, err) - barA.Record(ctx, 100, attribute.String("A", "B")) + barA.Record(ctx, 100, withAB) barB, err := meterB.Int64Histogram("bar", instrument.WithUnit("By"), instrument.WithDescription("meter b bar")) assert.NoError(t, err) - barB.Record(ctx, 100, attribute.String("A", "B")) + barB.Record(ctx, 100, withAB) }, possibleExpectedFiles: []string{ "testdata/conflict_help_two_histograms_1.txt", @@ -532,13 +550,13 @@ func TestDuplicateMetrics(t *testing.T) { instrument.WithUnit("By"), instrument.WithDescription("meter bar")) assert.NoError(t, err) - bazA.Add(ctx, 100, attribute.String("type", "bar")) + bazA.Add(ctx, 100, withTypeBar) bazB, err := meterB.Int64Counter("bar", instrument.WithUnit("ms"), instrument.WithDescription("meter bar")) assert.NoError(t, err) - bazB.Add(ctx, 100, attribute.String("type", "bar")) + bazB.Add(ctx, 100, withTypeBar) }, options: []Option{WithoutUnits()}, possibleExpectedFiles: []string{"testdata/conflict_unit_two_counters.txt"}, @@ -550,13 +568,13 @@ func TestDuplicateMetrics(t *testing.T) { instrument.WithUnit("By"), instrument.WithDescription("meter gauge bar")) assert.NoError(t, err) - barA.Add(ctx, 100, attribute.String("type", "bar")) + barA.Add(ctx, 100, withTypeBar) barB, err := meterB.Int64UpDownCounter("bar", instrument.WithUnit("ms"), instrument.WithDescription("meter gauge bar")) assert.NoError(t, err) - barB.Add(ctx, 100, attribute.String("type", "bar")) + barB.Add(ctx, 100, withTypeBar) }, options: []Option{WithoutUnits()}, possibleExpectedFiles: []string{"testdata/conflict_unit_two_updowncounters.txt"}, @@ -568,13 +586,13 @@ func TestDuplicateMetrics(t *testing.T) { instrument.WithUnit("By"), instrument.WithDescription("meter histogram bar")) assert.NoError(t, err) - barA.Record(ctx, 100, attribute.String("A", "B")) + barA.Record(ctx, 100, withAB) barB, err := meterB.Int64Histogram("bar", instrument.WithUnit("ms"), instrument.WithDescription("meter histogram bar")) assert.NoError(t, err) - barB.Record(ctx, 100, attribute.String("A", "B")) + barB.Record(ctx, 100, withAB) }, options: []Option{WithoutUnits()}, possibleExpectedFiles: []string{"testdata/conflict_unit_two_histograms.txt"}, @@ -586,13 +604,13 @@ func TestDuplicateMetrics(t *testing.T) { instrument.WithUnit("By"), instrument.WithDescription("meter foo")) assert.NoError(t, err) - counter.Add(ctx, 100, attribute.String("type", "foo")) + counter.Add(ctx, 100, withTypeFoo) gauge, err := meterA.Int64UpDownCounter("foo_total", instrument.WithUnit("By"), instrument.WithDescription("meter foo")) assert.NoError(t, err) - gauge.Add(ctx, 200, attribute.String("type", "foo")) + gauge.Add(ctx, 200, withTypeFoo) }, options: []Option{WithoutUnits()}, possibleExpectedFiles: []string{ @@ -607,13 +625,13 @@ func TestDuplicateMetrics(t *testing.T) { instrument.WithUnit("By"), instrument.WithDescription("meter gauge foo")) assert.NoError(t, err) - fooA.Add(ctx, 100, attribute.String("A", "B")) + fooA.Add(ctx, 100, withAB) fooHistogramA, err := meterA.Int64Histogram("foo", instrument.WithUnit("By"), instrument.WithDescription("meter histogram foo")) assert.NoError(t, err) - fooHistogramA.Record(ctx, 100, attribute.String("A", "B")) + fooHistogramA.Record(ctx, 100, withAB) }, possibleExpectedFiles: []string{ "testdata/conflict_type_histogram_and_updowncounter_1.txt", From 122d1479dcad98b65d9586030374133c4eb651c2 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Wed, 5 Apr 2023 11:42:48 -0700 Subject: [PATCH 07/16] Update examples --- example/prometheus/main.go | 17 +++++++++-------- example/view/main.go | 15 ++++++++------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/example/prometheus/main.go b/example/prometheus/main.go index 652140d9442..3d8fc628f42 100644 --- a/example/prometheus/main.go +++ b/example/prometheus/main.go @@ -50,17 +50,18 @@ func main() { // Start the prometheus HTTP server and pass the exporter Collector to it go serveMetrics() - attrs := []attribute.KeyValue{ + attrs := attribute.NewSet( attribute.Key("A").String("B"), attribute.Key("C").String("D"), - } + ) + opt := instrument.WithAttributes(attrs) // This is the equivalent of prometheus.NewCounterVec counter, err := meter.Float64Counter("foo", instrument.WithDescription("a simple counter")) if err != nil { log.Fatal(err) } - counter.Add(ctx, 5, attrs...) + counter.Add(ctx, 5, opt) gauge, err := meter.Float64ObservableGauge("bar", instrument.WithDescription("a fun little gauge")) if err != nil { @@ -68,7 +69,7 @@ func main() { } _, err = meter.RegisterCallback(func(_ context.Context, o api.Observer) error { n := -10. + rng.Float64()*(90.) // [-10, 100) - o.ObserveFloat64(gauge, n, attrs...) + o.ObserveFloat64(gauge, n, opt) return nil }, gauge) if err != nil { @@ -80,10 +81,10 @@ func main() { if err != nil { log.Fatal(err) } - histogram.Record(ctx, 23, attrs...) - histogram.Record(ctx, 7, attrs...) - histogram.Record(ctx, 101, attrs...) - histogram.Record(ctx, 105, attrs...) + histogram.Record(ctx, 23, opt) + histogram.Record(ctx, 7, opt) + histogram.Record(ctx, 101, opt) + histogram.Record(ctx, 105, opt) ctx, _ = signal.NotifyContext(ctx, os.Interrupt) <-ctx.Done() diff --git a/example/view/main.go b/example/view/main.go index b609e48737d..561b45be6d5 100644 --- a/example/view/main.go +++ b/example/view/main.go @@ -64,25 +64,26 @@ func main() { // Start the prometheus HTTP server and pass the exporter Collector to it go serveMetrics() - attrs := []attribute.KeyValue{ + attrs := attribute.NewSet( attribute.Key("A").String("B"), attribute.Key("C").String("D"), - } + ) + opt := instrument.WithAttributes(attrs) counter, err := meter.Float64Counter("foo", instrument.WithDescription("a simple counter")) if err != nil { log.Fatal(err) } - counter.Add(ctx, 5, attrs...) + counter.Add(ctx, 5, opt) histogram, err := meter.Float64Histogram("custom_histogram", instrument.WithDescription("a histogram with custom buckets and rename")) if err != nil { log.Fatal(err) } - histogram.Record(ctx, 136, attrs...) - histogram.Record(ctx, 64, attrs...) - histogram.Record(ctx, 701, attrs...) - histogram.Record(ctx, 830, attrs...) + histogram.Record(ctx, 136, opt) + histogram.Record(ctx, 64, opt) + histogram.Record(ctx, 701, opt) + histogram.Record(ctx, 830, opt) ctx, _ = signal.NotifyContext(ctx, os.Interrupt) <-ctx.Done() From 9faab8618db6633ede0ed79ea4867c8aa1e69ccc Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Mon, 10 Apr 2023 09:11:06 -0700 Subject: [PATCH 08/16] WithAttributes and WithAttributeSet --- example/prometheus/main.go | 3 +- example/view/main.go | 3 +- exporters/prometheus/exporter_test.go | 54 +++++------ metric/example_test.go | 3 +- metric/instrument/instrument.go | 62 ++++++++++--- metric/instrument/instrument_test.go | 125 ++++++++++++++++++++++++++ sdk/metric/benchmark_test.go | 19 ++-- sdk/metric/meter_test.go | 10 +-- 8 files changed, 211 insertions(+), 68 deletions(-) create mode 100644 metric/instrument/instrument_test.go diff --git a/example/prometheus/main.go b/example/prometheus/main.go index 3d8fc628f42..c716aa1e447 100644 --- a/example/prometheus/main.go +++ b/example/prometheus/main.go @@ -50,11 +50,10 @@ func main() { // Start the prometheus HTTP server and pass the exporter Collector to it go serveMetrics() - attrs := attribute.NewSet( + opt := instrument.WithAttributes( attribute.Key("A").String("B"), attribute.Key("C").String("D"), ) - opt := instrument.WithAttributes(attrs) // This is the equivalent of prometheus.NewCounterVec counter, err := meter.Float64Counter("foo", instrument.WithDescription("a simple counter")) diff --git a/example/view/main.go b/example/view/main.go index 561b45be6d5..1fc6d9cd636 100644 --- a/example/view/main.go +++ b/example/view/main.go @@ -64,11 +64,10 @@ func main() { // Start the prometheus HTTP server and pass the exporter Collector to it go serveMetrics() - attrs := attribute.NewSet( + opt := instrument.WithAttributes( attribute.Key("A").String("B"), attribute.Key("C").String("D"), ) - opt := instrument.WithAttributes(attrs) counter, err := meter.Float64Counter("foo", instrument.WithDescription("a simple counter")) if err != nil { diff --git a/exporters/prometheus/exporter_test.go b/exporters/prometheus/exporter_test.go index 4ec683c1cf1..c4674eb3ef0 100644 --- a/exporters/prometheus/exporter_test.go +++ b/exporters/prometheus/exporter_test.go @@ -46,13 +46,12 @@ func TestPrometheusExporter(t *testing.T) { name: "counter", expectedFile: "testdata/counter.txt", recordMetrics: func(ctx context.Context, meter otelmetric.Meter) { - attrs := attribute.NewSet( + opt := instrument.WithAttributes( attribute.Key("A").String("B"), attribute.Key("C").String("D"), attribute.Key("E").Bool(true), attribute.Key("F").Int(42), ) - opt := instrument.WithAttributes(attrs) counter, err := meter.Float64Counter( "foo", instrument.WithDescription("a simple counter"), @@ -69,18 +68,17 @@ func TestPrometheusExporter(t *testing.T) { attribute.Key("E").Bool(true), attribute.Key("F").Int(42), ) - counter.Add(ctx, 5, instrument.WithAttributes(attrs2)) + counter.Add(ctx, 5, instrument.WithAttributeSet(attrs2)) }, }, { name: "gauge", expectedFile: "testdata/gauge.txt", recordMetrics: func(ctx context.Context, meter otelmetric.Meter) { - attrs := attribute.NewSet( + opt := instrument.WithAttributes( attribute.Key("A").String("B"), attribute.Key("C").String("D"), ) - opt := instrument.WithAttributes(attrs) gauge, err := meter.Float64UpDownCounter( "bar", instrument.WithDescription("a fun little gauge"), @@ -95,11 +93,10 @@ func TestPrometheusExporter(t *testing.T) { name: "histogram", expectedFile: "testdata/histogram.txt", recordMetrics: func(ctx context.Context, meter otelmetric.Meter) { - attrs := attribute.NewSet( + opt := instrument.WithAttributes( attribute.Key("A").String("B"), attribute.Key("C").String("D"), ) - opt := instrument.WithAttributes(attrs) histogram, err := meter.Float64Histogram( "histogram_baz", instrument.WithDescription("a very nice histogram"), @@ -117,7 +114,7 @@ func TestPrometheusExporter(t *testing.T) { expectedFile: "testdata/sanitized_labels.txt", options: []Option{WithoutUnits()}, recordMetrics: func(ctx context.Context, meter otelmetric.Meter) { - attrs := attribute.NewSet( + opt := instrument.WithAttributes( // exact match, value should be overwritten attribute.Key("A.B").String("X"), attribute.Key("A.B").String("Q"), @@ -126,7 +123,6 @@ func TestPrometheusExporter(t *testing.T) { attribute.Key("C.D").String("Y"), attribute.Key("C/D").String("Z"), ) - opt := instrument.WithAttributes(attrs) counter, err := meter.Float64Counter( "foo", instrument.WithDescription("a sanitary counter"), @@ -143,11 +139,10 @@ func TestPrometheusExporter(t *testing.T) { name: "invalid instruments are renamed", expectedFile: "testdata/sanitized_names.txt", recordMetrics: func(ctx context.Context, meter otelmetric.Meter) { - attrs := attribute.NewSet( + opt := instrument.WithAttributes( attribute.Key("A").String("B"), attribute.Key("C").String("D"), ) - opt := instrument.WithAttributes(attrs) // Valid. gauge, err := meter.Float64UpDownCounter("bar", instrument.WithDescription("a fun little gauge")) require.NoError(t, err) @@ -173,13 +168,12 @@ func TestPrometheusExporter(t *testing.T) { emptyResource: true, expectedFile: "testdata/empty_resource.txt", recordMetrics: func(ctx context.Context, meter otelmetric.Meter) { - attrs := attribute.NewSet( + opt := instrument.WithAttributes( attribute.Key("A").String("B"), attribute.Key("C").String("D"), attribute.Key("E").Bool(true), attribute.Key("F").Int(42), ) - opt := instrument.WithAttributes(attrs) counter, err := meter.Float64Counter("foo", instrument.WithDescription("a simple counter")) require.NoError(t, err) counter.Add(ctx, 5, opt) @@ -195,13 +189,12 @@ func TestPrometheusExporter(t *testing.T) { }, expectedFile: "testdata/custom_resource.txt", recordMetrics: func(ctx context.Context, meter otelmetric.Meter) { - attrs := attribute.NewSet( + opt := instrument.WithAttributes( attribute.Key("A").String("B"), attribute.Key("C").String("D"), attribute.Key("E").Bool(true), attribute.Key("F").Int(42), ) - opt := instrument.WithAttributes(attrs) counter, err := meter.Float64Counter("foo", instrument.WithDescription("a simple counter")) require.NoError(t, err) counter.Add(ctx, 5, opt) @@ -214,13 +207,12 @@ func TestPrometheusExporter(t *testing.T) { options: []Option{WithoutTargetInfo()}, expectedFile: "testdata/without_target_info.txt", recordMetrics: func(ctx context.Context, meter otelmetric.Meter) { - attrs := attribute.NewSet( + opt := instrument.WithAttributes( attribute.Key("A").String("B"), attribute.Key("C").String("D"), attribute.Key("E").Bool(true), attribute.Key("F").Int(42), ) - opt := instrument.WithAttributes(attrs) counter, err := meter.Float64Counter("foo", instrument.WithDescription("a simple counter")) require.NoError(t, err) counter.Add(ctx, 5, opt) @@ -233,11 +225,10 @@ func TestPrometheusExporter(t *testing.T) { options: []Option{WithoutScopeInfo()}, expectedFile: "testdata/without_scope_info.txt", recordMetrics: func(ctx context.Context, meter otelmetric.Meter) { - attrs := attribute.NewSet( + opt := instrument.WithAttributes( attribute.Key("A").String("B"), attribute.Key("C").String("D"), ) - opt := instrument.WithAttributes(attrs) gauge, err := meter.Int64UpDownCounter( "bar", instrument.WithDescription("a fun little gauge"), @@ -253,11 +244,10 @@ func TestPrometheusExporter(t *testing.T) { options: []Option{WithoutScopeInfo(), WithoutTargetInfo()}, expectedFile: "testdata/without_scope_and_target_info.txt", recordMetrics: func(ctx context.Context, meter otelmetric.Meter) { - attrs := attribute.NewSet( + opt := instrument.WithAttributes( attribute.Key("A").String("B"), attribute.Key("C").String("D"), ) - opt := instrument.WithAttributes(attrs) counter, err := meter.Int64Counter( "bar", instrument.WithDescription("a fun little counter"), @@ -275,17 +265,17 @@ func TestPrometheusExporter(t *testing.T) { WithNamespace("test"), }, recordMetrics: func(ctx context.Context, meter otelmetric.Meter) { - attrs := []attribute.KeyValue{ + opt := instrument.WithAttributes( attribute.Key("A").String("B"), attribute.Key("C").String("D"), attribute.Key("E").Bool(true), attribute.Key("F").Int(42), - } + ) counter, err := meter.Float64Counter("foo", instrument.WithDescription("a simple counter")) require.NoError(t, err) - counter.Add(ctx, 5, attrs...) - counter.Add(ctx, 10.3, attrs...) - counter.Add(ctx, 9, attrs...) + counter.Add(ctx, 5, opt) + counter.Add(ctx, 10.3, opt) + counter.Add(ctx, 9, opt) }, }, } @@ -398,8 +388,7 @@ func TestMultiScopes(t *testing.T) { instrument.WithUnit("ms"), instrument.WithDescription("meter foo counter")) assert.NoError(t, err) - s := attribute.NewSet(attribute.String("type", "foo")) - fooCounter.Add(ctx, 100, instrument.WithAttributes(s)) + fooCounter.Add(ctx, 100, instrument.WithAttributes(attribute.String("type", "foo"))) barCounter, err := provider.Meter("meterbar", otelmetric.WithInstrumentationVersion("v0.1.0")). Int64Counter( @@ -407,8 +396,7 @@ func TestMultiScopes(t *testing.T) { instrument.WithUnit("ms"), instrument.WithDescription("meter bar counter")) assert.NoError(t, err) - s = attribute.NewSet(attribute.String("type", "bar")) - barCounter.Add(ctx, 200, instrument.WithAttributes(s)) + barCounter.Add(ctx, 200, instrument.WithAttributes(attribute.String("type", "bar"))) file, err := os.Open("testdata/multi_scopes.txt") require.NoError(t, err) @@ -420,11 +408,11 @@ func TestMultiScopes(t *testing.T) { func TestDuplicateMetrics(t *testing.T) { ab := attribute.NewSet(attribute.String("A", "B")) - withAB := instrument.WithAttributes(ab) + withAB := instrument.WithAttributeSet(ab) typeBar := attribute.NewSet(attribute.String("type", "bar")) - withTypeBar := instrument.WithAttributes(typeBar) + withTypeBar := instrument.WithAttributeSet(typeBar) typeFoo := attribute.NewSet(attribute.String("type", "foo")) - withTypeFoo := instrument.WithAttributes(typeFoo) + withTypeFoo := instrument.WithAttributeSet(typeFoo) testCases := []struct { name string customResouceAttrs []attribute.KeyValue diff --git a/metric/example_test.go b/metric/example_test.go index 41d835ec5b4..fee7e415bc2 100644 --- a/metric/example_test.go +++ b/metric/example_test.go @@ -63,8 +63,7 @@ func ExampleMeter_asynchronous_single() { // // For demonstration purpose, a static value is used here. usage := 75000 - s := attribute.NewSet(attribute.Int("disk.id", 3)) - obsrv.Observe(int64(usage), instrument.WithAttributes(s)) + obsrv.Observe(int64(usage), instrument.WithAttributes(attribute.Int("disk.id", 3))) return nil }), ) diff --git a/metric/instrument/instrument.go b/metric/instrument/instrument.go index efb6b043a2b..fce5a72a0f5 100644 --- a/metric/instrument/instrument.go +++ b/metric/instrument/instrument.go @@ -182,7 +182,7 @@ type Int64AddConfig struct { // NewInt64AddConfig returns a new [Int64AddConfig] with all opts applied. func NewInt64AddConfig(opts ...Int64AddOption) Int64AddConfig { - var config Int64AddConfig + config := Int64AddConfig{attrs: *attribute.EmptySet()} for _, o := range opts { config = o.applyInt64Add(config) } @@ -208,7 +208,7 @@ type Float64AddConfig struct { // NewFloat64AddConfig returns a new [Float64AddConfig] with all opts applied. func NewFloat64AddConfig(opts ...Float64AddOption) Float64AddConfig { - var config Float64AddConfig + config := Float64AddConfig{attrs: *attribute.EmptySet()} for _, o := range opts { config = o.applyFloat64Add(config) } @@ -235,7 +235,7 @@ type Int64RecordConfig struct { // NewInt64RecordConfig returns a new [Int64RecordConfig] with all opts // applied. func NewInt64RecordConfig(opts ...Int64RecordOption) Int64RecordConfig { - var config Int64RecordConfig + config := Int64RecordConfig{attrs: *attribute.EmptySet()} for _, o := range opts { config = o.applyInt64Record(config) } @@ -262,7 +262,7 @@ type Float64RecordConfig struct { // NewFloat64RecordConfig returns a new [Float64RecordConfig] with all opts // applied. func NewFloat64RecordConfig(opts ...Float64RecordOption) Float64RecordConfig { - var config Float64RecordConfig + config := Float64RecordConfig{attrs: *attribute.EmptySet()} for _, o := range opts { config = o.applyFloat64Record(config) } @@ -289,7 +289,7 @@ type Int64ObserveConfig struct { // NewInt64ObserveConfig returns a new [Int64ObserveConfig] with all opts // applied. func NewInt64ObserveConfig(opts ...Int64ObserveOption) Int64ObserveConfig { - var config Int64ObserveConfig + config := Int64ObserveConfig{attrs: *attribute.EmptySet()} for _, o := range opts { config = o.applyInt64Observe(config) } @@ -316,7 +316,7 @@ type Float64ObserveConfig struct { // NewFloat64ObserveConfig returns a new [Float64ObserveConfig] with all opts // applied. func NewFloat64ObserveConfig(opts ...Float64ObserveOption) Float64ObserveConfig { - var config Float64ObserveConfig + config := Float64ObserveConfig{attrs: *attribute.EmptySet()} for _, o := range opts { config = o.applyFloat64Observe(config) } @@ -342,37 +342,71 @@ 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 { + switch 0 { + case a.Len(): + return b + case b.Len(): + return a + } + + // 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) applyInt64Add(c Int64AddConfig) Int64AddConfig { - c.attrs = o.set + c.attrs = mergeSets(c.attrs, o.set) return c } func (o attrOpt) applyFloat64Add(c Float64AddConfig) Float64AddConfig { - c.attrs = o.set + c.attrs = mergeSets(c.attrs, o.set) return c } func (o attrOpt) applyInt64Record(c Int64RecordConfig) Int64RecordConfig { - c.attrs = o.set + c.attrs = mergeSets(c.attrs, o.set) return c } func (o attrOpt) applyFloat64Record(c Float64RecordConfig) Float64RecordConfig { - c.attrs = o.set + c.attrs = mergeSets(c.attrs, o.set) return c } func (o attrOpt) applyInt64Observe(c Int64ObserveConfig) Int64ObserveConfig { - c.attrs = o.set + c.attrs = mergeSets(c.attrs, o.set) return c } func (o attrOpt) applyFloat64Observe(c Float64ObserveConfig) Float64ObserveConfig { - c.attrs = o.set + c.attrs = mergeSets(c.attrs, o.set) return c } -// WithAttributes sets the attributes a measurement is made with. -func WithAttributes(attributes attribute.Set) MeasurementOption { +// 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} } + +// WithAttributeSet converts attributes into an attribute Set and sets the Set +// to be associated with a measurement. This is shorthand for: +// +// WithAttributes(attribute.NewSet(attributes...)) +// +// See [WithAttributeSet] for how multiple WithAttributes are merged. +func WithAttributes(attributes ...attribute.KeyValue) MeasurementOption { + return attrOpt{set: attribute.NewSet(attributes...)} +} diff --git a/metric/instrument/instrument_test.go b/metric/instrument/instrument_test.go new file mode 100644 index 00000000000..872cad6b838 --- /dev/null +++ b/metric/instrument/instrument_test.go @@ -0,0 +1,125 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package instrument // import "go.opentelemetry.io/otel/metric/instrument" + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/otel/attribute" +) + +type attrConf interface { + Attributes() attribute.Set +} + +func TestWithAttributeSet(t *testing.T) { + t.Run("Float64AddConfig", testConfAttr(func(mo ...MeasurementOption) attrConf { + opts := make([]Float64AddOption, len(mo)) + for i := range mo { + opts[i] = mo[i].(Float64AddOption) + } + return NewFloat64AddConfig(opts...) + })) + + t.Run("Int64AddConfig", testConfAttr(func(mo ...MeasurementOption) attrConf { + opts := make([]Int64AddOption, len(mo)) + for i := range mo { + opts[i] = mo[i].(Int64AddOption) + } + return NewInt64AddConfig(opts...) + })) + + t.Run("Float64RecordConfig", testConfAttr(func(mo ...MeasurementOption) attrConf { + opts := make([]Float64RecordOption, len(mo)) + for i := range mo { + opts[i] = mo[i].(Float64RecordOption) + } + return NewFloat64RecordConfig(opts...) + })) + + t.Run("Int64RecordConfig", testConfAttr(func(mo ...MeasurementOption) attrConf { + opts := make([]Int64RecordOption, len(mo)) + for i := range mo { + opts[i] = mo[i].(Int64RecordOption) + } + return NewInt64RecordConfig(opts...) + })) + + t.Run("Float64ObserveConfig", testConfAttr(func(mo ...MeasurementOption) attrConf { + opts := make([]Float64ObserveOption, len(mo)) + for i := range mo { + opts[i] = mo[i].(Float64ObserveOption) + } + return NewFloat64ObserveConfig(opts...) + })) + + t.Run("Int64ObserveConfig", testConfAttr(func(mo ...MeasurementOption) attrConf { + opts := make([]Int64ObserveOption, len(mo)) + for i := range mo { + opts[i] = mo[i].(Int64ObserveOption) + } + return NewInt64ObserveConfig(opts...) + })) +} + +func testConfAttr(newConf func(...MeasurementOption) attrConf) func(t *testing.T) { + return func(t *testing.T) { + t.Run("ZeroConfigEmpty", func(t *testing.T) { + c := newConf() + assert.Equal(t, *attribute.EmptySet(), c.Attributes()) + }) + + t.Run("EmptySet", func(t *testing.T) { + c := newConf(WithAttributeSet(*attribute.EmptySet())) + assert.Equal(t, *attribute.EmptySet(), c.Attributes()) + }) + + aliceAttr := attribute.String("user", "Alice") + alice := attribute.NewSet(aliceAttr) + t.Run("SingleWithAttributeSet", func(t *testing.T) { + c := newConf(WithAttributeSet(alice)) + assert.Equal(t, alice, c.Attributes()) + }) + + t.Run("SingleWithAttributes", func(t *testing.T) { + c := newConf(WithAttributes(aliceAttr)) + assert.Equal(t, alice, c.Attributes()) + }) + + bobAttr := attribute.String("user", "Bob") + bob := attribute.NewSet(bobAttr) + t.Run("MultiWithAttributeSet", func(t *testing.T) { + c := newConf(WithAttributeSet(alice), WithAttributeSet(bob)) + assert.Equal(t, bob, c.Attributes()) + }) + + t.Run("MergedWithAttributes", func(t *testing.T) { + c := newConf(WithAttributes(aliceAttr, bobAttr)) + assert.Equal(t, bob, c.Attributes()) + }) + + t.Run("MultiWithAttributeSet", func(t *testing.T) { + c := newConf(WithAttributes(aliceAttr), WithAttributes(bobAttr)) + assert.Equal(t, bob, c.Attributes()) + }) + + t.Run("MergedEmpty", func(t *testing.T) { + c := newConf(WithAttributeSet(alice), WithAttributeSet(*attribute.EmptySet())) + assert.Equal(t, alice, c.Attributes()) + }) + } +} diff --git a/sdk/metric/benchmark_test.go b/sdk/metric/benchmark_test.go index 3b0ad1de135..ff9fdc5c45a 100644 --- a/sdk/metric/benchmark_test.go +++ b/sdk/metric/benchmark_test.go @@ -47,7 +47,7 @@ func BenchmarkCounterAddOneAttr(b *testing.B) { ctx, _, cntr := benchCounter(b) for i := 0; i < b.N; i++ { - cntr.Add(ctx, 1, instrument.WithAttributes(s)) + cntr.Add(ctx, 1, instrument.WithAttributeSet(s)) } } @@ -59,7 +59,7 @@ func BenchmarkCounterAddOneInvalidAttr(b *testing.B) { ctx, _, cntr := benchCounter(b) for i := 0; i < b.N; i++ { - cntr.Add(ctx, 1, instrument.WithAttributes(s)) + cntr.Add(ctx, 1, instrument.WithAttributeSet(s)) } } @@ -68,7 +68,7 @@ func BenchmarkCounterAddSingleUseAttrs(b *testing.B) { for i := 0; i < b.N; i++ { s := attribute.NewSet(attribute.Int("K", i)) - cntr.Add(ctx, 1, instrument.WithAttributes(s)) + cntr.Add(ctx, 1, instrument.WithAttributeSet(s)) } } @@ -76,11 +76,11 @@ func BenchmarkCounterAddSingleUseInvalidAttrs(b *testing.B) { ctx, _, cntr := benchCounter(b) for i := 0; i < b.N; i++ { - s := attribute.NewSet( + o := instrument.WithAttributes( attribute.Int("", i), attribute.Int("K", i), ) - cntr.Add(ctx, 1, instrument.WithAttributes(s)) + cntr.Add(ctx, 1, o) } } @@ -93,11 +93,11 @@ func BenchmarkCounterAddSingleUseFilteredAttrs(b *testing.B) { )) for i := 0; i < b.N; i++ { - s := attribute.NewSet( + o := instrument.WithAttributes( attribute.Int("L", i), attribute.Int("K", i), ) - cntr.Add(ctx, 1, instrument.WithAttributes(s)) + cntr.Add(ctx, 1, o) } } @@ -106,7 +106,7 @@ func BenchmarkCounterCollectOneAttr(b *testing.B) { ctx, rdr, cntr := benchCounter(b) for i := 0; i < b.N; i++ { - cntr.Add(ctx, 1, instrument.WithAttributes(s)) + cntr.Add(ctx, 1, instrument.WithAttributeSet(s)) _ = rdr.Collect(ctx, nil) } @@ -117,8 +117,7 @@ func BenchmarkCounterCollectTenAttrs(b *testing.B) { for i := 0; i < b.N; i++ { for j := 0; j < 10; j++ { - s := attribute.NewSet(attribute.Int("K", j)) - cntr.Add(ctx, 1, instrument.WithAttributes(s)) + cntr.Add(ctx, 1, instrument.WithAttributes(attribute.Int("K", j))) } _ = rdr.Collect(ctx, nil) } diff --git a/sdk/metric/meter_test.go b/sdk/metric/meter_test.go index d0b965832c7..ca82a2f5282 100644 --- a/sdk/metric/meter_test.go +++ b/sdk/metric/meter_test.go @@ -169,7 +169,7 @@ func TestCallbackUnregisterConcurrency(t *testing.T) { // Instruments should produce correct ResourceMetrics. func TestMeterCreatesInstruments(t *testing.T) { attrs := attribute.NewSet(attribute.String("name", "alice")) - opt := instrument.WithAttributes(attrs) + opt := instrument.WithAttributeSet(attrs) testCases := []struct { name string fn func(*testing.T, metric.Meter) @@ -886,11 +886,11 @@ func TestAttributeFilter(t *testing.T) { func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) { fooBar := attribute.NewSet(attribute.String("foo", "bar")) - withFooBar := instrument.WithAttributes(fooBar) + withFooBar := instrument.WithAttributeSet(fooBar) v1 := attribute.NewSet(attribute.String("foo", "bar"), attribute.Int("version", 1)) - withV1 := instrument.WithAttributes(v1) + withV1 := instrument.WithAttributeSet(v1) v2 := attribute.NewSet(attribute.String("foo", "bar"), attribute.Int("version", 2)) - withV2 := instrument.WithAttributes(v2) + withV2 := instrument.WithAttributeSet(v2) testcases := []struct { name string register func(t *testing.T, mtr metric.Meter) error @@ -1275,7 +1275,7 @@ func TestObservableExample(t *testing.T) { _, err := meter.Int64ObservableCounter(instName, instrument.WithInt64Callback( func(_ context.Context, o instrument.Int64Observer) error { for attrSet, val := range observations { - o.Observe(val, instrument.WithAttributes(attrSet)) + o.Observe(val, instrument.WithAttributeSet(attrSet)) } return nil }, From 796b83dd89bd56f14c0376319eeebd317f45bf82 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Mon, 10 Apr 2023 09:57:42 -0700 Subject: [PATCH 09/16] Add changes to changelog --- CHANGELOG.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a75215263e..2709b5afaa0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,25 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - The `go.opentelemetry.io/otel/metric/embedded` package. (#3916) - The `Version` function to `go.opentelemetry.io/otel/sdk` to return the SDK version. (#3949) - Add a `WithNamespace` option to `go.opentelemetry.io/otel/exporters/prometheus` to allow users to prefix metrics with a namespace. (#3970) +- The following configuration types were added to `go.opentelemetry.io/otel/metric/instrument` to be used in the configuration of measurement methods. (#3971) + - The `Int64AddConfig` used to hold configuration for `int64` addition measurements + - `NewInt64AddConfig` used to create a new `Int64AddConfig` + - `Int64AddOption` used to configure an `Int64AddConfig` + - The `Float64AddConfig` used to hold configuration for `float64` addition measurements + - `NewFloat64AddConfig` used to create a new `Float64AddConfig` + - `Float64AddOption` used to configure an `Float64AddConfig` + - The `Int64RecordConfig` used to hold configuration for `int64` recorded measurements + - `NewInt64RecordConfig` used to create a new `Int64RecordConfig` + - `Int64RecordOption` used to configure an `Int64RecordConfig` + - The `Float64RecordConfig` used to hold configuration for `float64` recorded measurements + - `NewFloat64RecordConfig` used to create a new `Float64RecordConfig` + - `Float64RecordOption` used to configure an `Float64RecordConfig` + - The `Int64ObserveConfig` used to hold configuration for `int64` observed measurements + - `NewInt64ObserveConfig` used to create a new `Int64ObserveConfig` + - `Int64ObserveOption` used to configure an `Int64ObserveConfig` + - The `Float64ObserveConfig` used to hold configuration for `float64` observed measurements + - `NewFloat64ObserveConfig` used to create a new `Float64ObserveConfig` + - `Float64ObserveOption` used to configure an `Float64ObserveConfig` ### Changed @@ -22,6 +41,18 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Move No-Op implementation from `go.opentelemetry.io/otel/metric` into its own package `go.opentelemetry.io/otel/metric/noop`. (#3941) - `metric.NewNoopMeterProvider` is replaced with `noop.NewMeterProvider` - Wrap `UploadMetrics` error in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/` to improve error message when encountering generic grpc errors. (#3974) +- The measurement methods for all instruments in `go.opentelemetry.io/otel/metric/instrument` accept an option instead of the variadic `"go.opentelemetry.io/otel/attribute".KeyValue`. (#3971) + - The `Int64Counter.Add` method now accepts `...Int64AddOption` + - The `Float64Counter.Add` method now accepts `...Float64AddOption` + - The `Int64UpDownCounter.Add` method now accepts `...Int64AddOption` + - The `Float64UpDownCounter.Add` method now accepts `...Float64AddOption` + - The `Int64Histogram.Record` method now accepts `...Int64RecordOption` + - The `Float64Histogram.Record` method now accepts `...Float64RecordOption` + - The `Int64Observer.Observe` method now accepts `...Int64ObserveOption` + - The `Float64Observer.Observe` method now accepts `...Float64ObserveOption` +- The `Observer` methods in `go.opentelemetry.io/otel/metric` accept an option instead of the variadic `"go.opentelemetry.io/otel/attribute".KeyValue`. (#3971) + - The `Observer.ObserveInt64` method now accepts `...Int64ObserveOption` + - The `Observer.ObserveFloat64` method now accepts `...Float64ObserveOption` ### Fixed From 344f812c03b7a7069d1179038813c9ca344fc2a4 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Mon, 10 Apr 2023 13:26:58 -0700 Subject: [PATCH 10/16] Accept slice instead of variadic to new conf funcs --- metric/instrument/instrument.go | 71 ++++++++++++++++++++-------- metric/instrument/instrument_test.go | 65 ++++++++++++++++++++++--- sdk/metric/benchmark_test.go | 63 +++++++++++++++--------- sdk/metric/instrument.go | 8 ++-- sdk/metric/meter.go | 8 ++-- 5 files changed, 158 insertions(+), 57 deletions(-) diff --git a/metric/instrument/instrument.go b/metric/instrument/instrument.go index fce5a72a0f5..d9daf20ca50 100644 --- a/metric/instrument/instrument.go +++ b/metric/instrument/instrument.go @@ -181,7 +181,7 @@ type Int64AddConfig struct { } // NewInt64AddConfig returns a new [Int64AddConfig] with all opts applied. -func NewInt64AddConfig(opts ...Int64AddOption) Int64AddConfig { +func NewInt64AddConfig(opts []Int64AddOption) Int64AddConfig { config := Int64AddConfig{attrs: *attribute.EmptySet()} for _, o := range opts { config = o.applyInt64Add(config) @@ -207,7 +207,7 @@ type Float64AddConfig struct { } // NewFloat64AddConfig returns a new [Float64AddConfig] with all opts applied. -func NewFloat64AddConfig(opts ...Float64AddOption) Float64AddConfig { +func NewFloat64AddConfig(opts []Float64AddOption) Float64AddConfig { config := Float64AddConfig{attrs: *attribute.EmptySet()} for _, o := range opts { config = o.applyFloat64Add(config) @@ -234,7 +234,7 @@ type Int64RecordConfig struct { // NewInt64RecordConfig returns a new [Int64RecordConfig] with all opts // applied. -func NewInt64RecordConfig(opts ...Int64RecordOption) Int64RecordConfig { +func NewInt64RecordConfig(opts []Int64RecordOption) Int64RecordConfig { config := Int64RecordConfig{attrs: *attribute.EmptySet()} for _, o := range opts { config = o.applyInt64Record(config) @@ -261,7 +261,7 @@ type Float64RecordConfig struct { // NewFloat64RecordConfig returns a new [Float64RecordConfig] with all opts // applied. -func NewFloat64RecordConfig(opts ...Float64RecordOption) Float64RecordConfig { +func NewFloat64RecordConfig(opts []Float64RecordOption) Float64RecordConfig { config := Float64RecordConfig{attrs: *attribute.EmptySet()} for _, o := range opts { config = o.applyFloat64Record(config) @@ -288,7 +288,7 @@ type Int64ObserveConfig struct { // NewInt64ObserveConfig returns a new [Int64ObserveConfig] with all opts // applied. -func NewInt64ObserveConfig(opts ...Int64ObserveOption) Int64ObserveConfig { +func NewInt64ObserveConfig(opts []Int64ObserveOption) Int64ObserveConfig { config := Int64ObserveConfig{attrs: *attribute.EmptySet()} for _, o := range opts { config = o.applyInt64Observe(config) @@ -315,7 +315,7 @@ type Float64ObserveConfig struct { // NewFloat64ObserveConfig returns a new [Float64ObserveConfig] with all opts // applied. -func NewFloat64ObserveConfig(opts ...Float64ObserveOption) Float64ObserveConfig { +func NewFloat64ObserveConfig(opts []Float64ObserveOption) Float64ObserveConfig { config := Float64ObserveConfig{attrs: *attribute.EmptySet()} for _, o := range opts { config = o.applyFloat64Observe(config) @@ -345,13 +345,6 @@ type attrOpt struct { // 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 { - switch 0 { - case a.Len(): - return b - case b.Len(): - return a - } - // NewMergeIterator uses the first value for any duplicates. iter := attribute.NewMergeIterator(&b, &a) merged := make([]attribute.KeyValue, 0, a.Len()+b.Len()) @@ -362,32 +355,68 @@ func mergeSets(a, b attribute.Set) attribute.Set { } func (o attrOpt) applyInt64Add(c Int64AddConfig) Int64AddConfig { - c.attrs = mergeSets(c.attrs, o.set) + 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) applyFloat64Add(c Float64AddConfig) Float64AddConfig { - c.attrs = mergeSets(c.attrs, o.set) + 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) applyInt64Record(c Int64RecordConfig) Int64RecordConfig { - c.attrs = mergeSets(c.attrs, o.set) + 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) applyFloat64Record(c Float64RecordConfig) Float64RecordConfig { - c.attrs = mergeSets(c.attrs, o.set) + 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) applyInt64Observe(c Int64ObserveConfig) Int64ObserveConfig { - c.attrs = mergeSets(c.attrs, o.set) + 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) applyFloat64Observe(c Float64ObserveConfig) Float64ObserveConfig { - c.attrs = mergeSets(c.attrs, o.set) + 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 } @@ -408,5 +437,7 @@ func WithAttributeSet(attributes attribute.Set) MeasurementOption { // // See [WithAttributeSet] for how multiple WithAttributes are merged. func WithAttributes(attributes ...attribute.KeyValue) MeasurementOption { - return attrOpt{set: attribute.NewSet(attributes...)} + cp := make([]attribute.KeyValue, len(attributes)) + copy(cp, attributes) + return attrOpt{set: attribute.NewSet(cp...)} } diff --git a/metric/instrument/instrument_test.go b/metric/instrument/instrument_test.go index 872cad6b838..a3965266b3c 100644 --- a/metric/instrument/instrument_test.go +++ b/metric/instrument/instrument_test.go @@ -15,6 +15,7 @@ package instrument // import "go.opentelemetry.io/otel/metric/instrument" import ( + "sync" "testing" "github.com/stretchr/testify/assert" @@ -26,13 +27,13 @@ type attrConf interface { Attributes() attribute.Set } -func TestWithAttributeSet(t *testing.T) { +func TestConfigAttrs(t *testing.T) { t.Run("Float64AddConfig", testConfAttr(func(mo ...MeasurementOption) attrConf { opts := make([]Float64AddOption, len(mo)) for i := range mo { opts[i] = mo[i].(Float64AddOption) } - return NewFloat64AddConfig(opts...) + return NewFloat64AddConfig(opts) })) t.Run("Int64AddConfig", testConfAttr(func(mo ...MeasurementOption) attrConf { @@ -40,7 +41,7 @@ func TestWithAttributeSet(t *testing.T) { for i := range mo { opts[i] = mo[i].(Int64AddOption) } - return NewInt64AddConfig(opts...) + return NewInt64AddConfig(opts) })) t.Run("Float64RecordConfig", testConfAttr(func(mo ...MeasurementOption) attrConf { @@ -48,7 +49,7 @@ func TestWithAttributeSet(t *testing.T) { for i := range mo { opts[i] = mo[i].(Float64RecordOption) } - return NewFloat64RecordConfig(opts...) + return NewFloat64RecordConfig(opts) })) t.Run("Int64RecordConfig", testConfAttr(func(mo ...MeasurementOption) attrConf { @@ -56,7 +57,7 @@ func TestWithAttributeSet(t *testing.T) { for i := range mo { opts[i] = mo[i].(Int64RecordOption) } - return NewInt64RecordConfig(opts...) + return NewInt64RecordConfig(opts) })) t.Run("Float64ObserveConfig", testConfAttr(func(mo ...MeasurementOption) attrConf { @@ -64,7 +65,7 @@ func TestWithAttributeSet(t *testing.T) { for i := range mo { opts[i] = mo[i].(Float64ObserveOption) } - return NewFloat64ObserveConfig(opts...) + return NewFloat64ObserveConfig(opts) })) t.Run("Int64ObserveConfig", testConfAttr(func(mo ...MeasurementOption) attrConf { @@ -72,7 +73,7 @@ func TestWithAttributeSet(t *testing.T) { for i := range mo { opts[i] = mo[i].(Int64ObserveOption) } - return NewInt64ObserveConfig(opts...) + return NewInt64ObserveConfig(opts) })) } @@ -123,3 +124,53 @@ func testConfAttr(newConf func(...MeasurementOption) attrConf) func(t *testing.T }) } } + +func TestWithAttributesRace(t *testing.T) { + attrs := []attribute.KeyValue{ + attribute.String("user", "Alice"), + attribute.Bool("admin", true), + attribute.String("user", "Bob"), + } + + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + opt := []Int64AddOption{WithAttributes(attrs...)} + _ = NewInt64AddConfig(opt) + }() + wg.Add(1) + go func() { + defer wg.Done() + opt := []Float64AddOption{WithAttributes(attrs...)} + _ = NewFloat64AddConfig(opt) + }() + + wg.Add(1) + go func() { + defer wg.Done() + opt := []Int64RecordOption{WithAttributes(attrs...)} + _ = NewInt64RecordConfig(opt) + }() + wg.Add(1) + go func() { + defer wg.Done() + opt := []Float64RecordOption{WithAttributes(attrs...)} + _ = NewFloat64RecordConfig(opt) + }() + + wg.Add(1) + go func() { + defer wg.Done() + opt := []Int64ObserveOption{WithAttributes(attrs...)} + _ = NewInt64ObserveConfig(opt) + }() + wg.Add(1) + go func() { + defer wg.Done() + opt := []Float64ObserveOption{WithAttributes(attrs...)} + _ = NewFloat64ObserveConfig(opt) + }() + + wg.Wait() +} diff --git a/sdk/metric/benchmark_test.go b/sdk/metric/benchmark_test.go index ff9fdc5c45a..f3527ede0e8 100644 --- a/sdk/metric/benchmark_test.go +++ b/sdk/metric/benchmark_test.go @@ -43,48 +43,60 @@ func BenchmarkCounterAddNoAttrs(b *testing.B) { } func BenchmarkCounterAddOneAttr(b *testing.B) { - s := attribute.NewSet(attribute.String("K", "V")) + opt := []instrument.Int64AddOption{ + instrument.WithAttributes(attribute.String("K", "V")), + } ctx, _, cntr := benchCounter(b) for i := 0; i < b.N; i++ { - cntr.Add(ctx, 1, instrument.WithAttributeSet(s)) + cntr.Add(ctx, 1, opt...) } } func BenchmarkCounterAddOneInvalidAttr(b *testing.B) { - s := attribute.NewSet( - attribute.String("", "V"), - attribute.String("K", "V"), - ) + opt := []instrument.Int64AddOption{ + instrument.WithAttributes( + attribute.String("", "V"), + attribute.String("K", "V"), + ), + } ctx, _, cntr := benchCounter(b) for i := 0; i < b.N; i++ { - cntr.Add(ctx, 1, instrument.WithAttributeSet(s)) + cntr.Add(ctx, 1, opt...) } } func BenchmarkCounterAddSingleUseAttrs(b *testing.B) { + attrs := make([]attribute.KeyValue, 1) + opt := make([]instrument.Int64AddOption, 1) ctx, _, cntr := benchCounter(b) for i := 0; i < b.N; i++ { - s := attribute.NewSet(attribute.Int("K", i)) - cntr.Add(ctx, 1, instrument.WithAttributeSet(s)) + attrs[0] = attribute.Int("K", i) + s := attribute.NewSet(attrs...) + opt[0] = instrument.WithAttributeSet(s) + cntr.Add(ctx, 1, opt...) } } func BenchmarkCounterAddSingleUseInvalidAttrs(b *testing.B) { + attrs := make([]attribute.KeyValue, 2) + opt := make([]instrument.Int64AddOption, 1) ctx, _, cntr := benchCounter(b) for i := 0; i < b.N; i++ { - o := instrument.WithAttributes( - attribute.Int("", i), - attribute.Int("K", i), - ) - cntr.Add(ctx, 1, o) + attrs[0] = attribute.Int("", i) + attrs[1] = attribute.Int("K", i) + s := attribute.NewSet(attrs...) + opt[0] = instrument.WithAttributeSet(s) + cntr.Add(ctx, 1, opt...) } } func BenchmarkCounterAddSingleUseFilteredAttrs(b *testing.B) { + attrs := make([]attribute.KeyValue, 2) + opt := make([]instrument.Int64AddOption, 1) ctx, _, cntr := benchCounter(b, NewView( Instrument{Name: "*"}, Stream{AttributeFilter: func(kv attribute.KeyValue) bool { @@ -93,31 +105,38 @@ func BenchmarkCounterAddSingleUseFilteredAttrs(b *testing.B) { )) for i := 0; i < b.N; i++ { - o := instrument.WithAttributes( - attribute.Int("L", i), - attribute.Int("K", i), - ) - cntr.Add(ctx, 1, o) + attrs[0] = attribute.Int("L", i) + attrs[1] = attribute.Int("K", i) + s := attribute.NewSet(attrs...) + opt[0] = instrument.WithAttributeSet(s) + cntr.Add(ctx, 1, opt...) } } func BenchmarkCounterCollectOneAttr(b *testing.B) { - s := attribute.NewSet(attribute.Int("K", 1)) + opt := []instrument.Int64AddOption{ + instrument.WithAttributes(attribute.Int("K", 1)), + } ctx, rdr, cntr := benchCounter(b) for i := 0; i < b.N; i++ { - cntr.Add(ctx, 1, instrument.WithAttributeSet(s)) + cntr.Add(ctx, 1, opt...) _ = rdr.Collect(ctx, nil) } } func BenchmarkCounterCollectTenAttrs(b *testing.B) { + attrs := make([]attribute.KeyValue, 1) + opt := make([]instrument.Int64AddOption, 1) ctx, rdr, cntr := benchCounter(b) for i := 0; i < b.N; i++ { for j := 0; j < 10; j++ { - cntr.Add(ctx, 1, instrument.WithAttributes(attribute.Int("K", j))) + attrs[0] = attribute.Int("K", j) + s := attribute.NewSet(attrs...) + opt[0] = instrument.WithAttributeSet(s) + cntr.Add(ctx, 1, opt...) } _ = rdr.Collect(ctx, nil) } diff --git a/sdk/metric/instrument.go b/sdk/metric/instrument.go index eb90984d31d..fcba16527fc 100644 --- a/sdk/metric/instrument.go +++ b/sdk/metric/instrument.go @@ -183,12 +183,12 @@ var _ instrument.Int64UpDownCounter = (*int64Inst)(nil) var _ instrument.Int64Histogram = (*int64Inst)(nil) func (i *int64Inst) Add(ctx context.Context, val int64, opts ...instrument.Int64AddOption) { - c := instrument.NewInt64AddConfig(opts...) + c := instrument.NewInt64AddConfig(opts) i.aggregate(ctx, val, c.Attributes()) } func (i *int64Inst) Record(ctx context.Context, val int64, opts ...instrument.Int64RecordOption) { - c := instrument.NewInt64RecordConfig(opts...) + c := instrument.NewInt64RecordConfig(opts) i.aggregate(ctx, val, c.Attributes()) } @@ -214,12 +214,12 @@ var _ instrument.Float64UpDownCounter = (*float64Inst)(nil) var _ instrument.Float64Histogram = (*float64Inst)(nil) func (i *float64Inst) Add(ctx context.Context, val float64, opts ...instrument.Float64AddOption) { - c := instrument.NewFloat64AddConfig(opts...) + c := instrument.NewFloat64AddConfig(opts) i.aggregate(ctx, val, c.Attributes()) } func (i *float64Inst) Record(ctx context.Context, val float64, opts ...instrument.Float64RecordOption) { - c := instrument.NewFloat64RecordConfig(opts...) + c := instrument.NewFloat64RecordConfig(opts) i.aggregate(ctx, val, c.Attributes()) } diff --git a/sdk/metric/meter.go b/sdk/metric/meter.go index 1f656a73cf2..1c156eb57a5 100644 --- a/sdk/metric/meter.go +++ b/sdk/metric/meter.go @@ -325,7 +325,7 @@ func (r observer) ObserveFloat64(o instrument.Float64Observable, v float64, opts ) return } - c := instrument.NewFloat64ObserveConfig(opts...) + c := instrument.NewFloat64ObserveConfig(opts) oImpl.observe(v, c.Attributes()) } @@ -358,7 +358,7 @@ func (r observer) ObserveInt64(o instrument.Int64Observable, v int64, opts ...in ) return } - c := instrument.NewInt64ObserveConfig(opts...) + c := instrument.NewInt64ObserveConfig(opts) oImpl.observe(v, c.Attributes()) } @@ -453,7 +453,7 @@ type int64Observer struct { } func (o int64Observer) Observe(val int64, opts ...instrument.Int64ObserveOption) { - c := instrument.NewInt64ObserveConfig(opts...) + c := instrument.NewInt64ObserveConfig(opts) o.observe(val, c.Attributes()) } @@ -486,6 +486,6 @@ type float64Observer struct { } func (o float64Observer) Observe(val float64, opts ...instrument.Float64ObserveOption) { - c := instrument.NewFloat64ObserveConfig(opts...) + c := instrument.NewFloat64ObserveConfig(opts) o.observe(val, c.Attributes()) } From 7ceec02ccb41725583888936c2b1fe8d816d040b Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Mon, 10 Apr 2023 13:49:06 -0700 Subject: [PATCH 11/16] Clarify WithAttributes performance in docs --- metric/instrument/instrument.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/metric/instrument/instrument.go b/metric/instrument/instrument.go index d9daf20ca50..fc32cc758e8 100644 --- a/metric/instrument/instrument.go +++ b/metric/instrument/instrument.go @@ -433,9 +433,18 @@ func WithAttributeSet(attributes attribute.Set) MeasurementOption { // WithAttributeSet converts attributes into an attribute Set and sets the Set // to be associated with a measurement. This is shorthand for: // -// WithAttributes(attribute.NewSet(attributes...)) +// cp := make([]attribute.KeyValue, len(attributes)) +// copy(cp, attributes) +// WithAttributes(attribute.NewSet(cp...)) // -// See [WithAttributeSet] for how multiple WithAttributes are merged. +// [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]. That option function should be perfered +// 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) From f236ac0c97866a82bbdb30d32faa915d2c95aee3 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Tue, 11 Apr 2023 13:19:20 -0700 Subject: [PATCH 12/16] Address feedback about WithAttributes comment --- metric/instrument/instrument.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/metric/instrument/instrument.go b/metric/instrument/instrument.go index fc32cc758e8..988d5b16a33 100644 --- a/metric/instrument/instrument.go +++ b/metric/instrument/instrument.go @@ -430,18 +430,18 @@ func WithAttributeSet(attributes attribute.Set) MeasurementOption { return attrOpt{set: attributes} } -// WithAttributeSet converts attributes into an attribute Set and sets the Set -// to be associated with a measurement. This is shorthand for: +// 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) // WithAttributes(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 +// [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]. That option function should be perfered -// for performance sensitive code. +// comparison to [WithAttributeSet]. Therefore, [WithAttributeSet] should be +// preferred for performance sensitive code. // // See [WithAttributeSet] for information about how multiple WithAttributes are // merged. From 53d3d50d8e3d7fc89a1e8fd153b228477ae2880f Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Tue, 11 Apr 2023 13:21:35 -0700 Subject: [PATCH 13/16] Add changelog entry for WithAttribute{s,Set} --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf6d401f2c1..3fe5a1f332c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - The `Float64ObserveConfig` used to hold configuration for `float64` observed measurements - `NewFloat64ObserveConfig` used to create a new `Float64ObserveConfig` - `Float64ObserveOption` used to configure an `Float64ObserveConfig` +- `WithAttributeSet` and `WithAttributes` are added to `go.opentelemetry.io/otel/metric/instrument`. + They return an option used during a measurement that defines the attribute Set associated with the measurement. (#3971) - The `Version` function to `go.opentelemetry.io/otel/exporters/otlp/otlpmetric` to return the OTLP metrics client version. (#3956) - The `Version` function to `go.opentelemetry.io/otel/exporters/otlp/otlptrace` to return the OTLP trace client version. (#3956) From 147b8f2f3c5507683c2dc12f89d9bc267048c709 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Thu, 13 Apr 2023 12:32:38 -0700 Subject: [PATCH 14/16] Remove number scope from measure opts --- metric/instrument/asyncfloat64.go | 2 +- metric/instrument/asyncfloat64_test.go | 2 +- metric/instrument/asyncint64.go | 2 +- metric/instrument/asyncint64_test.go | 2 +- metric/instrument/instrument.go | 198 ++++-------------- metric/instrument/instrument_test.go | 66 +++--- metric/instrument/syncfloat64.go | 6 +- metric/instrument/syncint64.go | 6 +- metric/internal/global/instruments.go | 12 +- metric/internal/global/instruments_test.go | 8 +- metric/internal/global/meter_types_test.go | 4 +- metric/meter.go | 4 +- metric/noop/noop.go | 20 +- sdk/metric/benchmark_test.go | 14 +- sdk/metric/instrument.go | 16 +- .../internal/aggregator_example_test.go | 4 +- sdk/metric/meter.go | 16 +- 17 files changed, 131 insertions(+), 251 deletions(-) diff --git a/metric/instrument/asyncfloat64.go b/metric/instrument/asyncfloat64.go index b16fcebc14e..5aaac43a7aa 100644 --- a/metric/instrument/asyncfloat64.go +++ b/metric/instrument/asyncfloat64.go @@ -207,7 +207,7 @@ type Float64Observer interface { embedded.Float64Observer // Observe records the float64 value. - Observe(value float64, opts ...Float64ObserveOption) + Observe(value float64, opts ...ObserveOption) } // Float64Callback is a function registered with a Meter that makes diff --git a/metric/instrument/asyncfloat64_test.go b/metric/instrument/asyncfloat64_test.go index 6b8f6dd551c..73be71d1dc9 100644 --- a/metric/instrument/asyncfloat64_test.go +++ b/metric/instrument/asyncfloat64_test.go @@ -88,6 +88,6 @@ type float64Observer struct { got float64 } -func (o *float64Observer) Observe(v float64, _ ...Float64ObserveOption) { +func (o *float64Observer) Observe(v float64, _ ...ObserveOption) { o.got = v } diff --git a/metric/instrument/asyncint64.go b/metric/instrument/asyncint64.go index f51a9961b78..e9027b4b480 100644 --- a/metric/instrument/asyncint64.go +++ b/metric/instrument/asyncint64.go @@ -206,7 +206,7 @@ type Int64Observer interface { embedded.Int64Observer // Observe records the int64 value. - Observe(value int64, opts ...Int64ObserveOption) + Observe(value int64, opts ...ObserveOption) } // Int64Callback is a function registered with a Meter that makes observations diff --git a/metric/instrument/asyncint64_test.go b/metric/instrument/asyncint64_test.go index e4a3f682faa..2b7bc91c003 100644 --- a/metric/instrument/asyncint64_test.go +++ b/metric/instrument/asyncint64_test.go @@ -88,6 +88,6 @@ type int64Observer struct { got int64 } -func (o *int64Observer) Observe(v int64, _ ...Int64ObserveOption) { +func (o *int64Observer) Observe(v int64, _ ...ObserveOption) { o.got = v } diff --git a/metric/instrument/instrument.go b/metric/instrument/instrument.go index 988d5b16a33..cb0373c16e5 100644 --- a/metric/instrument/instrument.go +++ b/metric/instrument/instrument.go @@ -169,173 +169,86 @@ func (o unitOpt) applyInt64ObservableGauge(c Int64ObservableGaugeConfig) Int64Ob // WithUnit sets the instrument unit. func WithUnit(u string) Option { return unitOpt(u) } -// Int64AddOption applies options to an addition measurement. See -// [MeasurementOption] for other options that can be used as a Int64AddOption. -type Int64AddOption interface { - applyInt64Add(Int64AddConfig) Int64AddConfig +// AddOption applies options to an addition measurement. See +// [MeasurementOption] for other options that can be used as a AddOption. +type AddOption interface { + applyAdd(AddConfig) AddConfig } -// Int64AddConfig contains options for an int64 addition measurement. -type Int64AddConfig struct { +// AddConfig contains options for an addition measurement. +type AddConfig struct { attrs attribute.Set } -// NewInt64AddConfig returns a new [Int64AddConfig] with all opts applied. -func NewInt64AddConfig(opts []Int64AddOption) Int64AddConfig { - config := Int64AddConfig{attrs: *attribute.EmptySet()} +// NewAddConfig returns a new [AddConfig] with all opts applied. +func NewAddConfig(opts []AddOption) AddConfig { + config := AddConfig{attrs: *attribute.EmptySet()} for _, o := range opts { - config = o.applyInt64Add(config) + config = o.applyAdd(config) } return config } // Attributes returns the configured attribute set. -func (c Int64AddConfig) Attributes() attribute.Set { +func (c AddConfig) Attributes() attribute.Set { return c.attrs } -// Float64AddOption applies options to an addition measurement. See -// [MeasurementOption] for other options that can be used as a -// Float64AddOption. -type Float64AddOption interface { - applyFloat64Add(Float64AddConfig) Float64AddConfig +// 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 } -// Float64AddConfig contains options for an float64 addition measurement. -type Float64AddConfig struct { +// RecordConfig contains options for a recorded measurement. +type RecordConfig struct { attrs attribute.Set } -// NewFloat64AddConfig returns a new [Float64AddConfig] with all opts applied. -func NewFloat64AddConfig(opts []Float64AddOption) Float64AddConfig { - config := Float64AddConfig{attrs: *attribute.EmptySet()} +// NewRecordConfig returns a new [RecordConfig] with all opts applied. +func NewRecordConfig(opts []RecordOption) RecordConfig { + config := RecordConfig{attrs: *attribute.EmptySet()} for _, o := range opts { - config = o.applyFloat64Add(config) + config = o.applyRecord(config) } return config } // Attributes returns the configured attribute set. -func (c Float64AddConfig) Attributes() attribute.Set { +func (c RecordConfig) Attributes() attribute.Set { return c.attrs } -// Int64RecordOption applies options to an addition measurement. See -// [MeasurementOption] for other options that can be used as a -// Int64RecordOption. -type Int64RecordOption interface { - applyInt64Record(Int64RecordConfig) Int64RecordConfig +// 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 } -// Int64RecordConfig contains options for an int64 recorded measurement. -type Int64RecordConfig struct { +// ObserveConfig contains options for an observed measurement. +type ObserveConfig struct { attrs attribute.Set } -// NewInt64RecordConfig returns a new [Int64RecordConfig] with all opts -// applied. -func NewInt64RecordConfig(opts []Int64RecordOption) Int64RecordConfig { - config := Int64RecordConfig{attrs: *attribute.EmptySet()} +// NewObserveConfig returns a new [ObserveConfig] with all opts applied. +func NewObserveConfig(opts []ObserveOption) ObserveConfig { + config := ObserveConfig{attrs: *attribute.EmptySet()} for _, o := range opts { - config = o.applyInt64Record(config) + config = o.applyObserve(config) } return config } // Attributes returns the configured attribute set. -func (c Int64RecordConfig) Attributes() attribute.Set { - return c.attrs -} - -// Float64RecordOption applies options to an addition measurement. See -// [MeasurementOption] for other options that can be used as a -// Float64RecordOption. -type Float64RecordOption interface { - applyFloat64Record(Float64RecordConfig) Float64RecordConfig -} - -// Float64RecordConfig contains options for an float64 recorded measurement. -type Float64RecordConfig struct { - attrs attribute.Set -} - -// NewFloat64RecordConfig returns a new [Float64RecordConfig] with all opts -// applied. -func NewFloat64RecordConfig(opts []Float64RecordOption) Float64RecordConfig { - config := Float64RecordConfig{attrs: *attribute.EmptySet()} - for _, o := range opts { - config = o.applyFloat64Record(config) - } - return config -} - -// Attributes returns the configured attribute set. -func (c Float64RecordConfig) Attributes() attribute.Set { - return c.attrs -} - -// Int64ObserveOption applies options to an addition measurement. See -// [MeasurementOption] for other options that can be used as a -// Int64ObserveOption. -type Int64ObserveOption interface { - applyInt64Observe(Int64ObserveConfig) Int64ObserveConfig -} - -// Int64ObserveConfig contains options for an int64 observed measurement. -type Int64ObserveConfig struct { - attrs attribute.Set -} - -// NewInt64ObserveConfig returns a new [Int64ObserveConfig] with all opts -// applied. -func NewInt64ObserveConfig(opts []Int64ObserveOption) Int64ObserveConfig { - config := Int64ObserveConfig{attrs: *attribute.EmptySet()} - for _, o := range opts { - config = o.applyInt64Observe(config) - } - return config -} - -// Attributes returns the configured attribute set. -func (c Int64ObserveConfig) Attributes() attribute.Set { - return c.attrs -} - -// Float64ObserveOption applies options to an addition measurement. See -// [MeasurementOption] for other options that can be used as a -// Float64ObserveOption. -type Float64ObserveOption interface { - applyFloat64Observe(Float64ObserveConfig) Float64ObserveConfig -} - -// Float64ObserveConfig contains options for an float64 observed measurement. -type Float64ObserveConfig struct { - attrs attribute.Set -} - -// NewFloat64ObserveConfig returns a new [Float64ObserveConfig] with all opts -// applied. -func NewFloat64ObserveConfig(opts []Float64ObserveOption) Float64ObserveConfig { - config := Float64ObserveConfig{attrs: *attribute.EmptySet()} - for _, o := range opts { - config = o.applyFloat64Observe(config) - } - return config -} - -// Attributes returns the configured attribute set. -func (c Float64ObserveConfig) Attributes() attribute.Set { +func (c ObserveConfig) Attributes() attribute.Set { return c.attrs } // MeasurementOption applies options to all instrument measurement. type MeasurementOption interface { - Int64AddOption - Float64AddOption - Int64RecordOption - Float64RecordOption - Int64ObserveOption - Float64ObserveOption + AddOption + RecordOption + ObserveOption } type attrOpt struct { @@ -354,40 +267,7 @@ func mergeSets(a, b attribute.Set) attribute.Set { return attribute.NewSet(merged...) } -func (o attrOpt) applyInt64Add(c Int64AddConfig) Int64AddConfig { - 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) applyFloat64Add(c Float64AddConfig) Float64AddConfig { - 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) applyInt64Record(c Int64RecordConfig) Int64RecordConfig { - 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) applyFloat64Record(c Float64RecordConfig) Float64RecordConfig { +func (o attrOpt) applyAdd(c AddConfig) AddConfig { switch { case o.set.Len() == 0: case c.attrs.Len() == 0: @@ -398,7 +278,7 @@ func (o attrOpt) applyFloat64Record(c Float64RecordConfig) Float64RecordConfig { return c } -func (o attrOpt) applyInt64Observe(c Int64ObserveConfig) Int64ObserveConfig { +func (o attrOpt) applyRecord(c RecordConfig) RecordConfig { switch { case o.set.Len() == 0: case c.attrs.Len() == 0: @@ -409,7 +289,7 @@ func (o attrOpt) applyInt64Observe(c Int64ObserveConfig) Int64ObserveConfig { return c } -func (o attrOpt) applyFloat64Observe(c Float64ObserveConfig) Float64ObserveConfig { +func (o attrOpt) applyObserve(c ObserveConfig) ObserveConfig { switch { case o.set.Len() == 0: case c.attrs.Len() == 0: diff --git a/metric/instrument/instrument_test.go b/metric/instrument/instrument_test.go index a3965266b3c..19ef98ccb84 100644 --- a/metric/instrument/instrument_test.go +++ b/metric/instrument/instrument_test.go @@ -28,52 +28,52 @@ type attrConf interface { } func TestConfigAttrs(t *testing.T) { - t.Run("Float64AddConfig", testConfAttr(func(mo ...MeasurementOption) attrConf { - opts := make([]Float64AddOption, len(mo)) + t.Run("AddConfig", testConfAttr(func(mo ...MeasurementOption) attrConf { + opts := make([]AddOption, len(mo)) for i := range mo { - opts[i] = mo[i].(Float64AddOption) + opts[i] = mo[i].(AddOption) } - return NewFloat64AddConfig(opts) + return NewAddConfig(opts) })) t.Run("Int64AddConfig", testConfAttr(func(mo ...MeasurementOption) attrConf { - opts := make([]Int64AddOption, len(mo)) + opts := make([]AddOption, len(mo)) for i := range mo { - opts[i] = mo[i].(Int64AddOption) + opts[i] = mo[i].(AddOption) } - return NewInt64AddConfig(opts) + return NewAddConfig(opts) })) - t.Run("Float64RecordConfig", testConfAttr(func(mo ...MeasurementOption) attrConf { - opts := make([]Float64RecordOption, len(mo)) + t.Run("RecordConfig", testConfAttr(func(mo ...MeasurementOption) attrConf { + opts := make([]RecordOption, len(mo)) for i := range mo { - opts[i] = mo[i].(Float64RecordOption) + opts[i] = mo[i].(RecordOption) } - return NewFloat64RecordConfig(opts) + return NewRecordConfig(opts) })) t.Run("Int64RecordConfig", testConfAttr(func(mo ...MeasurementOption) attrConf { - opts := make([]Int64RecordOption, len(mo)) + opts := make([]RecordOption, len(mo)) for i := range mo { - opts[i] = mo[i].(Int64RecordOption) + opts[i] = mo[i].(RecordOption) } - return NewInt64RecordConfig(opts) + return NewRecordConfig(opts) })) - t.Run("Float64ObserveConfig", testConfAttr(func(mo ...MeasurementOption) attrConf { - opts := make([]Float64ObserveOption, len(mo)) + t.Run("ObserveConfig", testConfAttr(func(mo ...MeasurementOption) attrConf { + opts := make([]ObserveOption, len(mo)) for i := range mo { - opts[i] = mo[i].(Float64ObserveOption) + opts[i] = mo[i].(ObserveOption) } - return NewFloat64ObserveConfig(opts) + return NewObserveConfig(opts) })) t.Run("Int64ObserveConfig", testConfAttr(func(mo ...MeasurementOption) attrConf { - opts := make([]Int64ObserveOption, len(mo)) + opts := make([]ObserveOption, len(mo)) for i := range mo { - opts[i] = mo[i].(Int64ObserveOption) + opts[i] = mo[i].(ObserveOption) } - return NewInt64ObserveConfig(opts) + return NewObserveConfig(opts) })) } @@ -136,40 +136,40 @@ func TestWithAttributesRace(t *testing.T) { wg.Add(1) go func() { defer wg.Done() - opt := []Int64AddOption{WithAttributes(attrs...)} - _ = NewInt64AddConfig(opt) + opt := []AddOption{WithAttributes(attrs...)} + _ = NewAddConfig(opt) }() wg.Add(1) go func() { defer wg.Done() - opt := []Float64AddOption{WithAttributes(attrs...)} - _ = NewFloat64AddConfig(opt) + opt := []AddOption{WithAttributes(attrs...)} + _ = NewAddConfig(opt) }() wg.Add(1) go func() { defer wg.Done() - opt := []Int64RecordOption{WithAttributes(attrs...)} - _ = NewInt64RecordConfig(opt) + opt := []RecordOption{WithAttributes(attrs...)} + _ = NewRecordConfig(opt) }() wg.Add(1) go func() { defer wg.Done() - opt := []Float64RecordOption{WithAttributes(attrs...)} - _ = NewFloat64RecordConfig(opt) + opt := []RecordOption{WithAttributes(attrs...)} + _ = NewRecordConfig(opt) }() wg.Add(1) go func() { defer wg.Done() - opt := []Int64ObserveOption{WithAttributes(attrs...)} - _ = NewInt64ObserveConfig(opt) + opt := []ObserveOption{WithAttributes(attrs...)} + _ = NewObserveConfig(opt) }() wg.Add(1) go func() { defer wg.Done() - opt := []Float64ObserveOption{WithAttributes(attrs...)} - _ = NewFloat64ObserveConfig(opt) + opt := []ObserveOption{WithAttributes(attrs...)} + _ = NewObserveConfig(opt) }() wg.Wait() diff --git a/metric/instrument/syncfloat64.go b/metric/instrument/syncfloat64.go index d2be2c7a284..2399f83637e 100644 --- a/metric/instrument/syncfloat64.go +++ b/metric/instrument/syncfloat64.go @@ -30,7 +30,7 @@ type Float64Counter interface { embedded.Float64Counter // Add records a change to the counter. - Add(ctx context.Context, incr float64, opts ...Float64AddOption) + Add(ctx context.Context, incr float64, opts ...AddOption) } // Float64CounterConfig contains options for synchronous counter instruments that @@ -77,7 +77,7 @@ type Float64UpDownCounter interface { embedded.Float64UpDownCounter // Add records a change to the counter. - Add(ctx context.Context, incr float64, opts ...Float64AddOption) + Add(ctx context.Context, incr float64, opts ...AddOption) } // Float64UpDownCounterConfig contains options for synchronous counter @@ -125,7 +125,7 @@ type Float64Histogram interface { embedded.Float64Histogram // Record adds an additional value to the distribution. - Record(ctx context.Context, incr float64, opts ...Float64RecordOption) + Record(ctx context.Context, incr float64, opts ...RecordOption) } // Float64HistogramConfig contains options for synchronous counter instruments diff --git a/metric/instrument/syncint64.go b/metric/instrument/syncint64.go index 1eeb1a26d86..53d1c5b6c0a 100644 --- a/metric/instrument/syncint64.go +++ b/metric/instrument/syncint64.go @@ -30,7 +30,7 @@ type Int64Counter interface { embedded.Int64Counter // Add records a change to the counter. - Add(ctx context.Context, incr int64, opts ...Int64AddOption) + Add(ctx context.Context, incr int64, opts ...AddOption) } // Int64CounterConfig contains options for synchronous counter instruments that @@ -77,7 +77,7 @@ type Int64UpDownCounter interface { embedded.Int64UpDownCounter // Add records a change to the counter. - Add(ctx context.Context, incr int64, opts ...Int64AddOption) + Add(ctx context.Context, incr int64, opts ...AddOption) } // Int64UpDownCounterConfig contains options for synchronous counter @@ -125,7 +125,7 @@ type Int64Histogram interface { embedded.Int64Histogram // Record adds an additional value to the distribution. - Record(ctx context.Context, incr int64, opts ...Int64RecordOption) + Record(ctx context.Context, incr int64, opts ...RecordOption) } // Int64HistogramConfig contains options for synchronous counter instruments diff --git a/metric/internal/global/instruments.go b/metric/internal/global/instruments.go index dced0d691ef..79dd446630a 100644 --- a/metric/internal/global/instruments.go +++ b/metric/internal/global/instruments.go @@ -224,7 +224,7 @@ func (i *sfCounter) setDelegate(m metric.Meter) { i.delegate.Store(ctr) } -func (i *sfCounter) Add(ctx context.Context, incr float64, opts ...instrument.Float64AddOption) { +func (i *sfCounter) Add(ctx context.Context, incr float64, opts ...instrument.AddOption) { if ctr := i.delegate.Load(); ctr != nil { ctr.(instrument.Float64Counter).Add(ctx, incr, opts...) } @@ -250,7 +250,7 @@ func (i *sfUpDownCounter) setDelegate(m metric.Meter) { i.delegate.Store(ctr) } -func (i *sfUpDownCounter) Add(ctx context.Context, incr float64, opts ...instrument.Float64AddOption) { +func (i *sfUpDownCounter) Add(ctx context.Context, incr float64, opts ...instrument.AddOption) { if ctr := i.delegate.Load(); ctr != nil { ctr.(instrument.Float64UpDownCounter).Add(ctx, incr, opts...) } @@ -276,7 +276,7 @@ func (i *sfHistogram) setDelegate(m metric.Meter) { i.delegate.Store(ctr) } -func (i *sfHistogram) Record(ctx context.Context, x float64, opts ...instrument.Float64RecordOption) { +func (i *sfHistogram) Record(ctx context.Context, x float64, opts ...instrument.RecordOption) { if ctr := i.delegate.Load(); ctr != nil { ctr.(instrument.Float64Histogram).Record(ctx, x, opts...) } @@ -302,7 +302,7 @@ func (i *siCounter) setDelegate(m metric.Meter) { i.delegate.Store(ctr) } -func (i *siCounter) Add(ctx context.Context, x int64, opts ...instrument.Int64AddOption) { +func (i *siCounter) Add(ctx context.Context, x int64, opts ...instrument.AddOption) { if ctr := i.delegate.Load(); ctr != nil { ctr.(instrument.Int64Counter).Add(ctx, x, opts...) } @@ -328,7 +328,7 @@ func (i *siUpDownCounter) setDelegate(m metric.Meter) { i.delegate.Store(ctr) } -func (i *siUpDownCounter) Add(ctx context.Context, x int64, opts ...instrument.Int64AddOption) { +func (i *siUpDownCounter) Add(ctx context.Context, x int64, opts ...instrument.AddOption) { if ctr := i.delegate.Load(); ctr != nil { ctr.(instrument.Int64UpDownCounter).Add(ctx, x, opts...) } @@ -354,7 +354,7 @@ func (i *siHistogram) setDelegate(m metric.Meter) { i.delegate.Store(ctr) } -func (i *siHistogram) Record(ctx context.Context, x int64, opts ...instrument.Int64RecordOption) { +func (i *siHistogram) Record(ctx context.Context, x int64, opts ...instrument.RecordOption) { if ctr := i.delegate.Load(); ctr != nil { ctr.(instrument.Int64Histogram).Record(ctx, x, opts...) } diff --git a/metric/internal/global/instruments_test.go b/metric/internal/global/instruments_test.go index 358617679df..ce78cfb1252 100644 --- a/metric/internal/global/instruments_test.go +++ b/metric/internal/global/instruments_test.go @@ -163,10 +163,10 @@ type testCountingFloatInstrument struct { func (i *testCountingFloatInstrument) observe() { i.count++ } -func (i *testCountingFloatInstrument) Add(context.Context, float64, ...instrument.Float64AddOption) { +func (i *testCountingFloatInstrument) Add(context.Context, float64, ...instrument.AddOption) { i.count++ } -func (i *testCountingFloatInstrument) Record(context.Context, float64, ...instrument.Float64RecordOption) { +func (i *testCountingFloatInstrument) Record(context.Context, float64, ...instrument.RecordOption) { i.count++ } @@ -185,9 +185,9 @@ type testCountingIntInstrument struct { func (i *testCountingIntInstrument) observe() { i.count++ } -func (i *testCountingIntInstrument) Add(context.Context, int64, ...instrument.Int64AddOption) { +func (i *testCountingIntInstrument) Add(context.Context, int64, ...instrument.AddOption) { i.count++ } -func (i *testCountingIntInstrument) Record(context.Context, int64, ...instrument.Int64RecordOption) { +func (i *testCountingIntInstrument) Record(context.Context, int64, ...instrument.RecordOption) { i.count++ } diff --git a/metric/internal/global/meter_types_test.go b/metric/internal/global/meter_types_test.go index 2bc91d1da40..45de7ca4dbb 100644 --- a/metric/internal/global/meter_types_test.go +++ b/metric/internal/global/meter_types_test.go @@ -156,14 +156,14 @@ type observationRecorder struct { ctx context.Context } -func (o observationRecorder) ObserveFloat64(i instrument.Float64Observable, value float64, _ ...instrument.Float64ObserveOption) { +func (o observationRecorder) ObserveFloat64(i instrument.Float64Observable, value float64, _ ...instrument.ObserveOption) { iImpl, ok := i.(*testCountingFloatInstrument) if ok { iImpl.observe() } } -func (o observationRecorder) ObserveInt64(i instrument.Int64Observable, value int64, _ ...instrument.Int64ObserveOption) { +func (o observationRecorder) ObserveInt64(i instrument.Int64Observable, value int64, _ ...instrument.ObserveOption) { iImpl, ok := i.(*testCountingIntInstrument) if ok { iImpl.observe() diff --git a/metric/meter.go b/metric/meter.go index f95a7f1fb20..0f77cde8d7e 100644 --- a/metric/meter.go +++ b/metric/meter.go @@ -141,9 +141,9 @@ type Observer interface { embedded.Observer // ObserveFloat64 records the float64 value for obsrv. - ObserveFloat64(obsrv instrument.Float64Observable, value float64, opts ...instrument.Float64ObserveOption) + ObserveFloat64(obsrv instrument.Float64Observable, value float64, opts ...instrument.ObserveOption) // ObserveInt64 records the int64 value for obsrv. - ObserveInt64(obsrv instrument.Int64Observable, value int64, opts ...instrument.Int64ObserveOption) + ObserveInt64(obsrv instrument.Int64Observable, value int64, opts ...instrument.ObserveOption) } // Registration is an token representing the unique registration of a callback diff --git a/metric/noop/noop.go b/metric/noop/noop.go index b786cdca1ce..683f3e1c84c 100644 --- a/metric/noop/noop.go +++ b/metric/noop/noop.go @@ -152,11 +152,11 @@ func (Meter) RegisterCallback(metric.Callback, ...instrument.Observable) (metric type Observer struct{ embedded.Observer } // ObserveFloat64 performs no operation. -func (Observer) ObserveFloat64(instrument.Float64Observable, float64, ...instrument.Float64ObserveOption) { +func (Observer) ObserveFloat64(instrument.Float64Observable, float64, ...instrument.ObserveOption) { } // ObserveInt64 performs no operation. -func (Observer) ObserveInt64(instrument.Int64Observable, int64, ...instrument.Int64ObserveOption) { +func (Observer) ObserveInt64(instrument.Int64Observable, int64, ...instrument.ObserveOption) { } // Registration is the registration of a Callback with a No-Op Meter. @@ -172,42 +172,42 @@ func (Registration) Unregister() error { return nil } type Int64Counter struct{ embedded.Int64Counter } // Add performs no operation. -func (Int64Counter) Add(context.Context, int64, ...instrument.Int64AddOption) {} +func (Int64Counter) Add(context.Context, int64, ...instrument.AddOption) {} // Float64Counter is an OpenTelemetry Counter used to record float64 // measurements. It produces no telemetry. type Float64Counter struct{ embedded.Float64Counter } // Add performs no operation. -func (Float64Counter) Add(context.Context, float64, ...instrument.Float64AddOption) {} +func (Float64Counter) Add(context.Context, float64, ...instrument.AddOption) {} // Int64UpDownCounter is an OpenTelemetry UpDownCounter used to record int64 // measurements. It produces no telemetry. type Int64UpDownCounter struct{ embedded.Int64UpDownCounter } // Add performs no operation. -func (Int64UpDownCounter) Add(context.Context, int64, ...instrument.Int64AddOption) {} +func (Int64UpDownCounter) Add(context.Context, int64, ...instrument.AddOption) {} // Float64UpDownCounter is an OpenTelemetry UpDownCounter used to record // float64 measurements. It produces no telemetry. type Float64UpDownCounter struct{ embedded.Float64UpDownCounter } // Add performs no operation. -func (Float64UpDownCounter) Add(context.Context, float64, ...instrument.Float64AddOption) {} +func (Float64UpDownCounter) Add(context.Context, float64, ...instrument.AddOption) {} // Int64Histogram is an OpenTelemetry Histogram used to record int64 // measurements. It produces no telemetry. type Int64Histogram struct{ embedded.Int64Histogram } // Record performs no operation. -func (Int64Histogram) Record(context.Context, int64, ...instrument.Int64RecordOption) {} +func (Int64Histogram) Record(context.Context, int64, ...instrument.RecordOption) {} // Float64Histogram is an OpenTelemetry Histogram used to record float64 // measurements. It produces no telemetry. type Float64Histogram struct{ embedded.Float64Histogram } // Record performs no operation. -func (Float64Histogram) Record(context.Context, float64, ...instrument.Float64RecordOption) {} +func (Float64Histogram) Record(context.Context, float64, ...instrument.RecordOption) {} // Int64ObservableCounter is an OpenTelemetry ObservableCounter used to record // int64 measurements. It produces no telemetry. @@ -255,11 +255,11 @@ type Float64ObservableUpDownCounter struct { type Int64Observer struct{ embedded.Int64Observer } // Observe performs no operation. -func (Int64Observer) Observe(int64, ...instrument.Int64ObserveOption) {} +func (Int64Observer) Observe(int64, ...instrument.ObserveOption) {} // Float64Observer is a recorder of float64 measurements that performs no // operation. type Float64Observer struct{ embedded.Float64Observer } // Observe performs no operation. -func (Float64Observer) Observe(float64, ...instrument.Float64ObserveOption) {} +func (Float64Observer) Observe(float64, ...instrument.ObserveOption) {} diff --git a/sdk/metric/benchmark_test.go b/sdk/metric/benchmark_test.go index 933c5de0715..b39783e3ce8 100644 --- a/sdk/metric/benchmark_test.go +++ b/sdk/metric/benchmark_test.go @@ -43,7 +43,7 @@ func BenchmarkCounterAddNoAttrs(b *testing.B) { } func BenchmarkCounterAddOneAttr(b *testing.B) { - opt := []instrument.Int64AddOption{ + opt := []instrument.AddOption{ instrument.WithAttributes(attribute.String("K", "V")), } ctx, _, cntr := benchCounter(b) @@ -54,7 +54,7 @@ func BenchmarkCounterAddOneAttr(b *testing.B) { } func BenchmarkCounterAddOneInvalidAttr(b *testing.B) { - opt := []instrument.Int64AddOption{ + opt := []instrument.AddOption{ instrument.WithAttributes( attribute.String("", "V"), attribute.String("K", "V"), @@ -69,7 +69,7 @@ func BenchmarkCounterAddOneInvalidAttr(b *testing.B) { func BenchmarkCounterAddSingleUseAttrs(b *testing.B) { attrs := make([]attribute.KeyValue, 1) - opt := make([]instrument.Int64AddOption, 1) + opt := make([]instrument.AddOption, 1) ctx, _, cntr := benchCounter(b) for i := 0; i < b.N; i++ { @@ -82,7 +82,7 @@ func BenchmarkCounterAddSingleUseAttrs(b *testing.B) { func BenchmarkCounterAddSingleUseInvalidAttrs(b *testing.B) { attrs := make([]attribute.KeyValue, 2) - opt := make([]instrument.Int64AddOption, 1) + opt := make([]instrument.AddOption, 1) ctx, _, cntr := benchCounter(b) for i := 0; i < b.N; i++ { @@ -96,7 +96,7 @@ func BenchmarkCounterAddSingleUseInvalidAttrs(b *testing.B) { func BenchmarkCounterAddSingleUseFilteredAttrs(b *testing.B) { attrs := make([]attribute.KeyValue, 2) - opt := make([]instrument.Int64AddOption, 1) + opt := make([]instrument.AddOption, 1) ctx, _, cntr := benchCounter(b, NewView( Instrument{Name: "*"}, Stream{AttributeFilter: func(kv attribute.KeyValue) bool { @@ -114,7 +114,7 @@ func BenchmarkCounterAddSingleUseFilteredAttrs(b *testing.B) { } func BenchmarkCounterCollectOneAttr(b *testing.B) { - opt := []instrument.Int64AddOption{ + opt := []instrument.AddOption{ instrument.WithAttributes(attribute.Int("K", 1)), } ctx, rdr, cntr := benchCounter(b) @@ -128,7 +128,7 @@ func BenchmarkCounterCollectOneAttr(b *testing.B) { func BenchmarkCounterCollectTenAttrs(b *testing.B) { attrs := make([]attribute.KeyValue, 1) - opt := make([]instrument.Int64AddOption, 1) + opt := make([]instrument.AddOption, 1) ctx, rdr, cntr := benchCounter(b) for i := 0; i < b.N; i++ { diff --git a/sdk/metric/instrument.go b/sdk/metric/instrument.go index 8d652fe54ea..b4eb05a1606 100644 --- a/sdk/metric/instrument.go +++ b/sdk/metric/instrument.go @@ -182,13 +182,13 @@ var _ instrument.Int64Counter = (*int64Inst)(nil) var _ instrument.Int64UpDownCounter = (*int64Inst)(nil) var _ instrument.Int64Histogram = (*int64Inst)(nil) -func (i *int64Inst) Add(ctx context.Context, val int64, opts ...instrument.Int64AddOption) { - c := instrument.NewInt64AddConfig(opts) +func (i *int64Inst) Add(ctx context.Context, val int64, opts ...instrument.AddOption) { + c := instrument.NewAddConfig(opts) i.aggregate(ctx, val, c.Attributes()) } -func (i *int64Inst) Record(ctx context.Context, val int64, opts ...instrument.Int64RecordOption) { - c := instrument.NewInt64RecordConfig(opts) +func (i *int64Inst) Record(ctx context.Context, val int64, opts ...instrument.RecordOption) { + c := instrument.NewRecordConfig(opts) i.aggregate(ctx, val, c.Attributes()) } @@ -213,13 +213,13 @@ var _ instrument.Float64Counter = (*float64Inst)(nil) var _ instrument.Float64UpDownCounter = (*float64Inst)(nil) var _ instrument.Float64Histogram = (*float64Inst)(nil) -func (i *float64Inst) Add(ctx context.Context, val float64, opts ...instrument.Float64AddOption) { - c := instrument.NewFloat64AddConfig(opts) +func (i *float64Inst) Add(ctx context.Context, val float64, opts ...instrument.AddOption) { + c := instrument.NewAddConfig(opts) i.aggregate(ctx, val, c.Attributes()) } -func (i *float64Inst) Record(ctx context.Context, val float64, opts ...instrument.Float64RecordOption) { - c := instrument.NewFloat64RecordConfig(opts) +func (i *float64Inst) Record(ctx context.Context, val float64, opts ...instrument.RecordOption) { + c := instrument.NewRecordConfig(opts) i.aggregate(ctx, val, c.Attributes()) } diff --git a/sdk/metric/internal/aggregator_example_test.go b/sdk/metric/internal/aggregator_example_test.go index 952dd5c6309..f36d8262c5e 100644 --- a/sdk/metric/internal/aggregator_example_test.go +++ b/sdk/metric/internal/aggregator_example_test.go @@ -94,8 +94,8 @@ type inst struct { embedded.Int64Histogram } -func (inst) Add(context.Context, int64, ...instrument.Int64AddOption) {} -func (inst) Record(context.Context, int64, ...instrument.Int64RecordOption) {} +func (inst) Add(context.Context, int64, ...instrument.AddOption) {} +func (inst) Record(context.Context, int64, ...instrument.RecordOption) {} func Example() { m := meter{} diff --git a/sdk/metric/meter.go b/sdk/metric/meter.go index 1c156eb57a5..fe74a73de70 100644 --- a/sdk/metric/meter.go +++ b/sdk/metric/meter.go @@ -296,7 +296,7 @@ var ( errUnregObserver = errors.New("observable instrument not registered for callback") ) -func (r observer) ObserveFloat64(o instrument.Float64Observable, v float64, opts ...instrument.Float64ObserveOption) { +func (r observer) ObserveFloat64(o instrument.Float64Observable, v float64, opts ...instrument.ObserveOption) { var oImpl float64Observable switch conv := o.(type) { case float64Observable: @@ -325,11 +325,11 @@ func (r observer) ObserveFloat64(o instrument.Float64Observable, v float64, opts ) return } - c := instrument.NewFloat64ObserveConfig(opts) + c := instrument.NewObserveConfig(opts) oImpl.observe(v, c.Attributes()) } -func (r observer) ObserveInt64(o instrument.Int64Observable, v int64, opts ...instrument.Int64ObserveOption) { +func (r observer) ObserveInt64(o instrument.Int64Observable, v int64, opts ...instrument.ObserveOption) { var oImpl int64Observable switch conv := o.(type) { case int64Observable: @@ -358,7 +358,7 @@ func (r observer) ObserveInt64(o instrument.Int64Observable, v int64, opts ...in ) return } - c := instrument.NewInt64ObserveConfig(opts) + c := instrument.NewObserveConfig(opts) oImpl.observe(v, c.Attributes()) } @@ -452,8 +452,8 @@ type int64Observer struct { int64Observable } -func (o int64Observer) Observe(val int64, opts ...instrument.Int64ObserveOption) { - c := instrument.NewInt64ObserveConfig(opts) +func (o int64Observer) Observe(val int64, opts ...instrument.ObserveOption) { + c := instrument.NewObserveConfig(opts) o.observe(val, c.Attributes()) } @@ -485,7 +485,7 @@ type float64Observer struct { float64Observable } -func (o float64Observer) Observe(val float64, opts ...instrument.Float64ObserveOption) { - c := instrument.NewFloat64ObserveConfig(opts) +func (o float64Observer) Observe(val float64, opts ...instrument.ObserveOption) { + c := instrument.NewObserveConfig(opts) o.observe(val, c.Attributes()) } From 6ee8fc6238a3ecb154b6ffeccd7f3c3b055ad770 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Thu, 13 Apr 2023 12:34:52 -0700 Subject: [PATCH 15/16] Update changelog --- CHANGELOG.md | 47 +++++++++++++++++++---------------------------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1065abb235..1c5c9350781 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,24 +14,15 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - The `Version` function to `go.opentelemetry.io/otel/sdk` to return the SDK version. (#3949) - Add a `WithNamespace` option to `go.opentelemetry.io/otel/exporters/prometheus` to allow users to prefix metrics with a namespace. (#3970) - The following configuration types were added to `go.opentelemetry.io/otel/metric/instrument` to be used in the configuration of measurement methods. (#3971) - - The `Int64AddConfig` used to hold configuration for `int64` addition measurements - - `NewInt64AddConfig` used to create a new `Int64AddConfig` - - `Int64AddOption` used to configure an `Int64AddConfig` - - The `Float64AddConfig` used to hold configuration for `float64` addition measurements - - `NewFloat64AddConfig` used to create a new `Float64AddConfig` - - `Float64AddOption` used to configure an `Float64AddConfig` - - The `Int64RecordConfig` used to hold configuration for `int64` recorded measurements - - `NewInt64RecordConfig` used to create a new `Int64RecordConfig` - - `Int64RecordOption` used to configure an `Int64RecordConfig` - - The `Float64RecordConfig` used to hold configuration for `float64` recorded measurements - - `NewFloat64RecordConfig` used to create a new `Float64RecordConfig` - - `Float64RecordOption` used to configure an `Float64RecordConfig` - - The `Int64ObserveConfig` used to hold configuration for `int64` observed measurements - - `NewInt64ObserveConfig` used to create a new `Int64ObserveConfig` - - `Int64ObserveOption` used to configure an `Int64ObserveConfig` - - The `Float64ObserveConfig` used to hold configuration for `float64` observed measurements - - `NewFloat64ObserveConfig` used to create a new `Float64ObserveConfig` - - `Float64ObserveOption` used to configure an `Float64ObserveConfig` + - The `AddConfig` used to hold configuration for addition measurements + - `NewAddConfig` used to create a new `AddConfig` + - `AddOption` used to configure an `AddConfig` + - The `RecordConfig` used to hold configuration for recorded measurements + - `NewRecordConfig` used to create a new `RecordConfig` + - `RecordOption` used to configure a `RecordConfig` + - The `ObserveConfig` used to hold configuration for observed measurements + - `NewObserveConfig` used to create a new `ObserveConfig` + - `ObserveOption` used to configure an `ObserveConfig` - `WithAttributeSet` and `WithAttributes` are added to `go.opentelemetry.io/otel/metric/instrument`. They return an option used during a measurement that defines the attribute Set associated with the measurement. (#3971) - The `Version` function to `go.opentelemetry.io/otel/exporters/otlp/otlpmetric` to return the OTLP metrics client version. (#3956) @@ -46,17 +37,17 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - `metric.NewNoopMeterProvider` is replaced with `noop.NewMeterProvider` - Wrap `UploadMetrics` error in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/` to improve error message when encountering generic grpc errors. (#3974) - The measurement methods for all instruments in `go.opentelemetry.io/otel/metric/instrument` accept an option instead of the variadic `"go.opentelemetry.io/otel/attribute".KeyValue`. (#3971) - - The `Int64Counter.Add` method now accepts `...Int64AddOption` - - The `Float64Counter.Add` method now accepts `...Float64AddOption` - - The `Int64UpDownCounter.Add` method now accepts `...Int64AddOption` - - The `Float64UpDownCounter.Add` method now accepts `...Float64AddOption` - - The `Int64Histogram.Record` method now accepts `...Int64RecordOption` - - The `Float64Histogram.Record` method now accepts `...Float64RecordOption` - - The `Int64Observer.Observe` method now accepts `...Int64ObserveOption` - - The `Float64Observer.Observe` method now accepts `...Float64ObserveOption` + - The `Int64Counter.Add` method now accepts `...AddOption` + - The `Float64Counter.Add` method now accepts `...AddOption` + - The `Int64UpDownCounter.Add` method now accepts `...AddOption` + - The `Float64UpDownCounter.Add` method now accepts `...AddOption` + - The `Int64Histogram.Record` method now accepts `...RecordOption` + - The `Float64Histogram.Record` method now accepts `...RecordOption` + - The `Int64Observer.Observe` method now accepts `...ObserveOption` + - The `Float64Observer.Observe` method now accepts `...ObserveOption` - The `Observer` methods in `go.opentelemetry.io/otel/metric` accept an option instead of the variadic `"go.opentelemetry.io/otel/attribute".KeyValue`. (#3971) - - The `Observer.ObserveInt64` method now accepts `...Int64ObserveOption` - - The `Observer.ObserveFloat64` method now accepts `...Float64ObserveOption` + - The `Observer.ObserveInt64` method now accepts `...ObserveOption` + - The `Observer.ObserveFloat64` method now accepts `...ObserveOption` - Move global metric back to `go.opentelemetry.io/otel/metric/global` from `go.opentelemetry.io/otel`. (#3986) ### Fixed From 0eeafdb41e4f59bd0212e79b2218cf28dfc9dedd Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Thu, 13 Apr 2023 12:41:39 -0700 Subject: [PATCH 16/16] Remove left-over test cases --- metric/instrument/instrument_test.go | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/metric/instrument/instrument_test.go b/metric/instrument/instrument_test.go index 19ef98ccb84..23f2bdab215 100644 --- a/metric/instrument/instrument_test.go +++ b/metric/instrument/instrument_test.go @@ -36,14 +36,6 @@ func TestConfigAttrs(t *testing.T) { return NewAddConfig(opts) })) - t.Run("Int64AddConfig", testConfAttr(func(mo ...MeasurementOption) attrConf { - opts := make([]AddOption, len(mo)) - for i := range mo { - opts[i] = mo[i].(AddOption) - } - return NewAddConfig(opts) - })) - t.Run("RecordConfig", testConfAttr(func(mo ...MeasurementOption) attrConf { opts := make([]RecordOption, len(mo)) for i := range mo { @@ -52,14 +44,6 @@ func TestConfigAttrs(t *testing.T) { return NewRecordConfig(opts) })) - t.Run("Int64RecordConfig", testConfAttr(func(mo ...MeasurementOption) attrConf { - opts := make([]RecordOption, len(mo)) - for i := range mo { - opts[i] = mo[i].(RecordOption) - } - return NewRecordConfig(opts) - })) - t.Run("ObserveConfig", testConfAttr(func(mo ...MeasurementOption) attrConf { opts := make([]ObserveOption, len(mo)) for i := range mo { @@ -67,14 +51,6 @@ func TestConfigAttrs(t *testing.T) { } return NewObserveConfig(opts) })) - - t.Run("Int64ObserveConfig", testConfAttr(func(mo ...MeasurementOption) attrConf { - opts := make([]ObserveOption, len(mo)) - for i := range mo { - opts[i] = mo[i].(ObserveOption) - } - return NewObserveConfig(opts) - })) } func testConfAttr(newConf func(...MeasurementOption) attrConf) func(t *testing.T) {