diff --git a/sdk/metric/instrument_provider.go b/sdk/metric/instrument_provider.go index 8640b58e52e..89c09b22990 100644 --- a/sdk/metric/instrument_provider.go +++ b/sdk/metric/instrument_provider.go @@ -22,251 +22,140 @@ import ( "go.opentelemetry.io/otel/metric/instrument/asyncint64" "go.opentelemetry.io/otel/metric/instrument/syncfloat64" "go.opentelemetry.io/otel/metric/instrument/syncint64" + "go.opentelemetry.io/otel/metric/unit" "go.opentelemetry.io/otel/sdk/instrumentation" "go.opentelemetry.io/otel/sdk/metric/view" ) -type asyncInt64Provider struct { - scope instrumentation.Scope - resolve *resolver[int64] +// instProviderKey uniquely describes an instrument creation request received +// by an instrument provider. +type instProviderKey struct { + // Name is the name of the instrument. + Name string + // Description is the description of the instrument. + Description string + // Unit is the unit of the instrument. + Unit unit.Unit + // Kind is the instrument Kind provided. + Kind view.InstrumentKind +} + +// viewInst returns the instProviderKey as a view Instrument using scope s. +func (k instProviderKey) viewInst(s instrumentation.Scope) view.Instrument { + return view.Instrument{ + Scope: s, + Name: k.Name, + Description: k.Description, + Kind: k.Kind, + } } -var _ asyncint64.InstrumentProvider = asyncInt64Provider{} +// instProvider provides all OpenTelemetry instruments. +type instProvider[N int64 | float64] struct { + resolve resolver[N] +} -// Counter creates an instrument for recording increasing values. -func (p asyncInt64Provider) Counter(name string, opts ...instrument.Option) (asyncint64.Counter, error) { - cfg := instrument.NewConfig(opts...) +func newInstProvider[N int64 | float64](r resolver[N]) *instProvider[N] { + return &instProvider[N]{resolve: r} +} - aggs, err := p.resolve.Aggregators(view.Instrument{ - Scope: p.scope, +// lookup returns the resolved instrumentImpl. +func (p *instProvider[N]) lookup(kind view.InstrumentKind, name string, opts []instrument.Option) (*instrumentImpl[N], error) { + cfg := instrument.NewConfig(opts...) + key := instProviderKey{ Name: name, Description: cfg.Description(), - Kind: view.AsyncCounter, - }, cfg.Unit()) + Unit: cfg.Unit(), + Kind: kind, + } + + aggs, err := p.resolve.Aggregators(key) if len(aggs) == 0 && err != nil { err = fmt.Errorf("instrument does not match any view: %w", err) } + return &instrumentImpl[N]{aggregators: aggs}, err +} - return &instrumentImpl[int64]{ - aggregators: aggs, - }, err +type asyncInt64Provider struct { + *instProvider[int64] +} + +var _ asyncint64.InstrumentProvider = asyncInt64Provider{} + +// Counter creates an instrument for recording increasing values. +func (p asyncInt64Provider) Counter(name string, opts ...instrument.Option) (asyncint64.Counter, error) { + return p.lookup(view.AsyncCounter, name, opts) } // UpDownCounter creates an instrument for recording changes of a value. func (p asyncInt64Provider) UpDownCounter(name string, opts ...instrument.Option) (asyncint64.UpDownCounter, error) { - cfg := instrument.NewConfig(opts...) - - aggs, err := p.resolve.Aggregators(view.Instrument{ - Scope: p.scope, - Name: name, - Description: cfg.Description(), - Kind: view.AsyncUpDownCounter, - }, cfg.Unit()) - if len(aggs) == 0 && err != nil { - err = fmt.Errorf("instrument does not match any view: %w", err) - } - return &instrumentImpl[int64]{ - aggregators: aggs, - }, err + return p.lookup(view.AsyncUpDownCounter, name, opts) } // Gauge creates an instrument for recording the current value. func (p asyncInt64Provider) Gauge(name string, opts ...instrument.Option) (asyncint64.Gauge, error) { - cfg := instrument.NewConfig(opts...) - - aggs, err := p.resolve.Aggregators(view.Instrument{ - Scope: p.scope, - Name: name, - Description: cfg.Description(), - Kind: view.AsyncGauge, - }, cfg.Unit()) - if len(aggs) == 0 && err != nil { - err = fmt.Errorf("instrument does not match any view: %w", err) - } - return &instrumentImpl[int64]{ - aggregators: aggs, - }, err + return p.lookup(view.AsyncGauge, name, opts) } type asyncFloat64Provider struct { - scope instrumentation.Scope - resolve *resolver[float64] + *instProvider[float64] } var _ asyncfloat64.InstrumentProvider = asyncFloat64Provider{} // Counter creates an instrument for recording increasing values. func (p asyncFloat64Provider) Counter(name string, opts ...instrument.Option) (asyncfloat64.Counter, error) { - cfg := instrument.NewConfig(opts...) - - aggs, err := p.resolve.Aggregators(view.Instrument{ - Scope: p.scope, - Name: name, - Description: cfg.Description(), - Kind: view.AsyncCounter, - }, cfg.Unit()) - if len(aggs) == 0 && err != nil { - err = fmt.Errorf("instrument does not match any view: %w", err) - } - return &instrumentImpl[float64]{ - aggregators: aggs, - }, err + return p.lookup(view.AsyncCounter, name, opts) } // UpDownCounter creates an instrument for recording changes of a value. func (p asyncFloat64Provider) UpDownCounter(name string, opts ...instrument.Option) (asyncfloat64.UpDownCounter, error) { - cfg := instrument.NewConfig(opts...) - - aggs, err := p.resolve.Aggregators(view.Instrument{ - Scope: p.scope, - Name: name, - Description: cfg.Description(), - Kind: view.AsyncUpDownCounter, - }, cfg.Unit()) - if len(aggs) == 0 && err != nil { - err = fmt.Errorf("instrument does not match any view: %w", err) - } - return &instrumentImpl[float64]{ - aggregators: aggs, - }, err + return p.lookup(view.AsyncUpDownCounter, name, opts) } // Gauge creates an instrument for recording the current value. func (p asyncFloat64Provider) Gauge(name string, opts ...instrument.Option) (asyncfloat64.Gauge, error) { - cfg := instrument.NewConfig(opts...) - - aggs, err := p.resolve.Aggregators(view.Instrument{ - Scope: p.scope, - Name: name, - Description: cfg.Description(), - Kind: view.AsyncGauge, - }, cfg.Unit()) - if len(aggs) == 0 && err != nil { - err = fmt.Errorf("instrument does not match any view: %w", err) - } - return &instrumentImpl[float64]{ - aggregators: aggs, - }, err + return p.lookup(view.AsyncGauge, name, opts) } type syncInt64Provider struct { - scope instrumentation.Scope - resolve *resolver[int64] + *instProvider[int64] } var _ syncint64.InstrumentProvider = syncInt64Provider{} // Counter creates an instrument for recording increasing values. func (p syncInt64Provider) Counter(name string, opts ...instrument.Option) (syncint64.Counter, error) { - cfg := instrument.NewConfig(opts...) - - aggs, err := p.resolve.Aggregators(view.Instrument{ - Scope: p.scope, - Name: name, - Description: cfg.Description(), - Kind: view.SyncCounter, - }, cfg.Unit()) - if len(aggs) == 0 && err != nil { - err = fmt.Errorf("instrument does not match any view: %w", err) - } - return &instrumentImpl[int64]{ - aggregators: aggs, - }, err + return p.lookup(view.SyncCounter, name, opts) } // UpDownCounter creates an instrument for recording changes of a value. func (p syncInt64Provider) UpDownCounter(name string, opts ...instrument.Option) (syncint64.UpDownCounter, error) { - cfg := instrument.NewConfig(opts...) - - aggs, err := p.resolve.Aggregators(view.Instrument{ - Scope: p.scope, - Name: name, - Description: cfg.Description(), - Kind: view.SyncUpDownCounter, - }, cfg.Unit()) - if len(aggs) == 0 && err != nil { - err = fmt.Errorf("instrument does not match any view: %w", err) - } - return &instrumentImpl[int64]{ - aggregators: aggs, - }, err + return p.lookup(view.SyncUpDownCounter, name, opts) } // Histogram creates an instrument for recording the current value. func (p syncInt64Provider) Histogram(name string, opts ...instrument.Option) (syncint64.Histogram, error) { - cfg := instrument.NewConfig(opts...) - - aggs, err := p.resolve.Aggregators(view.Instrument{ - Scope: p.scope, - Name: name, - Description: cfg.Description(), - Kind: view.SyncHistogram, - }, cfg.Unit()) - if len(aggs) == 0 && err != nil { - err = fmt.Errorf("instrument does not match any view: %w", err) - } - return &instrumentImpl[int64]{ - aggregators: aggs, - }, err + return p.lookup(view.SyncHistogram, name, opts) } type syncFloat64Provider struct { - scope instrumentation.Scope - resolve *resolver[float64] + *instProvider[float64] } var _ syncfloat64.InstrumentProvider = syncFloat64Provider{} // Counter creates an instrument for recording increasing values. func (p syncFloat64Provider) Counter(name string, opts ...instrument.Option) (syncfloat64.Counter, error) { - cfg := instrument.NewConfig(opts...) - - aggs, err := p.resolve.Aggregators(view.Instrument{ - Scope: p.scope, - Name: name, - Description: cfg.Description(), - Kind: view.SyncCounter, - }, cfg.Unit()) - if len(aggs) == 0 && err != nil { - err = fmt.Errorf("instrument does not match any view: %w", err) - } - return &instrumentImpl[float64]{ - aggregators: aggs, - }, err + return p.lookup(view.SyncCounter, name, opts) } // UpDownCounter creates an instrument for recording changes of a value. func (p syncFloat64Provider) UpDownCounter(name string, opts ...instrument.Option) (syncfloat64.UpDownCounter, error) { - cfg := instrument.NewConfig(opts...) - - aggs, err := p.resolve.Aggregators(view.Instrument{ - Scope: p.scope, - Name: name, - Description: cfg.Description(), - Kind: view.SyncUpDownCounter, - }, cfg.Unit()) - if len(aggs) == 0 && err != nil { - err = fmt.Errorf("instrument does not match any view: %w", err) - } - return &instrumentImpl[float64]{ - aggregators: aggs, - }, err + return p.lookup(view.SyncUpDownCounter, name, opts) } // Histogram creates an instrument for recording the current value. func (p syncFloat64Provider) Histogram(name string, opts ...instrument.Option) (syncfloat64.Histogram, error) { - cfg := instrument.NewConfig(opts...) - - aggs, err := p.resolve.Aggregators(view.Instrument{ - Scope: p.scope, - Name: name, - Description: cfg.Description(), - Kind: view.SyncHistogram, - }, cfg.Unit()) - if len(aggs) == 0 && err != nil { - err = fmt.Errorf("instrument does not match any view: %w", err) - } - return &instrumentImpl[float64]{ - aggregators: aggs, - }, err + return p.lookup(view.SyncHistogram, name, opts) } diff --git a/sdk/metric/meter.go b/sdk/metric/meter.go index 80007b1465e..670049037d4 100644 --- a/sdk/metric/meter.go +++ b/sdk/metric/meter.go @@ -31,15 +31,10 @@ import ( // produced by an instrumentation scope will use metric instruments from a // single meter. type meter struct { - instrumentation.Scope - - // *Resolvers are used by the provided instrument providers to resolve new - // instruments aggregators and maintain a cache across instruments this - // meter owns. - int64Resolver resolver[int64] - float64Resolver resolver[float64] - pipes pipelines + + instProviderInt64 *instProvider[int64] + instProviderFloat64 *instProvider[float64] } func newMeter(s instrumentation.Scope, p pipelines) *meter { @@ -52,12 +47,13 @@ func newMeter(s instrumentation.Scope, p pipelines) *meter { ic := newInstrumentCache[int64](nil, &viewCache) fc := newInstrumentCache[float64](nil, &viewCache) - return &meter{ - Scope: s, - pipes: p, + ir := newResolver(s, p, ic) + fr := newResolver(s, p, fc) - int64Resolver: newResolver(p, ic), - float64Resolver: newResolver(p, fc), + return &meter{ + pipes: p, + instProviderInt64: newInstProvider(ir), + instProviderFloat64: newInstProvider(fr), } } @@ -66,12 +62,12 @@ var _ metric.Meter = (*meter)(nil) // AsyncInt64 returns the asynchronous integer instrument provider. func (m *meter) AsyncInt64() asyncint64.InstrumentProvider { - return asyncInt64Provider{scope: m.Scope, resolve: &m.int64Resolver} + return asyncInt64Provider{m.instProviderInt64} } // AsyncFloat64 returns the asynchronous floating-point instrument provider. func (m *meter) AsyncFloat64() asyncfloat64.InstrumentProvider { - return asyncFloat64Provider{scope: m.Scope, resolve: &m.float64Resolver} + return asyncFloat64Provider{m.instProviderFloat64} } // RegisterCallback registers the function f to be called when any of the @@ -83,10 +79,10 @@ func (m *meter) RegisterCallback(insts []instrument.Asynchronous, f func(context // SyncInt64 returns the synchronous integer instrument provider. func (m *meter) SyncInt64() syncint64.InstrumentProvider { - return syncInt64Provider{scope: m.Scope, resolve: &m.int64Resolver} + return syncInt64Provider{m.instProviderInt64} } // SyncFloat64 returns the synchronous floating-point instrument provider. func (m *meter) SyncFloat64() syncfloat64.InstrumentProvider { - return syncFloat64Provider{scope: m.Scope, resolve: &m.float64Resolver} + return syncFloat64Provider{m.instProviderFloat64} } diff --git a/sdk/metric/meter_test.go b/sdk/metric/meter_test.go index 7cc7e307466..ff5da4f7e52 100644 --- a/sdk/metric/meter_test.go +++ b/sdk/metric/meter_test.go @@ -25,6 +25,10 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/metric/instrument" + "go.opentelemetry.io/otel/metric/instrument/asyncfloat64" + "go.opentelemetry.io/otel/metric/instrument/asyncint64" + "go.opentelemetry.io/otel/metric/instrument/syncfloat64" + "go.opentelemetry.io/otel/metric/instrument/syncint64" "go.opentelemetry.io/otel/sdk/instrumentation" "go.opentelemetry.io/otel/sdk/metric/metricdata" "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" @@ -828,3 +832,47 @@ func TestAttributeFilter(t *testing.T) { }) } } + +var ( + aiCounter asyncint64.Counter + aiUpDownCounter asyncint64.UpDownCounter + aiGauge asyncint64.Gauge + + afCounter asyncfloat64.Counter + afUpDownCounter asyncfloat64.UpDownCounter + afGauge asyncfloat64.Gauge + + siCounter syncint64.Counter + siUpDownCounter syncint64.UpDownCounter + siHistogram syncint64.Histogram + + sfCounter syncfloat64.Counter + sfUpDownCounter syncfloat64.UpDownCounter + sfHistogram syncfloat64.Histogram +) + +func BenchmarkInstrumentCreation(b *testing.B) { + provider := NewMeterProvider(WithReader(NewManualReader())) + meter := provider.Meter("BenchmarkInstrumentCreation") + + b.ReportAllocs() + b.ResetTimer() + + for n := 0; n < b.N; n++ { + aiCounter, _ = meter.AsyncInt64().Counter("async.int64.counter") + aiUpDownCounter, _ = meter.AsyncInt64().UpDownCounter("async.int64.up.down.counter") + aiGauge, _ = meter.AsyncInt64().Gauge("async.int64.gauge") + + afCounter, _ = meter.AsyncFloat64().Counter("async.float64.counter") + afUpDownCounter, _ = meter.AsyncFloat64().UpDownCounter("async.float64.up.down.counter") + afGauge, _ = meter.AsyncFloat64().Gauge("async.float64.gauge") + + siCounter, _ = meter.SyncInt64().Counter("sync.int64.counter") + siUpDownCounter, _ = meter.SyncInt64().UpDownCounter("sync.int64.up.down.counter") + siHistogram, _ = meter.SyncInt64().Histogram("sync.int64.histogram") + + sfCounter, _ = meter.SyncFloat64().Counter("sync.float64.counter") + sfUpDownCounter, _ = meter.SyncFloat64().UpDownCounter("sync.float64.up.down.counter") + sfHistogram, _ = meter.SyncFloat64().Histogram("sync.float64.histogram") + } +} diff --git a/sdk/metric/pipeline.go b/sdk/metric/pipeline.go index a3a7d069983..fb651355498 100644 --- a/sdk/metric/pipeline.go +++ b/sdk/metric/pipeline.go @@ -156,14 +156,16 @@ func (p *pipeline) produce(ctx context.Context) (metricdata.ResourceMetrics, err }, nil } -// inserter facilitates inserting of new instruments into a pipeline. +// inserter facilitates inserting of new instruments from a single scope into a +// pipeline. type inserter[N int64 | float64] struct { + scope instrumentation.Scope cache instrumentCache[N] pipeline *pipeline } -func newInserter[N int64 | float64](p *pipeline, c instrumentCache[N]) *inserter[N] { - return &inserter[N]{cache: c, pipeline: p} +func newInserter[N int64 | float64](s instrumentation.Scope, p *pipeline, c instrumentCache[N]) *inserter[N] { + return &inserter[N]{scope: s, cache: c, pipeline: p} } // Instrument inserts the instrument inst with instUnit into a pipeline. All @@ -187,7 +189,7 @@ func newInserter[N int64 | float64](p *pipeline, c instrumentCache[N]) *inserter // // If an instrument is determined to use a Drop aggregation, that instrument is // not inserted nor returned. -func (i *inserter[N]) Instrument(inst view.Instrument, instUnit unit.Unit) ([]internal.Aggregator[N], error) { +func (i *inserter[N]) Instrument(key instProviderKey) ([]internal.Aggregator[N], error) { var ( matched bool aggs []internal.Aggregator[N] @@ -197,6 +199,7 @@ func (i *inserter[N]) Instrument(inst view.Instrument, instUnit unit.Unit) ([]in // The cache will return the same Aggregator instance. Use this fact to // compare pointer addresses to deduplicate Aggregators. seen := make(map[internal.Aggregator[N]]struct{}) + inst := key.viewInst(i.scope) for _, v := range i.pipeline.views { inst, match := v.TransformInstrument(inst) if !match { @@ -204,7 +207,7 @@ func (i *inserter[N]) Instrument(inst view.Instrument, instUnit unit.Unit) ([]in } matched = true - agg, err := i.cachedAggregator(inst, instUnit, v.AttributeFilter()) + agg, err := i.cachedAggregator(inst, key.Unit, v.AttributeFilter()) if err != nil { errs.append(err) } @@ -224,7 +227,7 @@ func (i *inserter[N]) Instrument(inst view.Instrument, instUnit unit.Unit) ([]in } // Apply implicit default view if no explicit matched. - agg, err := i.cachedAggregator(inst, instUnit, nil) + agg, err := i.cachedAggregator(inst, key.Unit, nil) if err != nil { errs.append(err) } @@ -449,22 +452,22 @@ type resolver[N int64 | float64] struct { inserters []*inserter[N] } -func newResolver[N int64 | float64](p pipelines, c instrumentCache[N]) resolver[N] { +func newResolver[N int64 | float64](s instrumentation.Scope, p pipelines, c instrumentCache[N]) resolver[N] { in := make([]*inserter[N], len(p)) for i := range in { - in[i] = newInserter(p[i], c) + in[i] = newInserter(s, p[i], c) } return resolver[N]{in} } -// Aggregators returns the Aggregators instrument inst needs to update when it -// makes a measurement. -func (r resolver[N]) Aggregators(inst view.Instrument, instUnit unit.Unit) ([]internal.Aggregator[N], error) { +// Aggregators returns the Aggregators that must be updated by the instrument +// defined by key. +func (r resolver[N]) Aggregators(key instProviderKey) ([]internal.Aggregator[N], error) { var aggs []internal.Aggregator[N] errs := &multierror{} for _, i := range r.inserters { - a, err := i.Instrument(inst, instUnit) + a, err := i.Instrument(key) if err != nil { errs.append(err) } diff --git a/sdk/metric/pipeline_registry_test.go b/sdk/metric/pipeline_registry_test.go index a6ad6f81d23..ae3a2173f30 100644 --- a/sdk/metric/pipeline_registry_test.go +++ b/sdk/metric/pipeline_registry_test.go @@ -25,7 +25,7 @@ import ( "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/metric/unit" + "go.opentelemetry.io/otel/sdk/instrumentation" "go.opentelemetry.io/otel/sdk/metric/aggregation" "go.opentelemetry.io/otel/sdk/metric/internal" "go.opentelemetry.io/otel/sdk/metric/view" @@ -61,7 +61,7 @@ func testCreateAggregators[N int64 | float64](t *testing.T) { view.WithSetAggregation(invalidAggregation{}), ) - instruments := []view.Instrument{ + instruments := []instProviderKey{ {Name: "foo", Kind: view.InstrumentKind(0)}, //Unknown kind {Name: "foo", Kind: view.SyncCounter}, {Name: "foo", Kind: view.SyncUpDownCounter}, @@ -75,7 +75,7 @@ func testCreateAggregators[N int64 | float64](t *testing.T) { name string reader Reader views []view.View - inst view.Instrument + inst instProviderKey wantKind internal.Aggregator[N] //Aggregators should match len and types wantLen int wantErr error @@ -213,11 +213,12 @@ func testCreateAggregators[N int64 | float64](t *testing.T) { wantErr: errCreatingAggregators, }, } + s := instrumentation.Scope{Name: "testCreateAggregators"} for _, tt := range testcases { t.Run(tt.name, func(t *testing.T) { c := newInstrumentCache[N](nil, nil) - i := newInserter(newPipeline(nil, tt.reader, tt.views), c) - got, err := i.Instrument(tt.inst, unit.Dimensionless) + i := newInserter(s, newPipeline(nil, tt.reader, tt.views), c) + got, err := i.Instrument(tt.inst) assert.ErrorIs(t, err, tt.wantErr) require.Len(t, got, tt.wantLen) for _, agg := range got { @@ -229,12 +230,13 @@ func testCreateAggregators[N int64 | float64](t *testing.T) { func testInvalidInstrumentShouldPanic[N int64 | float64]() { c := newInstrumentCache[N](nil, nil) - i := newInserter(newPipeline(nil, NewManualReader(), []view.View{{}}), c) - inst := view.Instrument{ + s := instrumentation.Scope{Name: "testInvalidInstrumentShouldPanic"} + i := newInserter(s, newPipeline(nil, NewManualReader(), []view.View{{}}), c) + inst := instProviderKey{ Name: "foo", Kind: view.InstrumentKind(255), } - _, _ = i.Instrument(inst, unit.Dimensionless) + _, _ = i.Instrument(inst) } func TestInvalidInstrumentShouldPanic(t *testing.T) { @@ -313,22 +315,24 @@ func TestPipelineRegistryCreateAggregators(t *testing.T) { } func testPipelineRegistryResolveIntAggregators(t *testing.T, p pipelines, wantCount int) { - inst := view.Instrument{Name: "foo", Kind: view.SyncCounter} + inst := instProviderKey{Name: "foo", Kind: view.SyncCounter} c := newInstrumentCache[int64](nil, nil) - r := newResolver(p, c) - aggs, err := r.Aggregators(inst, unit.Dimensionless) + s := instrumentation.Scope{Name: "testPipelineRegistryResolveIntAggregators"} + r := newResolver(s, p, c) + aggs, err := r.Aggregators(inst) assert.NoError(t, err) require.Len(t, aggs, wantCount) } func testPipelineRegistryResolveFloatAggregators(t *testing.T, p pipelines, wantCount int) { - inst := view.Instrument{Name: "foo", Kind: view.SyncCounter} + inst := instProviderKey{Name: "foo", Kind: view.SyncCounter} c := newInstrumentCache[float64](nil, nil) - r := newResolver(p, c) - aggs, err := r.Aggregators(inst, unit.Dimensionless) + s := instrumentation.Scope{Name: "testPipelineRegistryResolveFloatAggregators"} + r := newResolver(s, p, c) + aggs, err := r.Aggregators(inst) assert.NoError(t, err) require.Len(t, aggs, wantCount) @@ -352,16 +356,17 @@ func TestPipelineRegistryCreateAggregatorsIncompatibleInstrument(t *testing.T) { readers := []Reader{testRdrHistogram} views := []view.View{{}} p := newPipelines(resource.Empty(), readers, views) - inst := view.Instrument{Name: "foo", Kind: view.AsyncGauge} + inst := instProviderKey{Name: "foo", Kind: view.AsyncGauge} vc := cache[string, instrumentID]{} - ri := newResolver(p, newInstrumentCache[int64](nil, &vc)) - intAggs, err := ri.Aggregators(inst, unit.Dimensionless) + s := instrumentation.Scope{Name: "TestPipelineRegistryCreateAggregatorsIncompatibleInstrument"} + ri := newResolver(s, p, newInstrumentCache[int64](nil, &vc)) + intAggs, err := ri.Aggregators(inst) assert.Error(t, err) assert.Len(t, intAggs, 0) - rf := newResolver(p, newInstrumentCache[float64](nil, &vc)) - floatAggs, err := rf.Aggregators(inst, unit.Dimensionless) + rf := newResolver(s, p, newInstrumentCache[float64](nil, &vc)) + floatAggs, err := rf.Aggregators(inst) assert.Error(t, err) assert.Len(t, floatAggs, 0) } @@ -393,41 +398,42 @@ func TestResolveAggregatorsDuplicateErrors(t *testing.T) { readers := []Reader{NewManualReader()} views := []view.View{{}, renameView} - fooInst := view.Instrument{Name: "foo", Kind: view.SyncCounter} - barInst := view.Instrument{Name: "bar", Kind: view.SyncCounter} + fooInst := instProviderKey{Name: "foo", Kind: view.SyncCounter} + barInst := instProviderKey{Name: "bar", Kind: view.SyncCounter} p := newPipelines(resource.Empty(), readers, views) vc := cache[string, instrumentID]{} - ri := newResolver(p, newInstrumentCache[int64](nil, &vc)) - intAggs, err := ri.Aggregators(fooInst, unit.Dimensionless) + s := instrumentation.Scope{Name: "TestPipelineRegistryCreateAggregatorsDuplicateErrors"} + ri := newResolver(s, p, newInstrumentCache[int64](nil, &vc)) + intAggs, err := ri.Aggregators(fooInst) assert.NoError(t, err) assert.Equal(t, 0, l.InfoN(), "no info logging should happen") assert.Len(t, intAggs, 1) // The Rename view should produce the same instrument without an error, the // default view should also cause a new aggregator to be returned. - intAggs, err = ri.Aggregators(barInst, unit.Dimensionless) + intAggs, err = ri.Aggregators(barInst) assert.NoError(t, err) assert.Equal(t, 0, l.InfoN(), "no info logging should happen") assert.Len(t, intAggs, 2) // Creating a float foo instrument should log a warning because there is an // int foo instrument. - rf := newResolver(p, newInstrumentCache[float64](nil, &vc)) - floatAggs, err := rf.Aggregators(fooInst, unit.Dimensionless) + rf := newResolver(s, p, newInstrumentCache[float64](nil, &vc)) + floatAggs, err := rf.Aggregators(fooInst) assert.NoError(t, err) assert.Equal(t, 1, l.InfoN(), "instrument conflict not logged") assert.Len(t, floatAggs, 1) - fooInst = view.Instrument{Name: "foo-float", Kind: view.SyncCounter} + fooInst = instProviderKey{Name: "foo-float", Kind: view.SyncCounter} - floatAggs, err = rf.Aggregators(fooInst, unit.Dimensionless) + floatAggs, err = rf.Aggregators(fooInst) assert.NoError(t, err) assert.Equal(t, 0, l.InfoN(), "no info logging should happen") assert.Len(t, floatAggs, 1) - floatAggs, err = rf.Aggregators(barInst, unit.Dimensionless) + floatAggs, err = rf.Aggregators(barInst) assert.NoError(t, err) // Both the rename and default view aggregators created above should now // conflict. Therefore, 2 warning messages should be logged. diff --git a/sdk/metric/pipeline_test.go b/sdk/metric/pipeline_test.go index e47bb6b5f64..75cc06d4878 100644 --- a/sdk/metric/pipeline_test.go +++ b/sdk/metric/pipeline_test.go @@ -26,7 +26,6 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric/unit" "go.opentelemetry.io/otel/sdk/instrumentation" - "go.opentelemetry.io/otel/sdk/metric/aggregation" "go.opentelemetry.io/otel/sdk/metric/metricdata" "go.opentelemetry.io/otel/sdk/metric/metricdata/metricdatatest" "go.opentelemetry.io/otel/sdk/metric/view" @@ -135,12 +134,12 @@ func TestDefaultViewImplicit(t *testing.T) { } func testDefaultViewImplicit[N int64 | float64]() func(t *testing.T) { - inst := view.Instrument{ - Scope: instrumentation.Scope{Name: "testing/lib"}, + scope := instrumentation.Scope{Name: "testing/lib"} + inst := instProviderKey{ Name: "requests", Description: "count of requests received", Kind: view.SyncCounter, - Aggregation: aggregation.Sum{}, + Unit: unit.Dimensionless, } return func(t *testing.T) { reader := NewManualReader() @@ -164,8 +163,8 @@ func testDefaultViewImplicit[N int64 | float64]() func(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { c := newInstrumentCache[N](nil, nil) - i := newInserter(test.pipe, c) - got, err := i.Instrument(inst, unit.Dimensionless) + i := newInserter(scope, test.pipe, c) + got, err := i.Instrument(inst) require.NoError(t, err) assert.Len(t, got, 1, "default view not applied")