1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2026-06-03 18:35:08 +02:00

Add options to measurement methods (#3971)

* Add options to measurement methods

* Update noop

* Update global impl

* Update SDK impl

* Fix metric API example

* Update prometheus exporter tests

* Update examples

* WithAttributes and WithAttributeSet

* Add changes to changelog

* Accept slice instead of variadic to new conf funcs

* Clarify WithAttributes performance in docs

* Address feedback about WithAttributes comment

* Add changelog entry for WithAttribute{s,Set}

* Remove number scope from measure opts

* Update changelog

* Remove left-over test cases

---------

Co-authored-by: Robert Pająk <pellared@hotmail.com>
This commit is contained in:
Tyler Yahn
2023-04-18 07:16:06 -07:00
committed by GitHub
parent d1959c9239
commit f8fcfda872
24 changed files with 742 additions and 364 deletions
+68 -61
View File
@@ -66,59 +66,65 @@ func benchSyncViews(views ...View) func(*testing.B) {
iCtr, err := meter.Int64Counter("int64-counter")
assert.NoError(b, err)
b.Run("Int64Counter", benchMeasAttrs(func() measF {
return func(attr []attribute.KeyValue) func() {
return func() { iCtr.Add(ctx, 1, attr...) }
return func(s attribute.Set) func() {
o := []instrument.AddOption{instrument.WithAttributeSet(s)}
return func() { iCtr.Add(ctx, 1, o...) }
}
}()))
fCtr, err := meter.Float64Counter("float64-counter")
assert.NoError(b, err)
b.Run("Float64Counter", benchMeasAttrs(func() measF {
return func(attr []attribute.KeyValue) func() {
return func() { fCtr.Add(ctx, 1, attr...) }
return func(s attribute.Set) func() {
o := []instrument.AddOption{instrument.WithAttributeSet(s)}
return func() { fCtr.Add(ctx, 1, o...) }
}
}()))
iUDCtr, err := meter.Int64UpDownCounter("int64-up-down-counter")
assert.NoError(b, err)
b.Run("Int64UpDownCounter", benchMeasAttrs(func() measF {
return func(attr []attribute.KeyValue) func() {
return func() { iUDCtr.Add(ctx, 1, attr...) }
return func(s attribute.Set) func() {
o := []instrument.AddOption{instrument.WithAttributeSet(s)}
return func() { iUDCtr.Add(ctx, 1, o...) }
}
}()))
fUDCtr, err := meter.Float64UpDownCounter("float64-up-down-counter")
assert.NoError(b, err)
b.Run("Float64UpDownCounter", benchMeasAttrs(func() measF {
return func(attr []attribute.KeyValue) func() {
return func() { fUDCtr.Add(ctx, 1, attr...) }
return func(s attribute.Set) func() {
o := []instrument.AddOption{instrument.WithAttributeSet(s)}
return func() { fUDCtr.Add(ctx, 1, o...) }
}
}()))
iHist, err := meter.Int64Histogram("int64-histogram")
assert.NoError(b, err)
b.Run("Int64Histogram", benchMeasAttrs(func() measF {
return func(attr []attribute.KeyValue) func() {
return func() { iHist.Record(ctx, 1, attr...) }
return func(s attribute.Set) func() {
o := []instrument.RecordOption{instrument.WithAttributeSet(s)}
return func() { iHist.Record(ctx, 1, o...) }
}
}()))
fHist, err := meter.Float64Histogram("float64-histogram")
assert.NoError(b, err)
b.Run("Float64Histogram", benchMeasAttrs(func() measF {
return func(attr []attribute.KeyValue) func() {
return func() { fHist.Record(ctx, 1, attr...) }
return func(s attribute.Set) func() {
o := []instrument.RecordOption{instrument.WithAttributeSet(s)}
return func() { fHist.Record(ctx, 1, o...) }
}
}()))
}
}
type measF func(attr []attribute.KeyValue) func()
type measF func(s attribute.Set) func()
func benchMeasAttrs(meas measF) func(*testing.B) {
return func(b *testing.B) {
b.Run("Attributes/0", func(b *testing.B) {
f := meas(nil)
f := meas(*attribute.EmptySet())
b.ReportAllocs()
b.ResetTimer()
for n := 0; n < b.N; n++ {
@@ -126,8 +132,7 @@ func benchMeasAttrs(meas measF) func(*testing.B) {
}
})
b.Run("Attributes/1", func(b *testing.B) {
attrs := []attribute.KeyValue{attribute.Bool("K", true)}
f := meas(attrs)
f := meas(attribute.NewSet(attribute.Bool("K", true)))
b.ReportAllocs()
b.ResetTimer()
for n := 0; n < b.N; n++ {
@@ -141,7 +146,7 @@ func benchMeasAttrs(meas measF) func(*testing.B) {
for i := 2; i < n; i++ {
attrs = append(attrs, attribute.Int(strconv.Itoa(i), i))
}
f := meas(attrs)
f := meas(attribute.NewSet(attrs...))
b.ReportAllocs()
b.ResetTimer()
for n := 0; n < b.N; n++ {
@@ -165,163 +170,163 @@ func benchCollectViews(views ...View) func(*testing.B) {
}
ctx := context.Background()
return func(b *testing.B) {
b.Run("Int64Counter/1", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
b.Run("Int64Counter/1", benchCollectAttrs(func(s attribute.Set) Reader {
m, r := setup("benchCollectViews/Int64Counter")
i, err := m.Int64Counter("int64-counter")
assert.NoError(b, err)
i.Add(ctx, 1, attr...)
i.Add(ctx, 1, instrument.WithAttributeSet(s))
return r
}))
b.Run("Int64Counter/10", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
b.Run("Int64Counter/10", benchCollectAttrs(func(s attribute.Set) Reader {
m, r := setup("benchCollectViews/Int64Counter")
i, err := m.Int64Counter("int64-counter")
assert.NoError(b, err)
for n := 0; n < 10; n++ {
i.Add(ctx, 1, attr...)
i.Add(ctx, 1, instrument.WithAttributeSet(s))
}
return r
}))
b.Run("Float64Counter/1", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
b.Run("Float64Counter/1", benchCollectAttrs(func(s attribute.Set) Reader {
m, r := setup("benchCollectViews/Float64Counter")
i, err := m.Float64Counter("float64-counter")
assert.NoError(b, err)
i.Add(ctx, 1, attr...)
i.Add(ctx, 1, instrument.WithAttributeSet(s))
return r
}))
b.Run("Float64Counter/10", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
b.Run("Float64Counter/10", benchCollectAttrs(func(s attribute.Set) Reader {
m, r := setup("benchCollectViews/Float64Counter")
i, err := m.Float64Counter("float64-counter")
assert.NoError(b, err)
for n := 0; n < 10; n++ {
i.Add(ctx, 1, attr...)
i.Add(ctx, 1, instrument.WithAttributeSet(s))
}
return r
}))
b.Run("Int64UpDownCounter/1", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
b.Run("Int64UpDownCounter/1", benchCollectAttrs(func(s attribute.Set) Reader {
m, r := setup("benchCollectViews/Int64UpDownCounter")
i, err := m.Int64UpDownCounter("int64-up-down-counter")
assert.NoError(b, err)
i.Add(ctx, 1, attr...)
i.Add(ctx, 1, instrument.WithAttributeSet(s))
return r
}))
b.Run("Int64UpDownCounter/10", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
b.Run("Int64UpDownCounter/10", benchCollectAttrs(func(s attribute.Set) Reader {
m, r := setup("benchCollectViews/Int64UpDownCounter")
i, err := m.Int64UpDownCounter("int64-up-down-counter")
assert.NoError(b, err)
for n := 0; n < 10; n++ {
i.Add(ctx, 1, attr...)
i.Add(ctx, 1, instrument.WithAttributeSet(s))
}
return r
}))
b.Run("Float64UpDownCounter/1", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
b.Run("Float64UpDownCounter/1", benchCollectAttrs(func(s attribute.Set) Reader {
m, r := setup("benchCollectViews/Float64UpDownCounter")
i, err := m.Float64UpDownCounter("float64-up-down-counter")
assert.NoError(b, err)
i.Add(ctx, 1, attr...)
i.Add(ctx, 1, instrument.WithAttributeSet(s))
return r
}))
b.Run("Float64UpDownCounter/10", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
b.Run("Float64UpDownCounter/10", benchCollectAttrs(func(s attribute.Set) Reader {
m, r := setup("benchCollectViews/Float64UpDownCounter")
i, err := m.Float64UpDownCounter("float64-up-down-counter")
assert.NoError(b, err)
for n := 0; n < 10; n++ {
i.Add(ctx, 1, attr...)
i.Add(ctx, 1, instrument.WithAttributeSet(s))
}
return r
}))
b.Run("Int64Histogram/1", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
b.Run("Int64Histogram/1", benchCollectAttrs(func(s attribute.Set) Reader {
m, r := setup("benchCollectViews/Int64Histogram")
i, err := m.Int64Histogram("int64-histogram")
assert.NoError(b, err)
i.Record(ctx, 1, attr...)
i.Record(ctx, 1, instrument.WithAttributeSet(s))
return r
}))
b.Run("Int64Histogram/10", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
b.Run("Int64Histogram/10", benchCollectAttrs(func(s attribute.Set) Reader {
m, r := setup("benchCollectViews/Int64Histogram")
i, err := m.Int64Histogram("int64-histogram")
assert.NoError(b, err)
for n := 0; n < 10; n++ {
i.Record(ctx, 1, attr...)
i.Record(ctx, 1, instrument.WithAttributeSet(s))
}
return r
}))
b.Run("Float64Histogram/1", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
b.Run("Float64Histogram/1", benchCollectAttrs(func(s attribute.Set) Reader {
m, r := setup("benchCollectViews/Float64Histogram")
i, err := m.Float64Histogram("float64-histogram")
assert.NoError(b, err)
i.Record(ctx, 1, attr...)
i.Record(ctx, 1, instrument.WithAttributeSet(s))
return r
}))
b.Run("Float64Histogram/10", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
b.Run("Float64Histogram/10", benchCollectAttrs(func(s attribute.Set) Reader {
m, r := setup("benchCollectViews/Float64Histogram")
i, err := m.Float64Histogram("float64-histogram")
assert.NoError(b, err)
for n := 0; n < 10; n++ {
i.Record(ctx, 1, attr...)
i.Record(ctx, 1, instrument.WithAttributeSet(s))
}
return r
}))
b.Run("Int64ObservableCounter", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
b.Run("Int64ObservableCounter", benchCollectAttrs(func(s attribute.Set) Reader {
m, r := setup("benchCollectViews/Int64ObservableCounter")
_, err := m.Int64ObservableCounter(
"int64-observable-counter",
instrument.WithInt64Callback(int64Cback(attr)),
instrument.WithInt64Callback(int64Cback(s)),
)
assert.NoError(b, err)
return r
}))
b.Run("Float64ObservableCounter", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
b.Run("Float64ObservableCounter", benchCollectAttrs(func(s attribute.Set) Reader {
m, r := setup("benchCollectViews/Float64ObservableCounter")
_, err := m.Float64ObservableCounter(
"float64-observable-counter",
instrument.WithFloat64Callback(float64Cback(attr)),
instrument.WithFloat64Callback(float64Cback(s)),
)
assert.NoError(b, err)
return r
}))
b.Run("Int64ObservableUpDownCounter", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
b.Run("Int64ObservableUpDownCounter", benchCollectAttrs(func(s attribute.Set) Reader {
m, r := setup("benchCollectViews/Int64ObservableUpDownCounter")
_, err := m.Int64ObservableUpDownCounter(
"int64-observable-up-down-counter",
instrument.WithInt64Callback(int64Cback(attr)),
instrument.WithInt64Callback(int64Cback(s)),
)
assert.NoError(b, err)
return r
}))
b.Run("Float64ObservableUpDownCounter", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
b.Run("Float64ObservableUpDownCounter", benchCollectAttrs(func(s attribute.Set) Reader {
m, r := setup("benchCollectViews/Float64ObservableUpDownCounter")
_, err := m.Float64ObservableUpDownCounter(
"float64-observable-up-down-counter",
instrument.WithFloat64Callback(float64Cback(attr)),
instrument.WithFloat64Callback(float64Cback(s)),
)
assert.NoError(b, err)
return r
}))
b.Run("Int64ObservableGauge", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
b.Run("Int64ObservableGauge", benchCollectAttrs(func(s attribute.Set) Reader {
m, r := setup("benchCollectViews/Int64ObservableGauge")
_, err := m.Int64ObservableGauge(
"int64-observable-gauge",
instrument.WithInt64Callback(int64Cback(attr)),
instrument.WithInt64Callback(int64Cback(s)),
)
assert.NoError(b, err)
return r
}))
b.Run("Float64ObservableGauge", benchCollectAttrs(func(attr []attribute.KeyValue) Reader {
b.Run("Float64ObservableGauge", benchCollectAttrs(func(s attribute.Set) Reader {
m, r := setup("benchCollectViews/Float64ObservableGauge")
_, err := m.Float64ObservableGauge(
"float64-observable-gauge",
instrument.WithFloat64Callback(float64Cback(attr)),
instrument.WithFloat64Callback(float64Cback(s)),
)
assert.NoError(b, err)
return r
@@ -329,21 +334,23 @@ func benchCollectViews(views ...View) func(*testing.B) {
}
}
func int64Cback(attr []attribute.KeyValue) instrument.Int64Callback {
func int64Cback(s attribute.Set) instrument.Int64Callback {
opt := []instrument.ObserveOption{instrument.WithAttributeSet(s)}
return func(_ context.Context, o instrument.Int64Observer) error {
o.Observe(1, attr...)
o.Observe(1, opt...)
return nil
}
}
func float64Cback(attr []attribute.KeyValue) instrument.Float64Callback {
func float64Cback(s attribute.Set) instrument.Float64Callback {
opt := []instrument.ObserveOption{instrument.WithAttributeSet(s)}
return func(_ context.Context, o instrument.Float64Observer) error {
o.Observe(1, attr...)
o.Observe(1, opt...)
return nil
}
}
func benchCollectAttrs(setup func([]attribute.KeyValue) Reader) func(*testing.B) {
func benchCollectAttrs(setup func(attribute.Set) Reader) func(*testing.B) {
ctx := context.Background()
out := new(metricdata.ResourceMetrics)
run := func(reader Reader) func(b *testing.B) {
@@ -355,14 +362,14 @@ func benchCollectAttrs(setup func([]attribute.KeyValue) Reader) func(*testing.B)
}
}
return func(b *testing.B) {
b.Run("Attributes/0", run(setup(nil)))
b.Run("Attributes/0", run(setup(*attribute.EmptySet())))
attrs := []attribute.KeyValue{attribute.Bool("K", true)}
b.Run("Attributes/1", run(setup(attrs)))
b.Run("Attributes/1", run(setup(attribute.NewSet(attrs...))))
for i := 2; i < 10; i++ {
attrs = append(attrs, attribute.Int(strconv.Itoa(i), i))
}
b.Run("Attributes/10", run(setup(attrs)))
b.Run("Attributes/10", run(setup(attribute.NewSet(attrs...))))
}
}
+44 -25
View File
@@ -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 *instrumentImpl[N]) Add(ctx context.Context, val N, attrs ...attribute.KeyValue) {
i.aggregate(ctx, val, attrs)
func (i *int64Inst) Add(ctx context.Context, val int64, opts ...instrument.AddOption) {
c := instrument.NewAddConfig(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 *int64Inst) Record(ctx context.Context, val int64, opts ...instrument.RecordOption) {
c := instrument.NewRecordConfig(opts)
i.aggregate(ctx, val, c.Attributes())
}
func (i *instrumentImpl[N]) aggregate(ctx context.Context, val N, attrs []attribute.KeyValue) {
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 *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.RecordOption) {
c := instrument.NewRecordConfig(opts)
i.aggregate(ctx, val, c.Attributes())
}
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)
}
+4 -4
View File
@@ -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),
@@ -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.AddOption) {}
func (inst) Record(context.Context, int64, ...instrument.RecordOption) {}
func Example() {
m := meter{}
+54 -23
View File
@@ -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.ObserveOption) {
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.NewObserveConfig(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.ObserveOption) {
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.NewObserveConfig(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.ObserveOption) {
c := instrument.NewObserveConfig(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.ObserveOption) {
c := instrument.NewObserveConfig(opts)
o.observe(val, c.Attributes())
}
+60 -80
View File
@@ -169,7 +169,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.WithAttributeSet(attrs)
testCases := []struct {
name string
fn func(*testing.T, metric.Meter)
@@ -179,7 +180,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))
@@ -196,7 +197,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},
},
},
@@ -206,7 +207,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))
@@ -223,7 +224,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},
},
},
@@ -233,7 +234,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))
@@ -248,7 +249,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},
},
},
@@ -258,7 +259,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))
@@ -275,7 +276,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},
},
},
@@ -285,7 +286,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))
@@ -302,7 +303,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},
},
},
@@ -312,7 +313,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))
@@ -327,7 +328,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},
},
},
@@ -885,6 +886,12 @@ func TestAttributeFilter(t *testing.T) {
}
func testAttributeFilter(temporality metricdata.Temporality) func(*testing.T) {
fooBar := attribute.NewSet(attribute.String("foo", "bar"))
withFooBar := instrument.WithAttributeSet(fooBar)
v1 := attribute.NewSet(attribute.String("foo", "bar"), attribute.Int("version", 1))
withV1 := instrument.WithAttributeSet(v1)
v2 := attribute.NewSet(attribute.String("foo", "bar"), attribute.Int("version", 2))
withV2 := instrument.WithAttributeSet(v2)
testcases := []struct {
name string
register func(t *testing.T, mtr metric.Meter) error
@@ -898,9 +905,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
@@ -909,10 +916,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,
@@ -927,9 +931,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
@@ -956,8 +960,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
@@ -966,10 +970,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},
},
},
},
@@ -982,9 +983,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
@@ -993,10 +994,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,
@@ -1011,9 +1009,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
@@ -1022,10 +1020,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,
@@ -1040,8 +1035,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
@@ -1050,10 +1045,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},
},
},
},
@@ -1066,18 +1058,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,
@@ -1092,18 +1081,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,
@@ -1118,8 +1104,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{
@@ -1127,7 +1113,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,
@@ -1148,18 +1134,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,
@@ -1174,18 +1157,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,
@@ -1200,8 +1180,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{
@@ -1209,7 +1189,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,
@@ -1296,7 +1276,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.WithAttributeSet(attrSet))
}
return nil
},