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

Remove the unneeded Observe method from the async instruments (#3586)

* Update RegisterCallback and Callback decls

RegisterCallback accept variadic Asynchronous instruments instead of a
slice.

Callback accept an observation result recorder to ensure instruments
that are observed by a callback.

* Update global impl

* Update noop impl

* Update SDK impl

* Fix prometheus example

* Fix metric API example_test

* Remove unused registerabler

* Rename ObservationRecorder to MultiObserver

* Update Callback documentation about MultiObserver

* Remove the Observe method from async inst

* Revert to iface for Observers

* Fix async inst docs

* Update global async delegate race test

* Restore removed observe doc

* Remove TODO

* Remove stale comment

* Update changelog
This commit is contained in:
Tyler Yahn 2023-01-25 12:58:09 -08:00 committed by GitHub
parent c7e2679529
commit c0fb8dec4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 186 additions and 251 deletions

View File

@ -36,7 +36,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Add the `go.opentelemetry.io/otel/semconv/v1.16.0` package.
The package contains semantic conventions from the `v1.16.0` version of the OpenTelemetry specification. (#3579)
- Metric instruments were added to `go.opentelemetry.io/otel/metric/instrument`.
These instruments are use as replacements of the depreacted `go.opentelemetry.io/otel/metric/instrument/{asyncfloat64,asyncint64,syncfloat64,syncint64}` packages.(#3575)
These instruments are use as replacements of the depreacted `go.opentelemetry.io/otel/metric/instrument/{asyncfloat64,asyncint64,syncfloat64,syncint64}` packages.(#3575, #3586)
- `Float64ObservableCounter` replaces the `asyncfloat64.Counter`
- `Float64ObservableUpDownCounter` replaces the `asyncfloat64.UpDownCounter`
- `Float64ObservableGauge` replaces the `asyncfloat64.Gauge`

View File

@ -55,7 +55,7 @@ func ExampleMeter_asynchronous_single() {
_, err := meter.Int64ObservableGauge(
"DiskUsage",
instrument.WithUnit(unit.Bytes),
instrument.WithInt64Callback(func(ctx context.Context, inst instrument.Int64Observer) error {
instrument.WithInt64Callback(func(_ context.Context, obsrv instrument.Int64Observer) error {
// Do the real work here to get the real disk usage. For example,
//
// usage, err := GetDiskUsage(diskID)
@ -69,7 +69,7 @@ func ExampleMeter_asynchronous_single() {
//
// For demonstration purpose, a static value is used here.
usage := 75000
inst.Observe(ctx, int64(usage), attribute.Int("disk.id", 3))
obsrv.Observe(int64(usage), attribute.Int("disk.id", 3))
return nil
}),
)

View File

@ -21,45 +21,51 @@ import (
"go.opentelemetry.io/otel/metric/unit"
)
// Float64Observer is a recorder of float64 measurement values.
// Float64Observable describes a set of instruments used asynchronously to
// record float64 measurements once per collection cycle. Observations of
// these instruments are only made within a callback.
//
// Warning: methods may be added to this interface in minor releases.
type Float64Observer interface {
type Float64Observable interface {
Asynchronous
// Observe records the measurement value for a set of attributes.
//
// It is only valid to call this within a callback. If called outside of
// the registered callback it should have no effect on the instrument, and
// an error will be reported via the error handler.
Observe(ctx context.Context, value float64, attributes ...attribute.KeyValue)
float64Observable()
}
// Float64ObservableCounter is an instrument used to asynchronously record
// increasing float64 measurements once per a measurement collection cycle. The
// Observe method is used to record the measured state of the instrument when
// it is called. Implementations will assume the observed value to be the
// cumulative sum of the count.
// increasing float64 measurements once per collection cycle. Observations are
// only made within a callback for this instrument. The value observed is
// assumed the to be the cumulative sum of the count.
//
// Warning: methods may be added to this interface in minor releases.
type Float64ObservableCounter interface{ Float64Observer }
type Float64ObservableCounter interface{ Float64Observable }
// Float64ObservableUpDownCounter is an instrument used to asynchronously
// record float64 measurements once per a measurement collection cycle. The
// Observe method is used to record the measured state of the instrument when
// it is called. Implementations will assume the observed value to be the
// cumulative sum of the count.
// record float64 measurements once per collection cycle. Observations are only
// made within a callback for this instrument. The value observed is assumed
// the to be the cumulative sum of the count.
//
// Warning: methods may be added to this interface in minor releases.
type Float64ObservableUpDownCounter interface{ Float64Observer }
type Float64ObservableUpDownCounter interface{ Float64Observable }
// Float64ObservableGauge is an instrument used to asynchronously record
// instantaneous float64 measurements once per a measurement collection cycle.
// instantaneous float64 measurements once per collection cycle. Observations
// are only made within a callback for this instrument.
//
// Warning: methods may be added to this interface in minor releases.
type Float64ObservableGauge interface{ Float64Observer }
type Float64ObservableGauge interface{ Float64Observable }
// Float64Observer is a recorder of float64 measurements.
//
// Warning: methods may be added to this interface in minor releases.
type Float64Observer interface {
Observe(value float64, attributes ...attribute.KeyValue)
}
// Float64Callback is a function registered with a Meter that makes
// observations for a Float64Observer it is registered with.
// observations for a Float64Observerable instrument it is registered with.
// Calls to the Float64Observer record measurement values for the
// Float64Observable.
//
// The function needs to complete in a finite amount of time and the deadline
// of the passed context is expected to be honored.

View File

@ -35,8 +35,8 @@ func TestFloat64ObserverOptions(t *testing.T) {
got := NewFloat64ObserverConfig(
WithDescription(desc),
WithUnit(uBytes),
WithFloat64Callback(func(ctx context.Context, o Float64Observer) error {
o.Observe(ctx, token)
WithFloat64Callback(func(ctx context.Context, obsrv Float64Observer) error {
obsrv.Observe(token)
return nil
}),
)
@ -57,6 +57,6 @@ type float64Observer struct {
got float64
}
func (o *float64Observer) Observe(_ context.Context, v float64, _ ...attribute.KeyValue) {
func (o *float64Observer) Observe(v float64, _ ...attribute.KeyValue) {
o.got = v
}

View File

@ -21,46 +21,51 @@ import (
"go.opentelemetry.io/otel/metric/unit"
)
// Int64Observer is a recorder of int64 measurement values.
// Int64Observable describes a set of instruments used asynchronously to record
// int64 measurements once per collection cycle. Observations of these
// instruments are only made within a callback.
//
// Warning: methods may be added to this interface in minor releases.
type Int64Observer interface {
type Int64Observable interface {
Asynchronous
// Observe records the measurement value for a set of attributes.
//
// It is only valid to call this within a callback. If called outside of
// the registered callback it should have no effect on the instrument, and
// an error will be reported via the error handler.
Observe(ctx context.Context, value int64, attributes ...attribute.KeyValue)
int64Observable()
}
// Int64ObservableCounter is an instrument used to asynchronously record
// increasing int64 measurements once per a measurement collection cycle. The
// Observe method is used to record the measured state of the instrument when
// it is called. Implementations will assume the observed value to be the
// cumulative sum of the count.
// increasing int64 measurements once per collection cycle. Observations are
// only made within a callback for this instrument. The value observed is
// assumed the to be the cumulative sum of the count.
//
// Warning: methods may be added to this interface in minor releases.
type Int64ObservableCounter interface{ Int64Observer }
type Int64ObservableCounter interface{ Int64Observable }
// Int64ObservableUpDownCounter is an instrument used to asynchronously record
// int64 measurements once per a measurement collection cycle. The Observe
// method is used to record the measured state of the instrument when it is
// called. Implementations will assume the observed value to be the cumulative
// sum of the count.
// int64 measurements once per collection cycle. Observations are only made
// within a callback for this instrument. The value observed is assumed the to
// be the cumulative sum of the count.
//
// Warning: methods may be added to this interface in minor releases.
type Int64ObservableUpDownCounter interface{ Int64Observer }
type Int64ObservableUpDownCounter interface{ Int64Observable }
// Int64ObservableGauge is an instrument used to asynchronously record
// instantaneous int64 measurements once per a measurement collection cycle.
// instantaneous int64 measurements once per collection cycle. Observations are
// only made within a callback for this instrument.
//
// Warning: methods may be added to this interface in minor releases.
type Int64ObservableGauge interface{ Int64Observer }
type Int64ObservableGauge interface{ Int64Observable }
// Int64Observer is a recorder of int64 measurements.
//
// Warning: methods may be added to this interface in minor releases.
type Int64Observer interface {
Observe(value int64, attributes ...attribute.KeyValue)
}
// Int64Callback is a function registered with a Meter that makes
// observations for an Int64Observer it is registered with.
// observations for a Int64Observerable instrument it is registered with.
// Calls to the Int64Observer record measurement values for the
// Int64Observable.
//
// The function needs to complete in a finite amount of time and the deadline
// of the passed context is expected to be honored.

View File

@ -35,8 +35,8 @@ func TestInt64ObserverOptions(t *testing.T) {
got := NewInt64ObserverConfig(
WithDescription(desc),
WithUnit(uBytes),
WithInt64Callback(func(ctx context.Context, o Int64Observer) error {
o.Observe(ctx, token)
WithInt64Callback(func(_ context.Context, obsrv Int64Observer) error {
obsrv.Observe(token)
return nil
}),
)
@ -57,6 +57,6 @@ type int64Observer struct {
got int64
}
func (o *int64Observer) Observe(_ context.Context, v int64, _ ...attribute.KeyValue) {
func (o *int64Observer) Observe(v int64, _ ...attribute.KeyValue) {
o.got = v
}

View File

@ -30,12 +30,12 @@ type unwrapper interface {
}
type afCounter struct {
instrument.Float64Observable
name string
opts []instrument.Float64ObserverOption
delegate atomic.Value //instrument.Float64ObservableCounter
instrument.Asynchronous
}
var _ unwrapper = (*afCounter)(nil)
@ -50,12 +50,6 @@ func (i *afCounter) setDelegate(m metric.Meter) {
i.delegate.Store(ctr)
}
func (i *afCounter) Observe(ctx context.Context, x float64, attrs ...attribute.KeyValue) {
if ctr := i.delegate.Load(); ctr != nil {
ctr.(instrument.Float64ObservableCounter).Observe(ctx, x, attrs...)
}
}
func (i *afCounter) Unwrap() instrument.Asynchronous {
if ctr := i.delegate.Load(); ctr != nil {
return ctr.(instrument.Float64ObservableCounter)
@ -64,12 +58,12 @@ func (i *afCounter) Unwrap() instrument.Asynchronous {
}
type afUpDownCounter struct {
instrument.Float64Observable
name string
opts []instrument.Float64ObserverOption
delegate atomic.Value //instrument.Float64ObservableUpDownCounter
instrument.Asynchronous
}
var _ unwrapper = (*afUpDownCounter)(nil)
@ -84,12 +78,6 @@ func (i *afUpDownCounter) setDelegate(m metric.Meter) {
i.delegate.Store(ctr)
}
func (i *afUpDownCounter) Observe(ctx context.Context, x float64, attrs ...attribute.KeyValue) {
if ctr := i.delegate.Load(); ctr != nil {
ctr.(instrument.Float64ObservableUpDownCounter).Observe(ctx, x, attrs...)
}
}
func (i *afUpDownCounter) Unwrap() instrument.Asynchronous {
if ctr := i.delegate.Load(); ctr != nil {
return ctr.(instrument.Float64ObservableUpDownCounter)
@ -98,14 +86,17 @@ func (i *afUpDownCounter) Unwrap() instrument.Asynchronous {
}
type afGauge struct {
instrument.Float64Observable
name string
opts []instrument.Float64ObserverOption
delegate atomic.Value //instrument.Float64ObservableGauge
instrument.Asynchronous
}
var _ unwrapper = (*afGauge)(nil)
var _ instrument.Float64ObservableGauge = (*afGauge)(nil)
func (i *afGauge) setDelegate(m metric.Meter) {
ctr, err := m.Float64ObservableGauge(i.name, i.opts...)
if err != nil {
@ -115,15 +106,6 @@ func (i *afGauge) setDelegate(m metric.Meter) {
i.delegate.Store(ctr)
}
var _ unwrapper = (*afGauge)(nil)
var _ instrument.Float64ObservableGauge = (*afGauge)(nil)
func (i *afGauge) Observe(ctx context.Context, x float64, attrs ...attribute.KeyValue) {
if ctr := i.delegate.Load(); ctr != nil {
ctr.(instrument.Float64ObservableGauge).Observe(ctx, x, attrs...)
}
}
func (i *afGauge) Unwrap() instrument.Asynchronous {
if ctr := i.delegate.Load(); ctr != nil {
return ctr.(instrument.Float64ObservableGauge)
@ -132,12 +114,12 @@ func (i *afGauge) Unwrap() instrument.Asynchronous {
}
type aiCounter struct {
instrument.Int64Observable
name string
opts []instrument.Int64ObserverOption
delegate atomic.Value //instrument.Int64ObservableCounter
instrument.Asynchronous
}
var _ unwrapper = (*aiCounter)(nil)
@ -152,12 +134,6 @@ func (i *aiCounter) setDelegate(m metric.Meter) {
i.delegate.Store(ctr)
}
func (i *aiCounter) Observe(ctx context.Context, x int64, attrs ...attribute.KeyValue) {
if ctr := i.delegate.Load(); ctr != nil {
ctr.(instrument.Int64ObservableCounter).Observe(ctx, x, attrs...)
}
}
func (i *aiCounter) Unwrap() instrument.Asynchronous {
if ctr := i.delegate.Load(); ctr != nil {
return ctr.(instrument.Int64ObservableCounter)
@ -166,12 +142,12 @@ func (i *aiCounter) Unwrap() instrument.Asynchronous {
}
type aiUpDownCounter struct {
instrument.Int64Observable
name string
opts []instrument.Int64ObserverOption
delegate atomic.Value //instrument.Int64ObservableUpDownCounter
instrument.Asynchronous
}
var _ unwrapper = (*aiUpDownCounter)(nil)
@ -186,12 +162,6 @@ func (i *aiUpDownCounter) setDelegate(m metric.Meter) {
i.delegate.Store(ctr)
}
func (i *aiUpDownCounter) Observe(ctx context.Context, x int64, attrs ...attribute.KeyValue) {
if ctr := i.delegate.Load(); ctr != nil {
ctr.(instrument.Int64ObservableUpDownCounter).Observe(ctx, x, attrs...)
}
}
func (i *aiUpDownCounter) Unwrap() instrument.Asynchronous {
if ctr := i.delegate.Load(); ctr != nil {
return ctr.(instrument.Int64ObservableUpDownCounter)
@ -200,12 +170,12 @@ func (i *aiUpDownCounter) Unwrap() instrument.Asynchronous {
}
type aiGauge struct {
instrument.Int64Observable
name string
opts []instrument.Int64ObserverOption
delegate atomic.Value //instrument.Int64ObservableGauge
instrument.Asynchronous
}
var _ unwrapper = (*aiGauge)(nil)
@ -220,12 +190,6 @@ func (i *aiGauge) setDelegate(m metric.Meter) {
i.delegate.Store(ctr)
}
func (i *aiGauge) Observe(ctx context.Context, x int64, attrs ...attribute.KeyValue) {
if ctr := i.delegate.Load(); ctr != nil {
ctr.(instrument.Int64ObservableGauge).Observe(ctx, x, attrs...)
}
}
func (i *aiGauge) Unwrap() instrument.Asynchronous {
if ctr := i.delegate.Load(); ctr != nil {
return ctr.(instrument.Int64ObservableGauge)

View File

@ -62,17 +62,20 @@ func TestAsyncInstrumentSetDelegateRace(t *testing.T) {
t.Run("Float64", func(t *testing.T) {
t.Run("Counter", func(t *testing.T) {
delegate := &afCounter{}
testFloat64Race(delegate.Observe, delegate.setDelegate)
f := func(context.Context, float64, ...attribute.KeyValue) { _ = delegate.Unwrap() }
testFloat64Race(f, delegate.setDelegate)
})
t.Run("UpDownCounter", func(t *testing.T) {
delegate := &afUpDownCounter{}
testFloat64Race(delegate.Observe, delegate.setDelegate)
f := func(context.Context, float64, ...attribute.KeyValue) { _ = delegate.Unwrap() }
testFloat64Race(f, delegate.setDelegate)
})
t.Run("Gauge", func(t *testing.T) {
delegate := &afGauge{}
testFloat64Race(delegate.Observe, delegate.setDelegate)
f := func(context.Context, float64, ...attribute.KeyValue) { _ = delegate.Unwrap() }
testFloat64Race(f, delegate.setDelegate)
})
})
@ -81,17 +84,20 @@ func TestAsyncInstrumentSetDelegateRace(t *testing.T) {
t.Run("Int64", func(t *testing.T) {
t.Run("Counter", func(t *testing.T) {
delegate := &aiCounter{}
testInt64Race(delegate.Observe, delegate.setDelegate)
f := func(context.Context, int64, ...attribute.KeyValue) { _ = delegate.Unwrap() }
testInt64Race(f, delegate.setDelegate)
})
t.Run("UpDownCounter", func(t *testing.T) {
delegate := &aiUpDownCounter{}
testInt64Race(delegate.Observe, delegate.setDelegate)
f := func(context.Context, int64, ...attribute.KeyValue) { _ = delegate.Unwrap() }
testInt64Race(f, delegate.setDelegate)
})
t.Run("Gauge", func(t *testing.T) {
delegate := &aiGauge{}
testInt64Race(delegate.Observe, delegate.setDelegate)
f := func(context.Context, int64, ...attribute.KeyValue) { _ = delegate.Unwrap() }
testInt64Race(f, delegate.setDelegate)
})
})
}
@ -138,11 +144,11 @@ func TestSyncInstrumentSetDelegateRace(t *testing.T) {
type testCountingFloatInstrument struct {
count int
instrument.Asynchronous
instrument.Float64Observable
instrument.Synchronous
}
func (i *testCountingFloatInstrument) Observe(context.Context, float64, ...attribute.KeyValue) {
func (i *testCountingFloatInstrument) observe() {
i.count++
}
func (i *testCountingFloatInstrument) Add(context.Context, float64, ...attribute.KeyValue) {
@ -155,11 +161,11 @@ func (i *testCountingFloatInstrument) Record(context.Context, float64, ...attrib
type testCountingIntInstrument struct {
count int
instrument.Asynchronous
instrument.Int64Observable
instrument.Synchronous
}
func (i *testCountingIntInstrument) Observe(context.Context, int64, ...attribute.KeyValue) {
func (i *testCountingIntInstrument) observe() {
i.count++
}
func (i *testCountingIntInstrument) Add(context.Context, int64, ...attribute.KeyValue) {

View File

@ -148,10 +148,16 @@ type observationRecorder struct {
ctx context.Context
}
func (o observationRecorder) ObserveFloat64(i instrument.Float64Observer, value float64, attr ...attribute.KeyValue) {
i.Observe(o.ctx, value, attr...)
func (o observationRecorder) ObserveFloat64(i instrument.Float64Observable, value float64, attr ...attribute.KeyValue) {
iImpl, ok := i.(*testCountingFloatInstrument)
if ok {
iImpl.observe()
}
}
func (o observationRecorder) ObserveInt64(i instrument.Int64Observer, value int64, attr ...attribute.KeyValue) {
i.Observe(o.ctx, value, attr...)
func (o observationRecorder) ObserveInt64(i instrument.Int64Observable, value int64, attr ...attribute.KeyValue) {
iImpl, ok := i.(*testCountingIntInstrument)
if ok {
iImpl.observe()
}
}

View File

@ -123,9 +123,9 @@ type Callback func(context.Context, Observer) error
// Observer records measurements for multiple instruments in a Callback.
type Observer interface {
// ObserveFloat64 records the float64 value with attributes for obsrv.
ObserveFloat64(obsrv instrument.Float64Observer, value float64, attributes ...attribute.KeyValue)
ObserveFloat64(obsrv instrument.Float64Observable, value float64, attributes ...attribute.KeyValue)
// ObserveInt64 records the int64 value with attributes for obsrv.
ObserveInt64(obsrv instrument.Int64Observer, value int64, attributes ...attribute.KeyValue)
ObserveInt64(obsrv instrument.Int64Observable, value int64, attributes ...attribute.KeyValue)
}
// Registration is an token representing the unique registration of a callback

View File

@ -97,7 +97,7 @@ type noopReg struct{}
func (noopReg) Unregister() error { return nil }
type nonrecordingAsyncFloat64Instrument struct {
instrument.Asynchronous
instrument.Float64Observable
}
var (
@ -118,12 +118,8 @@ func (n nonrecordingAsyncFloat64Instrument) Gauge(string, ...instrument.Float64O
return n, nil
}
func (nonrecordingAsyncFloat64Instrument) Observe(context.Context, float64, ...attribute.KeyValue) {
}
type nonrecordingAsyncInt64Instrument struct {
instrument.Asynchronous
instrument.Int64Observable
}
var (
@ -144,9 +140,6 @@ func (n nonrecordingAsyncInt64Instrument) Gauge(string, ...instrument.Int64Obser
return n, nil
}
func (nonrecordingAsyncInt64Instrument) Observe(context.Context, int64, ...attribute.KeyValue) {
}
type nonrecordingSyncFloat64Instrument struct {
instrument.Synchronous
}

View File

@ -72,45 +72,3 @@ func TestSyncInt64(t *testing.T) {
inst.Record(context.Background(), 1, attribute.String("key", "value"))
})
}
func TestAsyncFloat64(t *testing.T) {
meter := NewNoopMeterProvider().Meter("test instrumentation")
assert.NotPanics(t, func() {
inst, err := meter.Float64ObservableCounter("test instrument")
require.NoError(t, err)
inst.Observe(context.Background(), 1.0, attribute.String("key", "value"))
})
assert.NotPanics(t, func() {
inst, err := meter.Float64ObservableUpDownCounter("test instrument")
require.NoError(t, err)
inst.Observe(context.Background(), -1.0, attribute.String("key", "value"))
})
assert.NotPanics(t, func() {
inst, err := meter.Float64ObservableGauge("test instrument")
require.NoError(t, err)
inst.Observe(context.Background(), 1.0, attribute.String("key", "value"))
})
}
func TestAsyncInt64(t *testing.T) {
meter := NewNoopMeterProvider().Meter("test instrumentation")
assert.NotPanics(t, func() {
inst, err := meter.Int64ObservableCounter("test instrument")
require.NoError(t, err)
inst.Observe(context.Background(), 1, attribute.String("key", "value"))
})
assert.NotPanics(t, func() {
inst, err := meter.Int64ObservableUpDownCounter("test instrument")
require.NoError(t, err)
inst.Observe(context.Background(), -1, attribute.String("key", "value"))
})
assert.NotPanics(t, func() {
inst, err := meter.Int64ObservableGauge("test instrument")
require.NoError(t, err)
inst.Observe(context.Background(), 1, attribute.String("key", "value"))
})
}

View File

@ -20,7 +20,6 @@ import (
"fmt"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/internal/global"
"go.opentelemetry.io/otel/metric/instrument"
"go.opentelemetry.io/otel/metric/unit"
"go.opentelemetry.io/otel/sdk/instrumentation"
@ -211,6 +210,36 @@ type observablID[N int64 | float64] struct {
scope instrumentation.Scope
}
type float64Observable struct {
instrument.Float64Observable
*observable[float64]
}
var _ instrument.Float64ObservableCounter = float64Observable{}
var _ instrument.Float64ObservableUpDownCounter = float64Observable{}
var _ instrument.Float64ObservableGauge = float64Observable{}
func newFloat64Observable(scope instrumentation.Scope, kind InstrumentKind, name, desc string, u unit.Unit, agg []internal.Aggregator[float64]) float64Observable {
return float64Observable{
observable: newObservable[float64](scope, kind, name, desc, u, agg),
}
}
type int64Observable struct {
instrument.Int64Observable
*observable[int64]
}
var _ instrument.Int64ObservableCounter = int64Observable{}
var _ instrument.Int64ObservableUpDownCounter = int64Observable{}
var _ instrument.Int64ObservableGauge = int64Observable{}
func newInt64Observable(scope instrumentation.Scope, kind InstrumentKind, name, desc string, u unit.Unit, agg []internal.Aggregator[int64]) int64Observable {
return int64Observable{
observable: newObservable[int64](scope, kind, name, desc, u, agg),
}
}
type observable[N int64 | float64] struct {
instrument.Asynchronous
observablID[N]
@ -231,25 +260,6 @@ func newObservable[N int64 | float64](scope instrumentation.Scope, kind Instrume
}
}
var _ instrument.Float64ObservableCounter = (*observable[float64])(nil)
var _ instrument.Float64ObservableUpDownCounter = (*observable[float64])(nil)
var _ instrument.Float64ObservableGauge = (*observable[float64])(nil)
var _ instrument.Int64ObservableCounter = (*observable[int64])(nil)
var _ instrument.Int64ObservableUpDownCounter = (*observable[int64])(nil)
var _ instrument.Int64ObservableGauge = (*observable[int64])(nil)
// Observe logs an error.
func (o *observable[N]) Observe(ctx context.Context, val N, attrs ...attribute.KeyValue) {
var zero N
err := errors.New("invalid observation")
global.Error(err, "dropping observation made outside a callback",
"name", o.name,
"description", o.description,
"unit", o.unit,
"number", fmt.Sprintf("%T", zero),
)
}
// observe records the val for the set of attrs.
func (o *observable[N]) observe(val N, attrs []attribute.KeyValue) {
for _, agg := range o.aggregators {

View File

@ -232,7 +232,7 @@ func (m *meter) RegisterCallback(f metric.Callback, insts ...instrument.Asynchro
}
switch o := inst.(type) {
case *observable[int64]:
case int64Observable:
if err := o.registerable(m.scope); err != nil {
if !errors.Is(err, errEmptyAgg) {
errs.append(err)
@ -240,7 +240,7 @@ func (m *meter) RegisterCallback(f metric.Callback, insts ...instrument.Asynchro
continue
}
reg.registerInt64(o.observablID)
case *observable[float64]:
case float64Observable:
if err := o.registerable(m.scope); err != nil {
if !errors.Is(err, errEmptyAgg) {
errs.append(err)
@ -298,10 +298,10 @@ var (
errUnregObserver = errors.New("observable instrument not registered for callback")
)
func (r observer) ObserveFloat64(o instrument.Float64Observer, v float64, a ...attribute.KeyValue) {
var oImpl *observable[float64]
func (r observer) ObserveFloat64(o instrument.Float64Observable, v float64, a ...attribute.KeyValue) {
var oImpl float64Observable
switch conv := o.(type) {
case *observable[float64]:
case float64Observable:
oImpl = conv
case interface {
Unwrap() instrument.Asynchronous
@ -309,7 +309,7 @@ func (r observer) ObserveFloat64(o instrument.Float64Observer, v float64, a ...a
// Unwrap any global.
async := conv.Unwrap()
var ok bool
if oImpl, ok = async.(*observable[float64]); !ok {
if oImpl, ok = async.(float64Observable); !ok {
global.Error(errUnknownObserver, "failed to record asynchronous")
return
}
@ -330,10 +330,10 @@ func (r observer) ObserveFloat64(o instrument.Float64Observer, v float64, a ...a
oImpl.observe(v, a)
}
func (r observer) ObserveInt64(o instrument.Int64Observer, v int64, a ...attribute.KeyValue) {
var oImpl *observable[int64]
func (r observer) ObserveInt64(o instrument.Int64Observable, v int64, a ...attribute.KeyValue) {
var oImpl int64Observable
switch conv := o.(type) {
case *observable[int64]:
case int64Observable:
oImpl = conv
case interface {
Unwrap() instrument.Asynchronous
@ -341,7 +341,7 @@ func (r observer) ObserveInt64(o instrument.Int64Observer, v int64, a ...attribu
// Unwrap any global.
async := conv.Unwrap()
var ok bool
if oImpl, ok = async.(*observable[int64]); !ok {
if oImpl, ok = async.(int64Observable); !ok {
global.Error(errUnknownObserver, "failed to record asynchronous")
return
}
@ -398,13 +398,13 @@ func (p *instProvider[N]) lookup(kind InstrumentKind, name, desc string, u unit.
type int64ObservProvider struct{ *instProvider[int64] }
func (p int64ObservProvider) lookup(kind InstrumentKind, name, desc string, u unit.Unit) (*observable[int64], error) {
func (p int64ObservProvider) lookup(kind InstrumentKind, name, desc string, u unit.Unit) (int64Observable, error) {
aggs, err := p.aggs(kind, name, desc, u)
return newObservable(p.scope, kind, name, desc, u, aggs), err
return newInt64Observable(p.scope, kind, name, desc, u, aggs), err
}
func (p int64ObservProvider) registerCallbacks(inst *observable[int64], cBacks []instrument.Int64Callback) {
if inst == nil {
func (p int64ObservProvider) registerCallbacks(inst int64Observable, cBacks []instrument.Int64Callback) {
if inst.observable == nil || len(inst.aggregators) == 0 {
// Drop aggregator.
return
}
@ -414,20 +414,28 @@ func (p int64ObservProvider) registerCallbacks(inst *observable[int64], cBacks [
}
}
func (p int64ObservProvider) callback(i *observable[int64], f instrument.Int64Callback) func(context.Context) error {
inst := callbackObserver[int64]{i}
func (p int64ObservProvider) callback(i int64Observable, f instrument.Int64Callback) func(context.Context) error {
inst := int64Observer{i}
return func(ctx context.Context) error { return f(ctx, inst) }
}
type int64Observer struct {
int64Observable
}
func (o int64Observer) Observe(val int64, attrs ...attribute.KeyValue) {
o.observe(val, attrs)
}
type float64ObservProvider struct{ *instProvider[float64] }
func (p float64ObservProvider) lookup(kind InstrumentKind, name, desc string, u unit.Unit) (*observable[float64], error) {
func (p float64ObservProvider) lookup(kind InstrumentKind, name, desc string, u unit.Unit) (float64Observable, error) {
aggs, err := p.aggs(kind, name, desc, u)
return newObservable(p.scope, kind, name, desc, u, aggs), err
return newFloat64Observable(p.scope, kind, name, desc, u, aggs), err
}
func (p float64ObservProvider) registerCallbacks(inst *observable[float64], cBacks []instrument.Float64Callback) {
if inst == nil {
func (p float64ObservProvider) registerCallbacks(inst float64Observable, cBacks []instrument.Float64Callback) {
if inst.observable == nil || len(inst.aggregators) == 0 {
// Drop aggregator.
return
}
@ -437,17 +445,15 @@ func (p float64ObservProvider) registerCallbacks(inst *observable[float64], cBac
}
}
func (p float64ObservProvider) callback(i *observable[float64], f instrument.Float64Callback) func(context.Context) error {
inst := callbackObserver[float64]{i}
func (p float64ObservProvider) callback(i float64Observable, f instrument.Float64Callback) func(context.Context) error {
inst := float64Observer{i}
return func(ctx context.Context) error { return f(ctx, inst) }
}
// callbackObserver is an observer that records values for a wrapped
// observable.
type callbackObserver[N int64 | float64] struct {
*observable[N]
type float64Observer struct {
float64Observable
}
func (o callbackObserver[N]) Observe(_ context.Context, val N, attrs ...attribute.KeyValue) {
func (o float64Observer) Observe(val float64, attrs ...attribute.KeyValue) {
o.observe(val, attrs)
}

View File

@ -179,8 +179,8 @@ func TestMeterCreatesInstruments(t *testing.T) {
{
name: "ObservableInt64Count",
fn: func(t *testing.T, m metric.Meter) {
cback := func(ctx context.Context, o instrument.Int64Observer) error {
o.Observe(ctx, 4, attrs...)
cback := func(_ context.Context, o instrument.Int64Observer) error {
o.Observe(4, attrs...)
return nil
}
ctr, err := m.Int64ObservableCounter("aint", instrument.WithInt64Callback(cback))
@ -190,9 +190,6 @@ func TestMeterCreatesInstruments(t *testing.T) {
return nil
}, ctr)
assert.NoError(t, err)
// Observed outside of a callback, it should be ignored.
ctr.Observe(context.Background(), 19)
},
want: metricdata.Metrics{
Name: "aint",
@ -209,8 +206,8 @@ func TestMeterCreatesInstruments(t *testing.T) {
{
name: "ObservableInt64UpDownCount",
fn: func(t *testing.T, m metric.Meter) {
cback := func(ctx context.Context, o instrument.Int64Observer) error {
o.Observe(ctx, 4, attrs...)
cback := func(_ context.Context, o instrument.Int64Observer) error {
o.Observe(4, attrs...)
return nil
}
ctr, err := m.Int64ObservableUpDownCounter("aint", instrument.WithInt64Callback(cback))
@ -220,9 +217,6 @@ func TestMeterCreatesInstruments(t *testing.T) {
return nil
}, ctr)
assert.NoError(t, err)
// Observed outside of a callback, it should be ignored.
ctr.Observe(context.Background(), 19)
},
want: metricdata.Metrics{
Name: "aint",
@ -239,8 +233,8 @@ func TestMeterCreatesInstruments(t *testing.T) {
{
name: "ObservableInt64Gauge",
fn: func(t *testing.T, m metric.Meter) {
cback := func(ctx context.Context, o instrument.Int64Observer) error {
o.Observe(ctx, 4, attrs...)
cback := func(_ context.Context, o instrument.Int64Observer) error {
o.Observe(4, attrs...)
return nil
}
gauge, err := m.Int64ObservableGauge("agauge", instrument.WithInt64Callback(cback))
@ -250,9 +244,6 @@ func TestMeterCreatesInstruments(t *testing.T) {
return nil
}, gauge)
assert.NoError(t, err)
// Observed outside of a callback, it should be ignored.
gauge.Observe(context.Background(), 19)
},
want: metricdata.Metrics{
Name: "agauge",
@ -267,8 +258,8 @@ func TestMeterCreatesInstruments(t *testing.T) {
{
name: "ObservableFloat64Count",
fn: func(t *testing.T, m metric.Meter) {
cback := func(ctx context.Context, o instrument.Float64Observer) error {
o.Observe(ctx, 4, attrs...)
cback := func(_ context.Context, o instrument.Float64Observer) error {
o.Observe(4, attrs...)
return nil
}
ctr, err := m.Float64ObservableCounter("afloat", instrument.WithFloat64Callback(cback))
@ -278,9 +269,6 @@ func TestMeterCreatesInstruments(t *testing.T) {
return nil
}, ctr)
assert.NoError(t, err)
// Observed outside of a callback, it should be ignored.
ctr.Observe(context.Background(), 19)
},
want: metricdata.Metrics{
Name: "afloat",
@ -297,8 +285,8 @@ func TestMeterCreatesInstruments(t *testing.T) {
{
name: "ObservableFloat64UpDownCount",
fn: func(t *testing.T, m metric.Meter) {
cback := func(ctx context.Context, o instrument.Float64Observer) error {
o.Observe(ctx, 4, attrs...)
cback := func(_ context.Context, o instrument.Float64Observer) error {
o.Observe(4, attrs...)
return nil
}
ctr, err := m.Float64ObservableUpDownCounter("afloat", instrument.WithFloat64Callback(cback))
@ -308,9 +296,6 @@ func TestMeterCreatesInstruments(t *testing.T) {
return nil
}, ctr)
assert.NoError(t, err)
// Observed outside of a callback, it should be ignored.
ctr.Observe(context.Background(), 19)
},
want: metricdata.Metrics{
Name: "afloat",
@ -327,8 +312,8 @@ func TestMeterCreatesInstruments(t *testing.T) {
{
name: "ObservableFloat64Gauge",
fn: func(t *testing.T, m metric.Meter) {
cback := func(ctx context.Context, o instrument.Float64Observer) error {
o.Observe(ctx, 4, attrs...)
cback := func(_ context.Context, o instrument.Float64Observer) error {
o.Observe(4, attrs...)
return nil
}
gauge, err := m.Float64ObservableGauge("agauge", instrument.WithFloat64Callback(cback))
@ -338,9 +323,6 @@ func TestMeterCreatesInstruments(t *testing.T) {
return nil
}, gauge)
assert.NoError(t, err)
// Observed outside of a callback, it should be ignored.
gauge.Observe(context.Background(), 19)
},
want: metricdata.Metrics{
Name: "agauge",
@ -564,10 +546,9 @@ func TestCallbackObserverNonRegistered(t *testing.T) {
fCtr, err := m2.Float64ObservableCounter("float64 ctr")
require.NoError(t, err)
// Panics if Observe is called.
type int64Obsrv struct{ instrument.Int64Observer }
type int64Obsrv struct{ instrument.Int64Observable }
int64Foreign := int64Obsrv{}
type float64Obsrv struct{ instrument.Float64Observer }
type float64Obsrv struct{ instrument.Float64Observable }
float64Foreign := float64Obsrv{}
_, err = m1.RegisterCallback(
@ -1311,9 +1292,9 @@ func TestAsynchronousExample(t *testing.T) {
observations := make(map[attribute.Set]int64)
_, err := meter.Int64ObservableCounter(instName, instrument.WithInt64Callback(
func(ctx context.Context, o instrument.Int64Observer) error {
func(_ context.Context, o instrument.Int64Observer) error {
for attrSet, val := range observations {
o.Observe(ctx, val, attrSet.ToSlice()...)
o.Observe(val, attrSet.ToSlice()...)
}
return nil
},