From dceba986e71fe091070f9d4f356356695d5f6752 Mon Sep 17 00:00:00 2001 From: Tyler Yahn Date: Mon, 10 Apr 2023 09:11:06 -0700 Subject: [PATCH] WithAttributes and WithAttributeSet --- example/prometheus/main.go | 3 +- example/view/main.go | 3 +- exporters/prometheus/exporter_test.go | 44 ++++----- 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, 206 insertions(+), 63 deletions(-) create mode 100644 metric/instrument/instrument_test.go diff --git a/example/prometheus/main.go b/example/prometheus/main.go index 3d8fc628f42f..c716aa1e4476 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 561b45be6d53..1fc6d9cd6365 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 4ec683c1cf1f..1885acd08e4c 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"), @@ -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 41d835ec5b4d..fee7e415bc23 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 efb6b043a2b2..fce5a72a0f5f 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 000000000000..872cad6b8386 --- /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 3b0ad1de1355..ff9fdc5c45a0 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 d0b965832c74..ca82a2f5282e 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 },