1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2025-01-18 03:22:12 +02:00

Remove bound metric instruments from the API (new champion) (#2399)

* Remove bound metric instruments from the API

* Removed dead code

* Added changelog message

* Added PR number

Co-authored-by: Joshua MacDonald <jmacd@lightstep.com>
Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com>
This commit is contained in:
Aaron Clawson 2021-11-17 09:51:04 -06:00 committed by GitHub
parent b663c7c2bd
commit 034956199a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 19 additions and 528 deletions

View File

@ -11,6 +11,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
### Removed
- Remove the metric Processor's ability to convert cumulative to delta aggregation temporality. (#2350)
- Remove the metric Bound Instruments interface and implementations. (#2399)
## [1.2.0] - 2021-11-12

View File

@ -41,10 +41,6 @@ import (
// in the MeterProvider and Meters ensure that each instrument has a delegate
// before the global provider is set.
//
// Bound instrument operations are implemented by delegating to the
// instrument after it is registered, with a sync.Once initializer to
// protect against races with Release().
//
// Metric uniqueness checking is implemented by calling the exported
// methods of the api/metric/registry package.
@ -108,19 +104,9 @@ type AsyncImpler interface {
AsyncImpl() sdkapi.AsyncImpl
}
type syncHandle struct {
delegate unsafe.Pointer // (*sdkapi.BoundInstrumentImpl)
inst *syncImpl
labels []attribute.KeyValue
initialize sync.Once
}
var _ metric.MeterProvider = &meterProvider{}
var _ sdkapi.MeterImpl = &meterImpl{}
var _ sdkapi.InstrumentImpl = &syncImpl{}
var _ sdkapi.BoundSyncImpl = &syncHandle{}
var _ sdkapi.AsyncImpl = &asyncImpl{}
func (inst *instrument) Descriptor() sdkapi.Descriptor {
@ -241,28 +227,6 @@ func (inst *syncImpl) Implementation() interface{} {
return inst
}
func (inst *syncImpl) Bind(labels []attribute.KeyValue) sdkapi.BoundSyncImpl {
if implPtr := (*sdkapi.SyncImpl)(atomic.LoadPointer(&inst.delegate)); implPtr != nil {
return (*implPtr).Bind(labels)
}
return &syncHandle{
inst: inst,
labels: labels,
}
}
func (bound *syncHandle) Unbind() {
bound.initialize.Do(func() {})
implPtr := (*sdkapi.BoundSyncImpl)(atomic.LoadPointer(&bound.delegate))
if implPtr == nil {
return
}
(*implPtr).Unbind()
}
// Async delegation
func (m *meterImpl) NewAsyncInstrument(
@ -325,37 +289,11 @@ func (inst *syncImpl) RecordOne(ctx context.Context, number number.Number, label
}
}
// Bound instrument initialization
func (bound *syncHandle) RecordOne(ctx context.Context, number number.Number) {
instPtr := (*sdkapi.SyncImpl)(atomic.LoadPointer(&bound.inst.delegate))
if instPtr == nil {
return
}
var implPtr *sdkapi.BoundSyncImpl
bound.initialize.Do(func() {
implPtr = new(sdkapi.BoundSyncImpl)
*implPtr = (*instPtr).Bind(bound.labels)
atomic.StorePointer(&bound.delegate, unsafe.Pointer(implPtr))
})
if implPtr == nil {
implPtr = (*sdkapi.BoundSyncImpl)(atomic.LoadPointer(&bound.delegate))
}
// This may still be nil if instrument was created and bound
// without a delegate, then the instrument was set to have a
// delegate and unbound.
if implPtr == nil {
return
}
(*implPtr).RecordOne(ctx, number)
}
func AtomicFieldOffsets() map[string]uintptr {
return map[string]uintptr{
"meterProvider.delegate": unsafe.Offsetof(meterProvider{}.delegate),
"meterImpl.delegate": unsafe.Offsetof(meterImpl{}.delegate),
"syncImpl.delegate": unsafe.Offsetof(syncImpl{}.delegate),
"asyncImpl.delegate": unsafe.Offsetof(asyncImpl{}.delegate),
"syncHandle.delegate": unsafe.Offsetof(syncHandle{}.delegate),
}
}

View File

@ -137,97 +137,6 @@ func TestDirect(t *testing.T) {
)
}
func TestBound(t *testing.T) {
global.ResetForTest()
// Note: this test uses opposite Float64/Int64 number kinds
// vs. the above, to cover all the instruments.
ctx := context.Background()
glob := metricglobal.Meter(
"test",
metric.WithInstrumentationVersion("semver:test-1.0"),
metric.WithSchemaURL("schema://url"),
)
labels1 := []attribute.KeyValue{attribute.String("A", "B")}
counter := Must(glob).NewFloat64Counter("test.counter")
boundC := counter.Bind(labels1...)
boundC.Add(ctx, 1)
boundC.Add(ctx, 1)
histogram := Must(glob).NewInt64Histogram("test.histogram")
boundM := histogram.Bind(labels1...)
boundM.Record(ctx, 1)
boundM.Record(ctx, 2)
provider := metrictest.NewMeterProvider()
metricglobal.SetMeterProvider(provider)
boundC.Add(ctx, 1)
boundM.Record(ctx, 3)
library := metrictest.Library{
InstrumentationName: "test",
InstrumentationVersion: "semver:test-1.0",
SchemaURL: "schema://url",
}
require.EqualValues(t,
[]metrictest.Measured{
{
Name: "test.counter",
Library: library,
Labels: metrictest.LabelsToMap(labels1...),
Number: asFloat(1),
},
{
Name: "test.histogram",
Library: library,
Labels: metrictest.LabelsToMap(labels1...),
Number: asInt(3),
},
},
metrictest.AsStructs(provider.MeasurementBatches))
boundC.Unbind()
boundM.Unbind()
}
func TestUnbind(t *testing.T) {
// Tests Unbind with SDK never installed.
global.ResetForTest()
glob := metricglobal.Meter("test")
labels1 := []attribute.KeyValue{attribute.String("A", "B")}
counter := Must(glob).NewFloat64Counter("test.counter")
boundC := counter.Bind(labels1...)
histogram := Must(glob).NewInt64Histogram("test.histogram")
boundM := histogram.Bind(labels1...)
boundC.Unbind()
boundM.Unbind()
}
func TestUnbindThenRecordOne(t *testing.T) {
global.ResetForTest()
ctx := context.Background()
provider := metrictest.NewMeterProvider()
meter := metricglobal.Meter("test")
counter := Must(meter).NewInt64Counter("test.counter")
boundC := counter.Bind()
metricglobal.SetMeterProvider(provider)
boundC.Unbind()
require.NotPanics(t, func() {
boundC.Add(ctx, 1)
})
require.Equal(t, 0, len(provider.MeasurementBatches))
}
type meterProviderWithConstructorError struct {
metric.MeterProvider
}

View File

@ -260,11 +260,6 @@ type syncInstrument struct {
instrument sdkapi.SyncImpl
}
// syncBoundInstrument contains a BoundSyncImpl.
type syncBoundInstrument struct {
boundInstrument sdkapi.BoundSyncImpl
}
// asyncInstrument contains a AsyncImpl.
type asyncInstrument struct {
instrument sdkapi.AsyncImpl
@ -280,10 +275,6 @@ func (s syncInstrument) SyncImpl() sdkapi.SyncImpl {
return s.instrument
}
func (s syncInstrument) bind(labels []attribute.KeyValue) syncBoundInstrument {
return newSyncBoundInstrument(s.instrument.Bind(labels))
}
func (s syncInstrument) float64Measurement(value float64) Measurement {
return sdkapi.NewMeasurement(s.instrument, number.NewFloat64Number(value))
}
@ -296,15 +287,6 @@ func (s syncInstrument) directRecord(ctx context.Context, number number.Number,
s.instrument.RecordOne(ctx, number, labels)
}
func (h syncBoundInstrument) directRecord(ctx context.Context, number number.Number) {
h.boundInstrument.RecordOne(ctx, number)
}
// Unbind calls SyncImpl.Unbind.
func (h syncBoundInstrument) Unbind() {
h.boundInstrument.Unbind()
}
// checkNewAsync receives an AsyncImpl and potential
// error, and returns the same types, checking for and ensuring that
// the returned interface is not nil.
@ -340,12 +322,6 @@ func checkNewSync(instrument sdkapi.SyncImpl, err error) (syncInstrument, error)
}, err
}
func newSyncBoundInstrument(boundInstrument sdkapi.BoundSyncImpl) syncBoundInstrument {
return syncBoundInstrument{
boundInstrument: boundInstrument,
}
}
// wrapInt64CounterInstrument converts a SyncImpl into Int64Counter.
func wrapInt64CounterInstrument(syncInst sdkapi.SyncImpl, err error) (Int64Counter, error) {
common, err := checkNewSync(syncInst, err)
@ -392,34 +368,6 @@ type Int64Counter struct {
syncInstrument
}
// BoundFloat64Counter is a bound instrument for Float64Counter.
//
// It inherits the Unbind function from syncBoundInstrument.
type BoundFloat64Counter struct {
syncBoundInstrument
}
// BoundInt64Counter is a boundInstrument for Int64Counter.
//
// It inherits the Unbind function from syncBoundInstrument.
type BoundInt64Counter struct {
syncBoundInstrument
}
// Bind creates a bound instrument for this counter. The labels are
// associated with values recorded via subsequent calls to Record.
func (c Float64Counter) Bind(labels ...attribute.KeyValue) (h BoundFloat64Counter) {
h.syncBoundInstrument = c.bind(labels)
return
}
// Bind creates a bound instrument for this counter. The labels are
// associated with values recorded via subsequent calls to Record.
func (c Int64Counter) Bind(labels ...attribute.KeyValue) (h BoundInt64Counter) {
h.syncBoundInstrument = c.bind(labels)
return
}
// Measurement creates a Measurement object to use with batch
// recording.
func (c Float64Counter) Measurement(value float64) Measurement {
@ -444,18 +392,6 @@ func (c Int64Counter) Add(ctx context.Context, value int64, labels ...attribute.
c.directRecord(ctx, number.NewInt64Number(value), labels)
}
// Add adds the value to the counter's sum using the labels
// previously bound to this counter via Bind()
func (b BoundFloat64Counter) Add(ctx context.Context, value float64) {
b.directRecord(ctx, number.NewFloat64Number(value))
}
// Add adds the value to the counter's sum using the labels
// previously bound to this counter via Bind()
func (b BoundInt64Counter) Add(ctx context.Context, value int64) {
b.directRecord(ctx, number.NewInt64Number(value))
}
// Float64UpDownCounter is a metric instrument that sums floating
// point values.
type Float64UpDownCounter struct {
@ -467,34 +403,6 @@ type Int64UpDownCounter struct {
syncInstrument
}
// BoundFloat64UpDownCounter is a bound instrument for Float64UpDownCounter.
//
// It inherits the Unbind function from syncBoundInstrument.
type BoundFloat64UpDownCounter struct {
syncBoundInstrument
}
// BoundInt64UpDownCounter is a boundInstrument for Int64UpDownCounter.
//
// It inherits the Unbind function from syncBoundInstrument.
type BoundInt64UpDownCounter struct {
syncBoundInstrument
}
// Bind creates a bound instrument for this counter. The labels are
// associated with values recorded via subsequent calls to Record.
func (c Float64UpDownCounter) Bind(labels ...attribute.KeyValue) (h BoundFloat64UpDownCounter) {
h.syncBoundInstrument = c.bind(labels)
return
}
// Bind creates a bound instrument for this counter. The labels are
// associated with values recorded via subsequent calls to Record.
func (c Int64UpDownCounter) Bind(labels ...attribute.KeyValue) (h BoundInt64UpDownCounter) {
h.syncBoundInstrument = c.bind(labels)
return
}
// Measurement creates a Measurement object to use with batch
// recording.
func (c Float64UpDownCounter) Measurement(value float64) Measurement {
@ -519,18 +427,6 @@ func (c Int64UpDownCounter) Add(ctx context.Context, value int64, labels ...attr
c.directRecord(ctx, number.NewInt64Number(value), labels)
}
// Add adds the value to the counter's sum using the labels
// previously bound to this counter via Bind()
func (b BoundFloat64UpDownCounter) Add(ctx context.Context, value float64) {
b.directRecord(ctx, number.NewFloat64Number(value))
}
// Add adds the value to the counter's sum using the labels
// previously bound to this counter via Bind()
func (b BoundInt64UpDownCounter) Add(ctx context.Context, value int64) {
b.directRecord(ctx, number.NewInt64Number(value))
}
// Float64Histogram is a metric that records float64 values.
type Float64Histogram struct {
syncInstrument
@ -541,34 +437,6 @@ type Int64Histogram struct {
syncInstrument
}
// BoundFloat64Histogram is a bound instrument for Float64Histogram.
//
// It inherits the Unbind function from syncBoundInstrument.
type BoundFloat64Histogram struct {
syncBoundInstrument
}
// BoundInt64Histogram is a bound instrument for Int64Histogram.
//
// It inherits the Unbind function from syncBoundInstrument.
type BoundInt64Histogram struct {
syncBoundInstrument
}
// Bind creates a bound instrument for this Histogram. The labels are
// associated with values recorded via subsequent calls to Record.
func (c Float64Histogram) Bind(labels ...attribute.KeyValue) (h BoundFloat64Histogram) {
h.syncBoundInstrument = c.bind(labels)
return
}
// Bind creates a bound instrument for this Histogram. The labels are
// associated with values recorded via subsequent calls to Record.
func (c Int64Histogram) Bind(labels ...attribute.KeyValue) (h BoundInt64Histogram) {
h.syncBoundInstrument = c.bind(labels)
return
}
// Measurement creates a Measurement object to use with batch
// recording.
func (c Float64Histogram) Measurement(value float64) Measurement {
@ -594,15 +462,3 @@ func (c Float64Histogram) Record(ctx context.Context, value float64, labels ...a
func (c Int64Histogram) Record(ctx context.Context, value int64, labels ...attribute.KeyValue) {
c.directRecord(ctx, number.NewInt64Number(value), labels)
}
// Record adds a new value to the Histogram's distribution using the labels
// previously bound to the Histogram via Bind().
func (b BoundFloat64Histogram) Record(ctx context.Context, value float64) {
b.directRecord(ctx, number.NewFloat64Number(value))
}
// Record adds a new value to the Histogram's distribution using the labels
// previously bound to the Histogram via Bind().
func (b BoundInt64Histogram) Record(ctx context.Context, value int64) {
b.directRecord(ctx, number.NewInt64Number(value))
}

View File

@ -250,11 +250,9 @@ func TestCounter(t *testing.T) {
ctx := context.Background()
labels := []attribute.KeyValue{attribute.String("A", "B")}
c.Add(ctx, 1994.1, labels...)
boundInstrument := c.Bind(labels...)
boundInstrument.Add(ctx, -742)
meter.RecordBatch(ctx, labels, c.Measurement(42))
checkSyncBatches(ctx, t, labels, provider, number.Float64Kind, sdkapi.CounterInstrumentKind, c.SyncImpl(),
1994.1, -742, 42,
1994.1, 42,
)
})
t.Run("int64 counter", func(t *testing.T) {
@ -263,11 +261,9 @@ func TestCounter(t *testing.T) {
ctx := context.Background()
labels := []attribute.KeyValue{attribute.String("A", "B"), attribute.String("C", "D")}
c.Add(ctx, 42, labels...)
boundInstrument := c.Bind(labels...)
boundInstrument.Add(ctx, 4200)
meter.RecordBatch(ctx, labels, c.Measurement(420000))
checkSyncBatches(ctx, t, labels, provider, number.Int64Kind, sdkapi.CounterInstrumentKind, c.SyncImpl(),
42, 4200, 420000,
42, 420000,
)
})
@ -277,11 +273,9 @@ func TestCounter(t *testing.T) {
ctx := context.Background()
labels := []attribute.KeyValue{attribute.String("A", "B"), attribute.String("C", "D")}
c.Add(ctx, 100, labels...)
boundInstrument := c.Bind(labels...)
boundInstrument.Add(ctx, -100)
meter.RecordBatch(ctx, labels, c.Measurement(42))
checkSyncBatches(ctx, t, labels, provider, number.Int64Kind, sdkapi.UpDownCounterInstrumentKind, c.SyncImpl(),
100, -100, 42,
100, 42,
)
})
t.Run("float64 updowncounter", func(t *testing.T) {
@ -290,11 +284,9 @@ func TestCounter(t *testing.T) {
ctx := context.Background()
labels := []attribute.KeyValue{attribute.String("A", "B"), attribute.String("C", "D")}
c.Add(ctx, 100.1, labels...)
boundInstrument := c.Bind(labels...)
boundInstrument.Add(ctx, -76)
meter.RecordBatch(ctx, labels, c.Measurement(-100.1))
checkSyncBatches(ctx, t, labels, provider, number.Float64Kind, sdkapi.UpDownCounterInstrumentKind, c.SyncImpl(),
100.1, -76, -100.1,
100.1, -100.1,
)
})
}
@ -306,11 +298,9 @@ func TestHistogram(t *testing.T) {
ctx := context.Background()
labels := []attribute.KeyValue{}
m.Record(ctx, 42, labels...)
boundInstrument := m.Bind(labels...)
boundInstrument.Record(ctx, 0)
meter.RecordBatch(ctx, labels, m.Measurement(-100.5))
checkSyncBatches(ctx, t, labels, provider, number.Float64Kind, sdkapi.HistogramInstrumentKind, m.SyncImpl(),
42, 0, -100.5,
42, -100.5,
)
})
t.Run("int64 histogram", func(t *testing.T) {
@ -319,11 +309,9 @@ func TestHistogram(t *testing.T) {
ctx := context.Background()
labels := []attribute.KeyValue{attribute.Int("I", 1)}
m.Record(ctx, 173, labels...)
boundInstrument := m.Bind(labels...)
boundInstrument.Record(ctx, 80)
meter.RecordBatch(ctx, labels, m.Measurement(0))
checkSyncBatches(ctx, t, labels, provider, number.Int64Kind, sdkapi.HistogramInstrumentKind, m.SyncImpl(),
173, 80, 0,
173, 0,
)
})
}

View File

@ -86,10 +86,9 @@ type (
)
var (
_ sdkapi.SyncImpl = &Sync{}
_ sdkapi.BoundSyncImpl = &Handle{}
_ sdkapi.MeterImpl = &MeterImpl{}
_ sdkapi.AsyncImpl = &Async{}
_ sdkapi.SyncImpl = &Sync{}
_ sdkapi.MeterImpl = &MeterImpl{}
_ sdkapi.AsyncImpl = &Async{}
)
// NewDescriptor is a test helper for constructing test metric
@ -111,13 +110,6 @@ func (s *Sync) Implementation() interface{} {
return s
}
func (s *Sync) Bind(labels []attribute.KeyValue) sdkapi.BoundSyncImpl {
return &Handle{
Instrument: s,
Labels: labels,
}
}
func (s *Sync) RecordOne(ctx context.Context, number number.Number, labels []attribute.KeyValue) {
s.meter.doRecordSingle(ctx, labels, s, number)
}

View File

@ -22,12 +22,10 @@ import (
)
type noopInstrument struct{}
type noopBoundInstrument struct{}
type noopSyncInstrument struct{ noopInstrument }
type noopAsyncInstrument struct{ noopInstrument }
var _ SyncImpl = noopSyncInstrument{}
var _ BoundSyncImpl = noopBoundInstrument{}
var _ AsyncImpl = noopAsyncInstrument{}
// NewNoopSyncInstrument returns a No-op implementation of the
@ -50,15 +48,5 @@ func (noopInstrument) Descriptor() Descriptor {
return Descriptor{}
}
func (noopBoundInstrument) RecordOne(context.Context, number.Number) {
}
func (noopBoundInstrument) Unbind() {
}
func (noopSyncInstrument) Bind([]attribute.KeyValue) BoundSyncImpl {
return noopBoundInstrument{}
}
func (noopSyncInstrument) RecordOne(context.Context, number.Number, []attribute.KeyValue) {
}

View File

@ -58,26 +58,10 @@ type InstrumentImpl interface {
type SyncImpl interface {
InstrumentImpl
// Bind creates an implementation-level bound instrument,
// binding a label set with this instrument implementation.
Bind(labels []attribute.KeyValue) BoundSyncImpl
// RecordOne captures a single synchronous metric event.
RecordOne(ctx context.Context, number number.Number, labels []attribute.KeyValue)
}
// BoundSyncImpl is the implementation-level interface to a
// generic bound synchronous instrument
type BoundSyncImpl interface {
// RecordOne captures a single synchronous metric event.
RecordOne(ctx context.Context, number number.Number)
// Unbind frees the resources associated with this bound instrument. It
// does not affect the metric this bound instrument was created through.
Unbind()
}
// AsyncImpl is an implementation-level interface to an
// asynchronous instrument (e.g., Observer instruments).
type AsyncImpl interface {

View File

@ -60,16 +60,6 @@ func (f *benchFixture) meterMust() metric.MeterMust {
return metric.Must(f.meter)
}
func makeManyLabels(n int) [][]attribute.KeyValue {
r := make([][]attribute.KeyValue, n)
for i := 0; i < n; i++ {
r[i] = makeLabels(1)
}
return r
}
func makeLabels(n int) []attribute.KeyValue {
used := map[string]bool{}
l := make([]attribute.KeyValue, n)
@ -123,50 +113,6 @@ func BenchmarkInt64CounterAddWithLabels_16(b *testing.B) {
// Note: performance does not depend on label set size for the
// benchmarks below--all are benchmarked for a single attribute.
func BenchmarkAcquireNewHandle(b *testing.B) {
fix := newFixture(b)
labelSets := makeManyLabels(b.N)
cnt := fix.meterMust().NewInt64Counter("int64.sum")
b.ResetTimer()
for i := 0; i < b.N; i++ {
cnt.Bind(labelSets[i]...)
}
}
func BenchmarkAcquireExistingHandle(b *testing.B) {
fix := newFixture(b)
labelSets := makeManyLabels(b.N)
cnt := fix.meterMust().NewInt64Counter("int64.sum")
for i := 0; i < b.N; i++ {
cnt.Bind(labelSets[i]...).Unbind()
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
cnt.Bind(labelSets[i]...)
}
}
func BenchmarkAcquireReleaseExistingHandle(b *testing.B) {
fix := newFixture(b)
labelSets := makeManyLabels(b.N)
cnt := fix.meterMust().NewInt64Counter("int64.sum")
for i := 0; i < b.N; i++ {
cnt.Bind(labelSets[i]...).Unbind()
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
cnt.Bind(labelSets[i]...).Unbind()
}
}
// Iterators
var benchmarkIteratorVar attribute.KeyValue
@ -241,20 +187,6 @@ func BenchmarkInt64CounterAdd(b *testing.B) {
}
}
func BenchmarkInt64CounterHandleAdd(b *testing.B) {
ctx := context.Background()
fix := newFixture(b)
labs := makeLabels(1)
cnt := fix.meterMust().NewInt64Counter("int64.sum")
handle := cnt.Bind(labs...)
b.ResetTimer()
for i := 0; i < b.N; i++ {
handle.Add(ctx, 1)
}
}
func BenchmarkFloat64CounterAdd(b *testing.B) {
ctx := context.Background()
fix := newFixture(b)
@ -268,20 +200,6 @@ func BenchmarkFloat64CounterAdd(b *testing.B) {
}
}
func BenchmarkFloat64CounterHandleAdd(b *testing.B) {
ctx := context.Background()
fix := newFixture(b)
labs := makeLabels(1)
cnt := fix.meterMust().NewFloat64Counter("float64.sum")
handle := cnt.Bind(labs...)
b.ResetTimer()
for i := 0; i < b.N; i++ {
handle.Add(ctx, 1.1)
}
}
// LastValue
func BenchmarkInt64LastValueAdd(b *testing.B) {
@ -297,20 +215,6 @@ func BenchmarkInt64LastValueAdd(b *testing.B) {
}
}
func BenchmarkInt64LastValueHandleAdd(b *testing.B) {
ctx := context.Background()
fix := newFixture(b)
labs := makeLabels(1)
mea := fix.meterMust().NewInt64Histogram("int64.lastvalue")
handle := mea.Bind(labs...)
b.ResetTimer()
for i := 0; i < b.N; i++ {
handle.Record(ctx, int64(i))
}
}
func BenchmarkFloat64LastValueAdd(b *testing.B) {
ctx := context.Background()
fix := newFixture(b)
@ -324,20 +228,6 @@ func BenchmarkFloat64LastValueAdd(b *testing.B) {
}
}
func BenchmarkFloat64LastValueHandleAdd(b *testing.B) {
ctx := context.Background()
fix := newFixture(b)
labs := makeLabels(1)
mea := fix.meterMust().NewFloat64Histogram("float64.lastvalue")
handle := mea.Bind(labs...)
b.ResetTimer()
for i := 0; i < b.N; i++ {
handle.Record(ctx, float64(i))
}
}
// Histograms
func benchmarkInt64HistogramAdd(b *testing.B, name string) {
@ -353,20 +243,6 @@ func benchmarkInt64HistogramAdd(b *testing.B, name string) {
}
}
func benchmarkInt64HistogramHandleAdd(b *testing.B, name string) {
ctx := context.Background()
fix := newFixture(b)
labs := makeLabels(1)
mea := fix.meterMust().NewInt64Histogram(name)
handle := mea.Bind(labs...)
b.ResetTimer()
for i := 0; i < b.N; i++ {
handle.Record(ctx, int64(i))
}
}
func benchmarkFloat64HistogramAdd(b *testing.B, name string) {
ctx := context.Background()
fix := newFixture(b)
@ -380,20 +256,6 @@ func benchmarkFloat64HistogramAdd(b *testing.B, name string) {
}
}
func benchmarkFloat64HistogramHandleAdd(b *testing.B, name string) {
ctx := context.Background()
fix := newFixture(b)
labs := makeLabels(1)
mea := fix.meterMust().NewFloat64Histogram(name)
handle := mea.Bind(labs...)
b.ResetTimer()
for i := 0; i < b.N; i++ {
handle.Record(ctx, float64(i))
}
}
// Observers
func BenchmarkObserverRegistration(b *testing.B) {
@ -447,36 +309,20 @@ func BenchmarkInt64MaxSumCountAdd(b *testing.B) {
benchmarkInt64HistogramAdd(b, "int64.minmaxsumcount")
}
func BenchmarkInt64MaxSumCountHandleAdd(b *testing.B) {
benchmarkInt64HistogramHandleAdd(b, "int64.minmaxsumcount")
}
func BenchmarkFloat64MaxSumCountAdd(b *testing.B) {
benchmarkFloat64HistogramAdd(b, "float64.minmaxsumcount")
}
func BenchmarkFloat64MaxSumCountHandleAdd(b *testing.B) {
benchmarkFloat64HistogramHandleAdd(b, "float64.minmaxsumcount")
}
// Exact
func BenchmarkInt64ExactAdd(b *testing.B) {
benchmarkInt64HistogramAdd(b, "int64.exact")
}
func BenchmarkInt64ExactHandleAdd(b *testing.B) {
benchmarkInt64HistogramHandleAdd(b, "int64.exact")
}
func BenchmarkFloat64ExactAdd(b *testing.B) {
benchmarkFloat64HistogramAdd(b, "float64.exact")
}
func BenchmarkFloat64ExactHandleAdd(b *testing.B) {
benchmarkFloat64HistogramHandleAdd(b, "float64.exact")
}
// BatchRecord
func benchmarkBatchRecord8Labels(b *testing.B, numInst int) {

View File

@ -483,16 +483,14 @@ func TestRecordPersistence(t *testing.T) {
meter, sdk, selector, _ := newSDK(t)
c := Must(meter).NewFloat64Counter("name.sum")
b := c.Bind(attribute.String("bound", "true"))
uk := attribute.String("bound", "false")
for i := 0; i < 100; i++ {
c.Add(ctx, 1, uk)
b.Add(ctx, 1)
sdk.Collect(ctx)
}
require.Equal(t, 4, selector.newAggCount)
require.Equal(t, 2, selector.newAggCount)
}
func TestIncorrectInstruments(t *testing.T) {

View File

@ -28,9 +28,7 @@ and asynchronous instruments. There are two constructors per instrument for
the two kinds of number (int64, float64).
Synchronous instruments are managed by a sync.Map containing a *record
with the current state for each synchronous instrument. A bound
instrument encapsulates a direct pointer to the record, allowing
bound metric events to bypass a sync.Map lookup. A lock-free
with the current state for each synchronous instrument. A lock-free
algorithm is used to protect against races when adding and removing
items from the sync.Map.
@ -45,7 +43,7 @@ record contains a set of recorders for every specific label set used in the
callback.
A sync.Map maintains the mapping of current instruments and label sets to
internal records. To create a new bound instrument, the SDK consults the Map to
internal records. To find a record, the SDK consults the Map to
locate an existing record, otherwise it constructs a new record. The SDK
maintains a count of the number of references to each record, ensuring
that records are not reclaimed from the Map while they are still active

View File

@ -138,10 +138,9 @@ type (
)
var (
_ sdkapi.MeterImpl = &Accumulator{}
_ sdkapi.AsyncImpl = &asyncInstrument{}
_ sdkapi.SyncImpl = &syncInstrument{}
_ sdkapi.BoundSyncImpl = &record{}
_ sdkapi.MeterImpl = &Accumulator{}
_ sdkapi.AsyncImpl = &asyncInstrument{}
_ sdkapi.SyncImpl = &syncInstrument{}
// ErrUninitializedInstrument is returned when an instrument is used when uninitialized.
ErrUninitializedInstrument = fmt.Errorf("use of an uninitialized instrument")
@ -279,15 +278,10 @@ func (s *syncInstrument) acquireHandle(kvs []attribute.KeyValue, labelPtr *attri
}
}
// The order of the input array `kvs` may be sorted after the function is called.
func (s *syncInstrument) Bind(kvs []attribute.KeyValue) sdkapi.BoundSyncImpl {
return s.acquireHandle(kvs, nil)
}
// The order of the input array `kvs` may be sorted after the function is called.
func (s *syncInstrument) RecordOne(ctx context.Context, num number.Number, kvs []attribute.KeyValue) {
h := s.acquireHandle(kvs, nil)
defer h.Unbind()
defer h.unbind()
h.RecordOne(ctx, num)
}
@ -490,7 +484,7 @@ func (m *Accumulator) RecordBatch(ctx context.Context, kvs []attribute.KeyValue,
labelsPtr = h.labels
}
defer h.Unbind()
defer h.unbind()
h.RecordOne(ctx, meas.Number())
}
}
@ -514,8 +508,7 @@ func (r *record) RecordOne(ctx context.Context, num number.Number) {
atomic.AddInt64(&r.updateCount, 1)
}
// Unbind implements sdkapi.SyncImpl.
func (r *record) Unbind() {
func (r *record) unbind() {
r.refMapped.unref()
}