You've already forked opentelemetry-go
mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2025-12-16 00:11:27 +02:00
Make Meter a struct, simplify the global Meter (#709)
* Tests pass * Precommit pass * More lint * Remove a few interfaces * Final edits * Fix comments * Indentation * registry->unique * Comments
This commit is contained in:
@@ -37,7 +37,7 @@ func (*testTraceProvider) Tracer(_ string) trace.Tracer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (*testMeterProvider) Meter(_ string) metric.Meter {
|
func (*testMeterProvider) Meter(_ string) metric.Meter {
|
||||||
return &metric.NoopMeter{}
|
return metric.Meter{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMultipleGlobalTracerProvider(t *testing.T) {
|
func TestMultipleGlobalTracerProvider(t *testing.T) {
|
||||||
|
|||||||
@@ -49,22 +49,27 @@ import (
|
|||||||
type meterProvider struct {
|
type meterProvider struct {
|
||||||
delegate metric.Provider
|
delegate metric.Provider
|
||||||
|
|
||||||
lock sync.Mutex
|
// lock protects `delegate` and `meters`.
|
||||||
meters map[string]*meter
|
lock sync.Mutex
|
||||||
|
|
||||||
|
// meters maintains a unique entry for every named Meter
|
||||||
|
// that has been registered through the global instance.
|
||||||
|
meters map[string]*meterEntry
|
||||||
}
|
}
|
||||||
|
|
||||||
type meter struct {
|
type meterImpl struct {
|
||||||
delegate unsafe.Pointer // (*metric.Meter)
|
delegate unsafe.Pointer // (*metric.MeterImpl)
|
||||||
|
|
||||||
provider *meterProvider
|
|
||||||
name string
|
|
||||||
|
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
registry map[string]metric.InstrumentImpl
|
|
||||||
syncInsts []*syncImpl
|
syncInsts []*syncImpl
|
||||||
asyncInsts []*asyncImpl
|
asyncInsts []*asyncImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type meterEntry struct {
|
||||||
|
unique metric.MeterImpl
|
||||||
|
impl meterImpl
|
||||||
|
}
|
||||||
|
|
||||||
type instrument struct {
|
type instrument struct {
|
||||||
descriptor metric.Descriptor
|
descriptor metric.Descriptor
|
||||||
}
|
}
|
||||||
@@ -73,8 +78,6 @@ type syncImpl struct {
|
|||||||
delegate unsafe.Pointer // (*metric.SyncImpl)
|
delegate unsafe.Pointer // (*metric.SyncImpl)
|
||||||
|
|
||||||
instrument
|
instrument
|
||||||
|
|
||||||
constructor func(metric.Meter) (metric.SyncImpl, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type asyncImpl struct {
|
type asyncImpl struct {
|
||||||
@@ -82,7 +85,7 @@ type asyncImpl struct {
|
|||||||
|
|
||||||
instrument
|
instrument
|
||||||
|
|
||||||
constructor func(metric.Meter) (metric.AsyncImpl, error)
|
callback func(func(metric.Number, []core.KeyValue))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SyncImpler is implemented by all of the sync metric
|
// SyncImpler is implemented by all of the sync metric
|
||||||
@@ -107,7 +110,7 @@ type syncHandle struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var _ metric.Provider = &meterProvider{}
|
var _ metric.Provider = &meterProvider{}
|
||||||
var _ metric.Meter = &meter{}
|
var _ metric.MeterImpl = &meterImpl{}
|
||||||
var _ metric.InstrumentImpl = &syncImpl{}
|
var _ metric.InstrumentImpl = &syncImpl{}
|
||||||
var _ metric.BoundSyncImpl = &syncHandle{}
|
var _ metric.BoundSyncImpl = &syncHandle{}
|
||||||
var _ metric.AsyncImpl = &asyncImpl{}
|
var _ metric.AsyncImpl = &asyncImpl{}
|
||||||
@@ -120,7 +123,7 @@ func (inst *instrument) Descriptor() metric.Descriptor {
|
|||||||
|
|
||||||
func newMeterProvider() *meterProvider {
|
func newMeterProvider() *meterProvider {
|
||||||
return &meterProvider{
|
return &meterProvider{
|
||||||
meters: map[string]*meter{},
|
meters: map[string]*meterEntry{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,8 +132,8 @@ func (p *meterProvider) setDelegate(provider metric.Provider) {
|
|||||||
defer p.lock.Unlock()
|
defer p.lock.Unlock()
|
||||||
|
|
||||||
p.delegate = provider
|
p.delegate = provider
|
||||||
for _, m := range p.meters {
|
for name, entry := range p.meters {
|
||||||
m.setDelegate(provider)
|
entry.impl.setDelegate(name, provider)
|
||||||
}
|
}
|
||||||
p.meters = nil
|
p.meters = nil
|
||||||
}
|
}
|
||||||
@@ -143,29 +146,24 @@ func (p *meterProvider) Meter(name string) metric.Meter {
|
|||||||
return p.delegate.Meter(name)
|
return p.delegate.Meter(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if exm, ok := p.meters[name]; ok {
|
entry, ok := p.meters[name]
|
||||||
return exm
|
if !ok {
|
||||||
}
|
entry = &meterEntry{}
|
||||||
|
entry.unique = registry.NewUniqueInstrumentMeterImpl(&entry.impl)
|
||||||
|
p.meters[name] = entry
|
||||||
|
|
||||||
m := &meter{
|
|
||||||
provider: p,
|
|
||||||
name: name,
|
|
||||||
registry: map[string]metric.InstrumentImpl{},
|
|
||||||
syncInsts: []*syncImpl{},
|
|
||||||
asyncInsts: []*asyncImpl{},
|
|
||||||
}
|
}
|
||||||
p.meters[name] = m
|
return metric.WrapMeterImpl(entry.unique, name)
|
||||||
return m
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Meter interface and delegation
|
// Meter interface and delegation
|
||||||
|
|
||||||
func (m *meter) setDelegate(provider metric.Provider) {
|
func (m *meterImpl) setDelegate(name string, provider metric.Provider) {
|
||||||
m.lock.Lock()
|
m.lock.Lock()
|
||||||
defer m.lock.Unlock()
|
defer m.lock.Unlock()
|
||||||
|
|
||||||
d := new(metric.Meter)
|
d := new(metric.MeterImpl)
|
||||||
*d = provider.Meter(m.name)
|
*d = provider.Meter(name).MeterImpl()
|
||||||
m.delegate = unsafe.Pointer(d)
|
m.delegate = unsafe.Pointer(d)
|
||||||
|
|
||||||
for _, inst := range m.syncInsts {
|
for _, inst := range m.syncInsts {
|
||||||
@@ -178,49 +176,30 @@ func (m *meter) setDelegate(provider metric.Provider) {
|
|||||||
m.asyncInsts = nil
|
m.asyncInsts = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *meter) newSync(desc metric.Descriptor, constructor func(metric.Meter) (metric.SyncImpl, error)) (metric.SyncImpl, error) {
|
func (m *meterImpl) NewSyncInstrument(desc metric.Descriptor) (metric.SyncImpl, error) {
|
||||||
m.lock.Lock()
|
m.lock.Lock()
|
||||||
defer m.lock.Unlock()
|
defer m.lock.Unlock()
|
||||||
|
|
||||||
if meterPtr := (*metric.Meter)(atomic.LoadPointer(&m.delegate)); meterPtr != nil {
|
if meterPtr := (*metric.MeterImpl)(atomic.LoadPointer(&m.delegate)); meterPtr != nil {
|
||||||
return constructor(*meterPtr)
|
return (*meterPtr).NewSyncInstrument(desc)
|
||||||
}
|
|
||||||
|
|
||||||
if ex, ok := m.registry[desc.Name()]; ok {
|
|
||||||
if !registry.Compatible(desc, ex.Descriptor()) {
|
|
||||||
return nil, registry.NewMetricKindMismatchError(ex.Descriptor())
|
|
||||||
}
|
|
||||||
return ex.(metric.SyncImpl), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inst := &syncImpl{
|
inst := &syncImpl{
|
||||||
instrument: instrument{
|
instrument: instrument{
|
||||||
descriptor: desc,
|
descriptor: desc,
|
||||||
},
|
},
|
||||||
constructor: constructor,
|
|
||||||
}
|
}
|
||||||
m.syncInsts = append(m.syncInsts, inst)
|
m.syncInsts = append(m.syncInsts, inst)
|
||||||
m.registry[desc.Name()] = inst
|
|
||||||
return inst, nil
|
return inst, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func syncCheck(has SyncImpler, err error) (metric.SyncImpl, error) {
|
|
||||||
if has != nil {
|
|
||||||
return has.SyncImpl(), err
|
|
||||||
}
|
|
||||||
if err == nil {
|
|
||||||
err = metric.ErrSDKReturnedNilImpl
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Synchronous delegation
|
// Synchronous delegation
|
||||||
|
|
||||||
func (inst *syncImpl) setDelegate(d metric.Meter) {
|
func (inst *syncImpl) setDelegate(d metric.MeterImpl) {
|
||||||
implPtr := new(metric.SyncImpl)
|
implPtr := new(metric.SyncImpl)
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
*implPtr, err = inst.constructor(d)
|
*implPtr, err = d.NewSyncInstrument(inst.descriptor)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO: There is no standard way to deliver this error to the user.
|
// TODO: There is no standard way to deliver this error to the user.
|
||||||
@@ -264,29 +243,25 @@ func (bound *syncHandle) Unbind() {
|
|||||||
|
|
||||||
// Async delegation
|
// Async delegation
|
||||||
|
|
||||||
func (m *meter) newAsync(desc metric.Descriptor, constructor func(metric.Meter) (metric.AsyncImpl, error)) (metric.AsyncImpl, error) {
|
func (m *meterImpl) NewAsyncInstrument(
|
||||||
|
desc metric.Descriptor,
|
||||||
|
callback func(func(metric.Number, []core.KeyValue)),
|
||||||
|
) (metric.AsyncImpl, error) {
|
||||||
|
|
||||||
m.lock.Lock()
|
m.lock.Lock()
|
||||||
defer m.lock.Unlock()
|
defer m.lock.Unlock()
|
||||||
|
|
||||||
if meterPtr := (*metric.Meter)(atomic.LoadPointer(&m.delegate)); meterPtr != nil {
|
if meterPtr := (*metric.MeterImpl)(atomic.LoadPointer(&m.delegate)); meterPtr != nil {
|
||||||
return constructor(*meterPtr)
|
return (*meterPtr).NewAsyncInstrument(desc, callback)
|
||||||
}
|
|
||||||
|
|
||||||
if ex, ok := m.registry[desc.Name()]; ok {
|
|
||||||
if !registry.Compatible(desc, ex.Descriptor()) {
|
|
||||||
return nil, registry.NewMetricKindMismatchError(ex.Descriptor())
|
|
||||||
}
|
|
||||||
return ex.(metric.AsyncImpl), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inst := &asyncImpl{
|
inst := &asyncImpl{
|
||||||
instrument: instrument{
|
instrument: instrument{
|
||||||
descriptor: desc,
|
descriptor: desc,
|
||||||
},
|
},
|
||||||
constructor: constructor,
|
callback: callback,
|
||||||
}
|
}
|
||||||
m.asyncInsts = append(m.asyncInsts, inst)
|
m.asyncInsts = append(m.asyncInsts, inst)
|
||||||
m.registry[desc.Name()] = inst
|
|
||||||
return inst, nil
|
return inst, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,21 +272,11 @@ func (obs *asyncImpl) Implementation() interface{} {
|
|||||||
return obs
|
return obs
|
||||||
}
|
}
|
||||||
|
|
||||||
func asyncCheck(has AsyncImpler, err error) (metric.AsyncImpl, error) {
|
func (obs *asyncImpl) setDelegate(d metric.MeterImpl) {
|
||||||
if has != nil {
|
|
||||||
return has.AsyncImpl(), err
|
|
||||||
}
|
|
||||||
if err == nil {
|
|
||||||
err = metric.ErrSDKReturnedNilImpl
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (obs *asyncImpl) setDelegate(d metric.Meter) {
|
|
||||||
implPtr := new(metric.AsyncImpl)
|
implPtr := new(metric.AsyncImpl)
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
*implPtr, err = obs.constructor(d)
|
*implPtr, err = d.NewAsyncInstrument(obs.descriptor, obs.callback)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO: There is no standard way to deliver this error to the user.
|
// TODO: There is no standard way to deliver this error to the user.
|
||||||
@@ -326,8 +291,8 @@ func (obs *asyncImpl) setDelegate(d metric.Meter) {
|
|||||||
|
|
||||||
// Metric updates
|
// Metric updates
|
||||||
|
|
||||||
func (m *meter) RecordBatch(ctx context.Context, labels []core.KeyValue, measurements ...metric.Measurement) {
|
func (m *meterImpl) RecordBatch(ctx context.Context, labels []core.KeyValue, measurements ...metric.Measurement) {
|
||||||
if delegatePtr := (*metric.Meter)(atomic.LoadPointer(&m.delegate)); delegatePtr != nil {
|
if delegatePtr := (*metric.MeterImpl)(atomic.LoadPointer(&m.delegate)); delegatePtr != nil {
|
||||||
(*delegatePtr).RecordBatch(ctx, labels, measurements...)
|
(*delegatePtr).RecordBatch(ctx, labels, measurements...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -363,64 +328,10 @@ func (bound *syncHandle) RecordOne(ctx context.Context, number metric.Number) {
|
|||||||
(*implPtr).RecordOne(ctx, number)
|
(*implPtr).RecordOne(ctx, number)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructors
|
|
||||||
|
|
||||||
func (m *meter) withName(opts []metric.Option) []metric.Option {
|
|
||||||
return append(opts, metric.WithLibraryName(m.name))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *meter) NewInt64Counter(name string, opts ...metric.Option) (metric.Int64Counter, error) {
|
|
||||||
return metric.WrapInt64CounterInstrument(m.newSync(
|
|
||||||
metric.NewDescriptor(name, metric.CounterKind, metric.Int64NumberKind, m.withName(opts)...),
|
|
||||||
func(other metric.Meter) (metric.SyncImpl, error) {
|
|
||||||
return syncCheck(other.NewInt64Counter(name, opts...))
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *meter) NewFloat64Counter(name string, opts ...metric.Option) (metric.Float64Counter, error) {
|
|
||||||
return metric.WrapFloat64CounterInstrument(m.newSync(
|
|
||||||
metric.NewDescriptor(name, metric.CounterKind, metric.Float64NumberKind, m.withName(opts)...),
|
|
||||||
func(other metric.Meter) (metric.SyncImpl, error) {
|
|
||||||
return syncCheck(other.NewFloat64Counter(name, opts...))
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *meter) NewInt64Measure(name string, opts ...metric.Option) (metric.Int64Measure, error) {
|
|
||||||
return metric.WrapInt64MeasureInstrument(m.newSync(
|
|
||||||
metric.NewDescriptor(name, metric.MeasureKind, metric.Int64NumberKind, m.withName(opts)...),
|
|
||||||
func(other metric.Meter) (metric.SyncImpl, error) {
|
|
||||||
return syncCheck(other.NewInt64Measure(name, opts...))
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *meter) NewFloat64Measure(name string, opts ...metric.Option) (metric.Float64Measure, error) {
|
|
||||||
return metric.WrapFloat64MeasureInstrument(m.newSync(
|
|
||||||
metric.NewDescriptor(name, metric.MeasureKind, metric.Float64NumberKind, m.withName(opts)...),
|
|
||||||
func(other metric.Meter) (metric.SyncImpl, error) {
|
|
||||||
return syncCheck(other.NewFloat64Measure(name, opts...))
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *meter) RegisterInt64Observer(name string, callback metric.Int64ObserverCallback, opts ...metric.Option) (metric.Int64Observer, error) {
|
|
||||||
return metric.WrapInt64ObserverInstrument(m.newAsync(
|
|
||||||
metric.NewDescriptor(name, metric.ObserverKind, metric.Int64NumberKind, m.withName(opts)...),
|
|
||||||
func(other metric.Meter) (metric.AsyncImpl, error) {
|
|
||||||
return asyncCheck(other.RegisterInt64Observer(name, callback, opts...))
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *meter) RegisterFloat64Observer(name string, callback metric.Float64ObserverCallback, opts ...metric.Option) (metric.Float64Observer, error) {
|
|
||||||
return metric.WrapFloat64ObserverInstrument(m.newAsync(
|
|
||||||
metric.NewDescriptor(name, metric.ObserverKind, metric.Float64NumberKind, m.withName(opts)...),
|
|
||||||
func(other metric.Meter) (metric.AsyncImpl, error) {
|
|
||||||
return asyncCheck(other.RegisterFloat64Observer(name, callback, opts...))
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
func AtomicFieldOffsets() map[string]uintptr {
|
func AtomicFieldOffsets() map[string]uintptr {
|
||||||
return map[string]uintptr{
|
return map[string]uintptr{
|
||||||
"meterProvider.delegate": unsafe.Offsetof(meterProvider{}.delegate),
|
"meterProvider.delegate": unsafe.Offsetof(meterProvider{}.delegate),
|
||||||
"meter.delegate": unsafe.Offsetof(meter{}.delegate),
|
"meterImpl.delegate": unsafe.Offsetof(meterImpl{}.delegate),
|
||||||
"syncImpl.delegate": unsafe.Offsetof(syncImpl{}.delegate),
|
"syncImpl.delegate": unsafe.Offsetof(syncImpl{}.delegate),
|
||||||
"asyncImpl.delegate": unsafe.Offsetof(asyncImpl{}.delegate),
|
"asyncImpl.delegate": unsafe.Offsetof(asyncImpl{}.delegate),
|
||||||
"syncHandle.delegate": unsafe.Offsetof(syncHandle{}.delegate),
|
"syncHandle.delegate": unsafe.Offsetof(syncHandle{}.delegate),
|
||||||
|
|||||||
@@ -280,15 +280,15 @@ type meterProviderWithConstructorError struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type meterWithConstructorError struct {
|
type meterWithConstructorError struct {
|
||||||
metric.Meter
|
metric.MeterImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *meterProviderWithConstructorError) Meter(name string) metric.Meter {
|
func (m *meterProviderWithConstructorError) Meter(name string) metric.Meter {
|
||||||
return &meterWithConstructorError{m.Provider.Meter(name)}
|
return metric.WrapMeterImpl(&meterWithConstructorError{m.Provider.Meter(name).MeterImpl()}, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *meterWithConstructorError) NewInt64Counter(name string, opts ...metric.Option) (metric.Int64Counter, error) {
|
func (m *meterWithConstructorError) NewSyncInstrument(_ metric.Descriptor) (metric.SyncImpl, error) {
|
||||||
return metric.Int64Counter{}, errors.New("constructor error")
|
return metric.NoopSync{}, errors.New("constructor error")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestErrorInDeferredConstructor(t *testing.T) {
|
func TestErrorInDeferredConstructor(t *testing.T) {
|
||||||
|
|||||||
@@ -135,38 +135,99 @@ func (d Descriptor) LibraryName() string {
|
|||||||
return d.config.LibraryName
|
return d.config.LibraryName
|
||||||
}
|
}
|
||||||
|
|
||||||
// Meter is an interface to the metrics portion of the OpenTelemetry SDK.
|
// Meter is the OpenTelemetry metric API, based on a `MeterImpl`
|
||||||
type Meter interface {
|
// implementation and the `Meter` library name.
|
||||||
// RecordBatch atomically records a batch of measurements.
|
//
|
||||||
RecordBatch(context.Context, []core.KeyValue, ...Measurement)
|
// An uninitialized Meter is a no-op implementation.
|
||||||
|
type Meter struct {
|
||||||
|
impl MeterImpl
|
||||||
|
libraryName string
|
||||||
|
}
|
||||||
|
|
||||||
// All instrument constructors may return an error for
|
// RecordBatch atomically records a batch of measurements.
|
||||||
// conditions such as:
|
func (m Meter) RecordBatch(ctx context.Context, ls []core.KeyValue, ms ...Measurement) {
|
||||||
// `name` is an empty string
|
if m.impl == nil {
|
||||||
// `name` was previously registered as a different kind of instrument
|
return
|
||||||
// for a given named `Meter`.
|
}
|
||||||
|
m.impl.RecordBatch(ctx, ls, ms...)
|
||||||
|
}
|
||||||
|
|
||||||
// NewInt64Counter creates a new integral counter with a given
|
// NewInt64Counter creates a new integer Counter instrument with the
|
||||||
// name and customized with passed options.
|
// given name, customized with options. May return an error if the
|
||||||
NewInt64Counter(name string, opts ...Option) (Int64Counter, error)
|
// name is invalid (e.g., empty) or improperly registered (e.g.,
|
||||||
// NewFloat64Counter creates a new floating point counter with
|
// duplicate registration).
|
||||||
// a given name and customized with passed options.
|
func (m Meter) NewInt64Counter(name string, options ...Option) (Int64Counter, error) {
|
||||||
NewFloat64Counter(name string, opts ...Option) (Float64Counter, error)
|
return wrapInt64CounterInstrument(
|
||||||
// NewInt64Measure creates a new integral measure with a given
|
m.newSync(name, CounterKind, Int64NumberKind, options))
|
||||||
// name and customized with passed options.
|
}
|
||||||
NewInt64Measure(name string, opts ...Option) (Int64Measure, error)
|
|
||||||
// NewFloat64Measure creates a new floating point measure with
|
|
||||||
// a given name and customized with passed options.
|
|
||||||
NewFloat64Measure(name string, opts ...Option) (Float64Measure, error)
|
|
||||||
|
|
||||||
// RegisterInt64Observer creates a new integral observer with a
|
// NewFloat64Counter creates a new floating point Counter with the
|
||||||
// given name, running a given callback, and customized with passed
|
// given name, customized with options. May return an error if the
|
||||||
// options. Callback may be nil.
|
// name is invalid (e.g., empty) or improperly registered (e.g.,
|
||||||
RegisterInt64Observer(name string, callback Int64ObserverCallback, opts ...Option) (Int64Observer, error)
|
// duplicate registration).
|
||||||
// RegisterFloat64Observer creates a new floating point observer
|
func (m Meter) NewFloat64Counter(name string, options ...Option) (Float64Counter, error) {
|
||||||
// with a given name, running a given callback, and customized with
|
return wrapFloat64CounterInstrument(
|
||||||
// passed options. Callback may be nil.
|
m.newSync(name, CounterKind, Float64NumberKind, options))
|
||||||
RegisterFloat64Observer(name string, callback Float64ObserverCallback, opts ...Option) (Float64Observer, error)
|
}
|
||||||
|
|
||||||
|
// NewInt64Measure creates a new integer Measure instrument with the
|
||||||
|
// given name, customized with options. May return an error if the
|
||||||
|
// name is invalid (e.g., empty) or improperly registered (e.g.,
|
||||||
|
// duplicate registration).
|
||||||
|
func (m Meter) NewInt64Measure(name string, opts ...Option) (Int64Measure, error) {
|
||||||
|
return wrapInt64MeasureInstrument(
|
||||||
|
m.newSync(name, MeasureKind, Int64NumberKind, opts))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFloat64Measure creates a new floating point Measure with the
|
||||||
|
// given name, customized with options. May return an error if the
|
||||||
|
// name is invalid (e.g., empty) or improperly registered (e.g.,
|
||||||
|
// duplicate registration).
|
||||||
|
func (m Meter) NewFloat64Measure(name string, opts ...Option) (Float64Measure, error) {
|
||||||
|
return wrapFloat64MeasureInstrument(
|
||||||
|
m.newSync(name, MeasureKind, Float64NumberKind, opts))
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterInt64Observer creates a new integer Observer instrument
|
||||||
|
// with the given name, running a given callback, and customized with
|
||||||
|
// options. May return an error if the name is invalid (e.g., empty)
|
||||||
|
// or improperly registered (e.g., duplicate registration).
|
||||||
|
func (m Meter) RegisterInt64Observer(name string, callback Int64ObserverCallback, opts ...Option) (Int64Observer, error) {
|
||||||
|
if callback == nil {
|
||||||
|
return wrapInt64ObserverInstrument(NoopAsync{}, nil)
|
||||||
|
}
|
||||||
|
return wrapInt64ObserverInstrument(
|
||||||
|
m.newAsync(name, ObserverKind, Int64NumberKind, opts,
|
||||||
|
func(observe func(Number, []core.KeyValue)) {
|
||||||
|
callback(Int64ObserverResult{observe})
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterFloat64Observer creates a new floating point Observer with
|
||||||
|
// the given name, running a given callback, and customized with
|
||||||
|
// options. May return an error if the name is invalid (e.g., empty)
|
||||||
|
// or improperly registered (e.g., duplicate registration).
|
||||||
|
func (m Meter) RegisterFloat64Observer(name string, callback Float64ObserverCallback, opts ...Option) (Float64Observer, error) {
|
||||||
|
if callback == nil {
|
||||||
|
return wrapFloat64ObserverInstrument(NoopAsync{}, nil)
|
||||||
|
}
|
||||||
|
return wrapFloat64ObserverInstrument(
|
||||||
|
m.newAsync(name, ObserverKind, Float64NumberKind, opts,
|
||||||
|
func(observe func(Number, []core.KeyValue)) {
|
||||||
|
callback(Float64ObserverResult{observe})
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Observe captures a single integer value from the associated
|
||||||
|
// instrument callback, with the given labels.
|
||||||
|
func (io Int64ObserverResult) Observe(value int64, labels ...core.KeyValue) {
|
||||||
|
io.observe(NewInt64Number(value), labels)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Observe captures a single floating point value from the associated
|
||||||
|
// instrument callback, with the given labels.
|
||||||
|
func (fo Float64ObserverResult) Observe(value float64, labels ...core.KeyValue) {
|
||||||
|
fo.observe(NewFloat64Number(value), labels)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithDescription applies provided description.
|
// WithDescription applies provided description.
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type NoopProvider struct{}
|
type NoopProvider struct{}
|
||||||
type NoopMeter struct{}
|
|
||||||
|
|
||||||
type noopInstrument struct{}
|
type noopInstrument struct{}
|
||||||
type noopBoundInstrument struct{}
|
type noopBoundInstrument struct{}
|
||||||
@@ -29,13 +28,12 @@ type NoopSync struct{ noopInstrument }
|
|||||||
type NoopAsync struct{ noopInstrument }
|
type NoopAsync struct{ noopInstrument }
|
||||||
|
|
||||||
var _ Provider = NoopProvider{}
|
var _ Provider = NoopProvider{}
|
||||||
var _ Meter = NoopMeter{}
|
|
||||||
var _ SyncImpl = NoopSync{}
|
var _ SyncImpl = NoopSync{}
|
||||||
var _ BoundSyncImpl = noopBoundInstrument{}
|
var _ BoundSyncImpl = noopBoundInstrument{}
|
||||||
var _ AsyncImpl = NoopAsync{}
|
var _ AsyncImpl = NoopAsync{}
|
||||||
|
|
||||||
func (NoopProvider) Meter(name string) Meter {
|
func (NoopProvider) Meter(name string) Meter {
|
||||||
return NoopMeter{}
|
return Meter{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (noopInstrument) Implementation() interface{} {
|
func (noopInstrument) Implementation() interface{} {
|
||||||
@@ -58,30 +56,3 @@ func (NoopSync) Bind([]core.KeyValue) BoundSyncImpl {
|
|||||||
|
|
||||||
func (NoopSync) RecordOne(context.Context, Number, []core.KeyValue) {
|
func (NoopSync) RecordOne(context.Context, Number, []core.KeyValue) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (NoopMeter) RecordBatch(context.Context, []core.KeyValue, ...Measurement) {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (NoopMeter) NewInt64Counter(string, ...Option) (Int64Counter, error) {
|
|
||||||
return Int64Counter{syncInstrument{NoopSync{}}}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (NoopMeter) NewFloat64Counter(string, ...Option) (Float64Counter, error) {
|
|
||||||
return Float64Counter{syncInstrument{NoopSync{}}}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (NoopMeter) NewInt64Measure(string, ...Option) (Int64Measure, error) {
|
|
||||||
return Int64Measure{syncInstrument{NoopSync{}}}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (NoopMeter) NewFloat64Measure(string, ...Option) (Float64Measure, error) {
|
|
||||||
return Float64Measure{syncInstrument{NoopSync{}}}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (NoopMeter) RegisterInt64Observer(string, Int64ObserverCallback, ...Option) (Int64Observer, error) {
|
|
||||||
return Int64Observer{asyncInstrument{NoopAsync{}}}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (NoopMeter) RegisterFloat64Observer(string, Float64ObserverCallback, ...Option) (Float64Observer, error) {
|
|
||||||
return Float64Observer{asyncInstrument{NoopAsync{}}}, nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -14,20 +14,6 @@
|
|||||||
|
|
||||||
package metric
|
package metric
|
||||||
|
|
||||||
import "go.opentelemetry.io/otel/api/core"
|
|
||||||
|
|
||||||
// Int64ObserverResult is an interface for reporting integral
|
|
||||||
// observations.
|
|
||||||
type Int64ObserverResult interface {
|
|
||||||
Observe(value int64, labels ...core.KeyValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float64ObserverResult is an interface for reporting floating point
|
|
||||||
// observations.
|
|
||||||
type Float64ObserverResult interface {
|
|
||||||
Observe(value float64, labels ...core.KeyValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int64ObserverCallback is a type of callback that integral
|
// Int64ObserverCallback is a type of callback that integral
|
||||||
// observers run.
|
// observers run.
|
||||||
type Int64ObserverCallback func(result Int64ObserverResult)
|
type Int64ObserverCallback func(result Int64ObserverResult)
|
||||||
|
|||||||
@@ -20,10 +20,8 @@ import (
|
|||||||
"go.opentelemetry.io/otel/api/core"
|
"go.opentelemetry.io/otel/api/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MeterImpl is a convenient interface for SDK and test
|
// MeterImpl is the interface an SDK must implement to supply a Meter
|
||||||
// implementations that would provide a `Meter` but do not wish to
|
// implementation.
|
||||||
// re-implement the API's type-safe interfaces. Helpers provided in
|
|
||||||
// this package will construct a `Meter` given a `MeterImpl`.
|
|
||||||
type MeterImpl interface {
|
type MeterImpl interface {
|
||||||
// RecordBatch atomically records a batch of measurements.
|
// RecordBatch atomically records a batch of measurements.
|
||||||
RecordBatch(context.Context, []core.KeyValue, ...Measurement)
|
RecordBatch(context.Context, []core.KeyValue, ...Measurement)
|
||||||
@@ -83,35 +81,20 @@ type BoundSyncImpl interface {
|
|||||||
// asynchronous instrument (e.g., Observer instruments).
|
// asynchronous instrument (e.g., Observer instruments).
|
||||||
type AsyncImpl interface {
|
type AsyncImpl interface {
|
||||||
InstrumentImpl
|
InstrumentImpl
|
||||||
|
|
||||||
// Note: An `Unregister()` API could be supported here.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// wrappedMeterImpl implements the `Meter` interface given a
|
// Int64ObserverResult is passed to an observer callback to capture
|
||||||
// `MeterImpl` implementation.
|
// observations for one asynchronous integer metric instrument.
|
||||||
type wrappedMeterImpl struct {
|
type Int64ObserverResult struct {
|
||||||
impl MeterImpl
|
|
||||||
libraryName string
|
|
||||||
}
|
|
||||||
|
|
||||||
// int64ObserverResult is an adapter for int64-valued asynchronous
|
|
||||||
// callbacks.
|
|
||||||
type int64ObserverResult struct {
|
|
||||||
observe func(Number, []core.KeyValue)
|
observe func(Number, []core.KeyValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
// float64ObserverResult is an adapter for float64-valued asynchronous
|
// Float64ObserverResult is passed to an observer callback to capture
|
||||||
// callbacks.
|
// observations for one asynchronous floating point metric instrument.
|
||||||
type float64ObserverResult struct {
|
type Float64ObserverResult struct {
|
||||||
observe func(Number, []core.KeyValue)
|
observe func(Number, []core.KeyValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
_ Meter = (*wrappedMeterImpl)(nil)
|
|
||||||
_ Int64ObserverResult = int64ObserverResult{}
|
|
||||||
_ Float64ObserverResult = float64ObserverResult{}
|
|
||||||
)
|
|
||||||
|
|
||||||
// Configure is a helper that applies all the options to a Config.
|
// Configure is a helper that applies all the options to a Config.
|
||||||
func Configure(opts []Option) Config {
|
func Configure(opts []Option) Config {
|
||||||
var config Config
|
var config Config
|
||||||
@@ -124,131 +107,87 @@ func Configure(opts []Option) Config {
|
|||||||
// WrapMeterImpl constructs a `Meter` implementation from a
|
// WrapMeterImpl constructs a `Meter` implementation from a
|
||||||
// `MeterImpl` implementation.
|
// `MeterImpl` implementation.
|
||||||
func WrapMeterImpl(impl MeterImpl, libraryName string) Meter {
|
func WrapMeterImpl(impl MeterImpl, libraryName string) Meter {
|
||||||
return &wrappedMeterImpl{
|
return Meter{
|
||||||
impl: impl,
|
impl: impl,
|
||||||
libraryName: libraryName,
|
libraryName: libraryName,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *wrappedMeterImpl) RecordBatch(ctx context.Context, ls []core.KeyValue, ms ...Measurement) {
|
// MeterImpl returns the underlying MeterImpl of this Meter.
|
||||||
m.impl.RecordBatch(ctx, ls, ms...)
|
func (m Meter) MeterImpl() MeterImpl {
|
||||||
|
return m.impl
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *wrappedMeterImpl) newSync(name string, metricKind Kind, numberKind NumberKind, opts []Option) (SyncImpl, error) {
|
// newSync constructs one new synchronous instrument.
|
||||||
|
func (m Meter) newSync(name string, metricKind Kind, numberKind NumberKind, opts []Option) (SyncImpl, error) {
|
||||||
|
if m.impl == nil {
|
||||||
|
return NoopSync{}, nil
|
||||||
|
}
|
||||||
desc := NewDescriptor(name, metricKind, numberKind, opts...)
|
desc := NewDescriptor(name, metricKind, numberKind, opts...)
|
||||||
desc.config.LibraryName = m.libraryName
|
desc.config.LibraryName = m.libraryName
|
||||||
return m.impl.NewSyncInstrument(desc)
|
return m.impl.NewSyncInstrument(desc)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *wrappedMeterImpl) NewInt64Counter(name string, opts ...Option) (Int64Counter, error) {
|
// wrapInt64CounterInstrument returns an `Int64Counter` from a
|
||||||
return WrapInt64CounterInstrument(
|
|
||||||
m.newSync(name, CounterKind, Int64NumberKind, opts))
|
|
||||||
}
|
|
||||||
|
|
||||||
// WrapInt64CounterInstrument returns an `Int64Counter` from a
|
|
||||||
// `SyncImpl`. An error will be generated if the
|
// `SyncImpl`. An error will be generated if the
|
||||||
// `SyncImpl` is nil (in which case a No-op is substituted),
|
// `SyncImpl` is nil (in which case a No-op is substituted),
|
||||||
// otherwise the error passes through.
|
// otherwise the error passes through.
|
||||||
func WrapInt64CounterInstrument(syncInst SyncImpl, err error) (Int64Counter, error) {
|
func wrapInt64CounterInstrument(syncInst SyncImpl, err error) (Int64Counter, error) {
|
||||||
common, err := checkNewSync(syncInst, err)
|
common, err := checkNewSync(syncInst, err)
|
||||||
return Int64Counter{syncInstrument: common}, err
|
return Int64Counter{syncInstrument: common}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *wrappedMeterImpl) NewFloat64Counter(name string, opts ...Option) (Float64Counter, error) {
|
// wrapFloat64CounterInstrument returns an `Float64Counter` from a
|
||||||
return WrapFloat64CounterInstrument(
|
|
||||||
m.newSync(name, CounterKind, Float64NumberKind, opts))
|
|
||||||
}
|
|
||||||
|
|
||||||
// WrapFloat64CounterInstrument returns an `Float64Counter` from a
|
|
||||||
// `SyncImpl`. An error will be generated if the
|
// `SyncImpl`. An error will be generated if the
|
||||||
// `SyncImpl` is nil (in which case a No-op is substituted),
|
// `SyncImpl` is nil (in which case a No-op is substituted),
|
||||||
// otherwise the error passes through.
|
// otherwise the error passes through.
|
||||||
func WrapFloat64CounterInstrument(syncInst SyncImpl, err error) (Float64Counter, error) {
|
func wrapFloat64CounterInstrument(syncInst SyncImpl, err error) (Float64Counter, error) {
|
||||||
common, err := checkNewSync(syncInst, err)
|
common, err := checkNewSync(syncInst, err)
|
||||||
return Float64Counter{syncInstrument: common}, err
|
return Float64Counter{syncInstrument: common}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *wrappedMeterImpl) NewInt64Measure(name string, opts ...Option) (Int64Measure, error) {
|
// wrapInt64MeasureInstrument returns an `Int64Measure` from a
|
||||||
return WrapInt64MeasureInstrument(
|
|
||||||
m.newSync(name, MeasureKind, Int64NumberKind, opts))
|
|
||||||
}
|
|
||||||
|
|
||||||
// WrapInt64MeasureInstrument returns an `Int64Measure` from a
|
|
||||||
// `SyncImpl`. An error will be generated if the
|
// `SyncImpl`. An error will be generated if the
|
||||||
// `SyncImpl` is nil (in which case a No-op is substituted),
|
// `SyncImpl` is nil (in which case a No-op is substituted),
|
||||||
// otherwise the error passes through.
|
// otherwise the error passes through.
|
||||||
func WrapInt64MeasureInstrument(syncInst SyncImpl, err error) (Int64Measure, error) {
|
func wrapInt64MeasureInstrument(syncInst SyncImpl, err error) (Int64Measure, error) {
|
||||||
common, err := checkNewSync(syncInst, err)
|
common, err := checkNewSync(syncInst, err)
|
||||||
return Int64Measure{syncInstrument: common}, err
|
return Int64Measure{syncInstrument: common}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *wrappedMeterImpl) NewFloat64Measure(name string, opts ...Option) (Float64Measure, error) {
|
// wrapFloat64MeasureInstrument returns an `Float64Measure` from a
|
||||||
return WrapFloat64MeasureInstrument(
|
|
||||||
m.newSync(name, MeasureKind, Float64NumberKind, opts))
|
|
||||||
}
|
|
||||||
|
|
||||||
// WrapFloat64MeasureInstrument returns an `Float64Measure` from a
|
|
||||||
// `SyncImpl`. An error will be generated if the
|
// `SyncImpl`. An error will be generated if the
|
||||||
// `SyncImpl` is nil (in which case a No-op is substituted),
|
// `SyncImpl` is nil (in which case a No-op is substituted),
|
||||||
// otherwise the error passes through.
|
// otherwise the error passes through.
|
||||||
func WrapFloat64MeasureInstrument(syncInst SyncImpl, err error) (Float64Measure, error) {
|
func wrapFloat64MeasureInstrument(syncInst SyncImpl, err error) (Float64Measure, error) {
|
||||||
common, err := checkNewSync(syncInst, err)
|
common, err := checkNewSync(syncInst, err)
|
||||||
return Float64Measure{syncInstrument: common}, err
|
return Float64Measure{syncInstrument: common}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *wrappedMeterImpl) newAsync(name string, mkind Kind, nkind NumberKind, opts []Option, callback func(func(Number, []core.KeyValue))) (AsyncImpl, error) {
|
// newAsync constructs one new asynchronous instrument.
|
||||||
|
func (m Meter) newAsync(name string, mkind Kind, nkind NumberKind, opts []Option, callback func(func(Number, []core.KeyValue))) (AsyncImpl, error) {
|
||||||
|
if m.impl == nil {
|
||||||
|
return NoopAsync{}, nil
|
||||||
|
}
|
||||||
desc := NewDescriptor(name, mkind, nkind, opts...)
|
desc := NewDescriptor(name, mkind, nkind, opts...)
|
||||||
desc.config.LibraryName = m.libraryName
|
desc.config.LibraryName = m.libraryName
|
||||||
return m.impl.NewAsyncInstrument(desc, callback)
|
return m.impl.NewAsyncInstrument(desc, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *wrappedMeterImpl) RegisterInt64Observer(name string, callback Int64ObserverCallback, opts ...Option) (Int64Observer, error) {
|
// wrapInt64ObserverInstrument returns an `Int64Observer` from a
|
||||||
if callback == nil {
|
|
||||||
return NoopMeter{}.RegisterInt64Observer("", nil)
|
|
||||||
}
|
|
||||||
return WrapInt64ObserverInstrument(
|
|
||||||
m.newAsync(name, ObserverKind, Int64NumberKind, opts,
|
|
||||||
func(observe func(Number, []core.KeyValue)) {
|
|
||||||
// Note: this memory allocation could be avoided by
|
|
||||||
// using a pointer to this object and mutating it
|
|
||||||
// on each collection interval.
|
|
||||||
callback(int64ObserverResult{observe})
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
// WrapInt64ObserverInstrument returns an `Int64Observer` from a
|
|
||||||
// `AsyncImpl`. An error will be generated if the
|
// `AsyncImpl`. An error will be generated if the
|
||||||
// `AsyncImpl` is nil (in which case a No-op is substituted),
|
// `AsyncImpl` is nil (in which case a No-op is substituted),
|
||||||
// otherwise the error passes through.
|
// otherwise the error passes through.
|
||||||
func WrapInt64ObserverInstrument(asyncInst AsyncImpl, err error) (Int64Observer, error) {
|
func wrapInt64ObserverInstrument(asyncInst AsyncImpl, err error) (Int64Observer, error) {
|
||||||
common, err := checkNewAsync(asyncInst, err)
|
common, err := checkNewAsync(asyncInst, err)
|
||||||
return Int64Observer{asyncInstrument: common}, err
|
return Int64Observer{asyncInstrument: common}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *wrappedMeterImpl) RegisterFloat64Observer(name string, callback Float64ObserverCallback, opts ...Option) (Float64Observer, error) {
|
// wrapFloat64ObserverInstrument returns an `Float64Observer` from a
|
||||||
if callback == nil {
|
|
||||||
return NoopMeter{}.RegisterFloat64Observer("", nil)
|
|
||||||
}
|
|
||||||
return WrapFloat64ObserverInstrument(
|
|
||||||
m.newAsync(name, ObserverKind, Float64NumberKind, opts,
|
|
||||||
func(observe func(Number, []core.KeyValue)) {
|
|
||||||
callback(float64ObserverResult{observe})
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
// WrapFloat64ObserverInstrument returns an `Float64Observer` from a
|
|
||||||
// `AsyncImpl`. An error will be generated if the
|
// `AsyncImpl`. An error will be generated if the
|
||||||
// `AsyncImpl` is nil (in which case a No-op is substituted),
|
// `AsyncImpl` is nil (in which case a No-op is substituted),
|
||||||
// otherwise the error passes through.
|
// otherwise the error passes through.
|
||||||
func WrapFloat64ObserverInstrument(asyncInst AsyncImpl, err error) (Float64Observer, error) {
|
func wrapFloat64ObserverInstrument(asyncInst AsyncImpl, err error) (Float64Observer, error) {
|
||||||
common, err := checkNewAsync(asyncInst, err)
|
common, err := checkNewAsync(asyncInst, err)
|
||||||
return Float64Observer{asyncInstrument: common}, err
|
return Float64Observer{asyncInstrument: common}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (io int64ObserverResult) Observe(value int64, labels ...core.KeyValue) {
|
|
||||||
io.observe(NewInt64Number(value), labels)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fo float64ObserverResult) Observe(value float64, labels ...core.KeyValue) {
|
|
||||||
fo.observe(NewFloat64Number(value), labels)
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user