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 {
|
||||
return &metric.NoopMeter{}
|
||||
return metric.Meter{}
|
||||
}
|
||||
|
||||
func TestMultipleGlobalTracerProvider(t *testing.T) {
|
||||
|
||||
@@ -49,22 +49,27 @@ import (
|
||||
type meterProvider struct {
|
||||
delegate metric.Provider
|
||||
|
||||
// lock protects `delegate` and `meters`.
|
||||
lock sync.Mutex
|
||||
meters map[string]*meter
|
||||
|
||||
// meters maintains a unique entry for every named Meter
|
||||
// that has been registered through the global instance.
|
||||
meters map[string]*meterEntry
|
||||
}
|
||||
|
||||
type meter struct {
|
||||
delegate unsafe.Pointer // (*metric.Meter)
|
||||
|
||||
provider *meterProvider
|
||||
name string
|
||||
type meterImpl struct {
|
||||
delegate unsafe.Pointer // (*metric.MeterImpl)
|
||||
|
||||
lock sync.Mutex
|
||||
registry map[string]metric.InstrumentImpl
|
||||
syncInsts []*syncImpl
|
||||
asyncInsts []*asyncImpl
|
||||
}
|
||||
|
||||
type meterEntry struct {
|
||||
unique metric.MeterImpl
|
||||
impl meterImpl
|
||||
}
|
||||
|
||||
type instrument struct {
|
||||
descriptor metric.Descriptor
|
||||
}
|
||||
@@ -73,8 +78,6 @@ type syncImpl struct {
|
||||
delegate unsafe.Pointer // (*metric.SyncImpl)
|
||||
|
||||
instrument
|
||||
|
||||
constructor func(metric.Meter) (metric.SyncImpl, error)
|
||||
}
|
||||
|
||||
type asyncImpl struct {
|
||||
@@ -82,7 +85,7 @@ type asyncImpl struct {
|
||||
|
||||
instrument
|
||||
|
||||
constructor func(metric.Meter) (metric.AsyncImpl, error)
|
||||
callback func(func(metric.Number, []core.KeyValue))
|
||||
}
|
||||
|
||||
// SyncImpler is implemented by all of the sync metric
|
||||
@@ -107,7 +110,7 @@ type syncHandle struct {
|
||||
}
|
||||
|
||||
var _ metric.Provider = &meterProvider{}
|
||||
var _ metric.Meter = &meter{}
|
||||
var _ metric.MeterImpl = &meterImpl{}
|
||||
var _ metric.InstrumentImpl = &syncImpl{}
|
||||
var _ metric.BoundSyncImpl = &syncHandle{}
|
||||
var _ metric.AsyncImpl = &asyncImpl{}
|
||||
@@ -120,7 +123,7 @@ func (inst *instrument) Descriptor() metric.Descriptor {
|
||||
|
||||
func newMeterProvider() *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()
|
||||
|
||||
p.delegate = provider
|
||||
for _, m := range p.meters {
|
||||
m.setDelegate(provider)
|
||||
for name, entry := range p.meters {
|
||||
entry.impl.setDelegate(name, provider)
|
||||
}
|
||||
p.meters = nil
|
||||
}
|
||||
@@ -143,29 +146,24 @@ func (p *meterProvider) Meter(name string) metric.Meter {
|
||||
return p.delegate.Meter(name)
|
||||
}
|
||||
|
||||
if exm, ok := p.meters[name]; ok {
|
||||
return exm
|
||||
}
|
||||
entry, ok := p.meters[name]
|
||||
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 m
|
||||
return metric.WrapMeterImpl(entry.unique, name)
|
||||
}
|
||||
|
||||
// Meter interface and delegation
|
||||
|
||||
func (m *meter) setDelegate(provider metric.Provider) {
|
||||
func (m *meterImpl) setDelegate(name string, provider metric.Provider) {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
d := new(metric.Meter)
|
||||
*d = provider.Meter(m.name)
|
||||
d := new(metric.MeterImpl)
|
||||
*d = provider.Meter(name).MeterImpl()
|
||||
m.delegate = unsafe.Pointer(d)
|
||||
|
||||
for _, inst := range m.syncInsts {
|
||||
@@ -178,49 +176,30 @@ func (m *meter) setDelegate(provider metric.Provider) {
|
||||
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()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
if meterPtr := (*metric.Meter)(atomic.LoadPointer(&m.delegate)); meterPtr != nil {
|
||||
return constructor(*meterPtr)
|
||||
}
|
||||
|
||||
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
|
||||
if meterPtr := (*metric.MeterImpl)(atomic.LoadPointer(&m.delegate)); meterPtr != nil {
|
||||
return (*meterPtr).NewSyncInstrument(desc)
|
||||
}
|
||||
|
||||
inst := &syncImpl{
|
||||
instrument: instrument{
|
||||
descriptor: desc,
|
||||
},
|
||||
constructor: constructor,
|
||||
}
|
||||
m.syncInsts = append(m.syncInsts, inst)
|
||||
m.registry[desc.Name()] = inst
|
||||
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
|
||||
|
||||
func (inst *syncImpl) setDelegate(d metric.Meter) {
|
||||
func (inst *syncImpl) setDelegate(d metric.MeterImpl) {
|
||||
implPtr := new(metric.SyncImpl)
|
||||
|
||||
var err error
|
||||
*implPtr, err = inst.constructor(d)
|
||||
*implPtr, err = d.NewSyncInstrument(inst.descriptor)
|
||||
|
||||
if err != nil {
|
||||
// TODO: There is no standard way to deliver this error to the user.
|
||||
@@ -264,29 +243,25 @@ func (bound *syncHandle) Unbind() {
|
||||
|
||||
// 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()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
if meterPtr := (*metric.Meter)(atomic.LoadPointer(&m.delegate)); meterPtr != nil {
|
||||
return constructor(*meterPtr)
|
||||
}
|
||||
|
||||
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
|
||||
if meterPtr := (*metric.MeterImpl)(atomic.LoadPointer(&m.delegate)); meterPtr != nil {
|
||||
return (*meterPtr).NewAsyncInstrument(desc, callback)
|
||||
}
|
||||
|
||||
inst := &asyncImpl{
|
||||
instrument: instrument{
|
||||
descriptor: desc,
|
||||
},
|
||||
constructor: constructor,
|
||||
callback: callback,
|
||||
}
|
||||
m.asyncInsts = append(m.asyncInsts, inst)
|
||||
m.registry[desc.Name()] = inst
|
||||
return inst, nil
|
||||
}
|
||||
|
||||
@@ -297,21 +272,11 @@ func (obs *asyncImpl) Implementation() interface{} {
|
||||
return obs
|
||||
}
|
||||
|
||||
func asyncCheck(has AsyncImpler, err error) (metric.AsyncImpl, error) {
|
||||
if has != nil {
|
||||
return has.AsyncImpl(), err
|
||||
}
|
||||
if err == nil {
|
||||
err = metric.ErrSDKReturnedNilImpl
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (obs *asyncImpl) setDelegate(d metric.Meter) {
|
||||
func (obs *asyncImpl) setDelegate(d metric.MeterImpl) {
|
||||
implPtr := new(metric.AsyncImpl)
|
||||
|
||||
var err error
|
||||
*implPtr, err = obs.constructor(d)
|
||||
*implPtr, err = d.NewAsyncInstrument(obs.descriptor, obs.callback)
|
||||
|
||||
if err != nil {
|
||||
// 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
|
||||
|
||||
func (m *meter) RecordBatch(ctx context.Context, labels []core.KeyValue, measurements ...metric.Measurement) {
|
||||
if delegatePtr := (*metric.Meter)(atomic.LoadPointer(&m.delegate)); delegatePtr != nil {
|
||||
func (m *meterImpl) RecordBatch(ctx context.Context, labels []core.KeyValue, measurements ...metric.Measurement) {
|
||||
if delegatePtr := (*metric.MeterImpl)(atomic.LoadPointer(&m.delegate)); delegatePtr != nil {
|
||||
(*delegatePtr).RecordBatch(ctx, labels, measurements...)
|
||||
}
|
||||
}
|
||||
@@ -363,64 +328,10 @@ func (bound *syncHandle) RecordOne(ctx context.Context, number metric.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 {
|
||||
return map[string]uintptr{
|
||||
"meterProvider.delegate": unsafe.Offsetof(meterProvider{}.delegate),
|
||||
"meter.delegate": unsafe.Offsetof(meter{}.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),
|
||||
|
||||
@@ -280,15 +280,15 @@ type meterProviderWithConstructorError struct {
|
||||
}
|
||||
|
||||
type meterWithConstructorError struct {
|
||||
metric.Meter
|
||||
metric.MeterImpl
|
||||
}
|
||||
|
||||
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) {
|
||||
return metric.Int64Counter{}, errors.New("constructor error")
|
||||
func (m *meterWithConstructorError) NewSyncInstrument(_ metric.Descriptor) (metric.SyncImpl, error) {
|
||||
return metric.NoopSync{}, errors.New("constructor error")
|
||||
}
|
||||
|
||||
func TestErrorInDeferredConstructor(t *testing.T) {
|
||||
|
||||
@@ -135,38 +135,99 @@ func (d Descriptor) LibraryName() string {
|
||||
return d.config.LibraryName
|
||||
}
|
||||
|
||||
// Meter is an interface to the metrics portion of the OpenTelemetry SDK.
|
||||
type Meter interface {
|
||||
// Meter is the OpenTelemetry metric API, based on a `MeterImpl`
|
||||
// implementation and the `Meter` library name.
|
||||
//
|
||||
// An uninitialized Meter is a no-op implementation.
|
||||
type Meter struct {
|
||||
impl MeterImpl
|
||||
libraryName string
|
||||
}
|
||||
|
||||
// RecordBatch atomically records a batch of measurements.
|
||||
RecordBatch(context.Context, []core.KeyValue, ...Measurement)
|
||||
func (m Meter) RecordBatch(ctx context.Context, ls []core.KeyValue, ms ...Measurement) {
|
||||
if m.impl == nil {
|
||||
return
|
||||
}
|
||||
m.impl.RecordBatch(ctx, ls, ms...)
|
||||
}
|
||||
|
||||
// All instrument constructors may return an error for
|
||||
// conditions such as:
|
||||
// `name` is an empty string
|
||||
// `name` was previously registered as a different kind of instrument
|
||||
// for a given named `Meter`.
|
||||
// NewInt64Counter creates a new integer Counter 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) NewInt64Counter(name string, options ...Option) (Int64Counter, error) {
|
||||
return wrapInt64CounterInstrument(
|
||||
m.newSync(name, CounterKind, Int64NumberKind, options))
|
||||
}
|
||||
|
||||
// NewInt64Counter creates a new integral counter with a given
|
||||
// name and customized with passed options.
|
||||
NewInt64Counter(name string, opts ...Option) (Int64Counter, error)
|
||||
// NewFloat64Counter creates a new floating point counter with
|
||||
// a given name and customized with passed options.
|
||||
NewFloat64Counter(name string, opts ...Option) (Float64Counter, error)
|
||||
// NewInt64Measure creates a new integral measure with a given
|
||||
// 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)
|
||||
// NewFloat64Counter creates a new floating point Counter 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) NewFloat64Counter(name string, options ...Option) (Float64Counter, error) {
|
||||
return wrapFloat64CounterInstrument(
|
||||
m.newSync(name, CounterKind, Float64NumberKind, options))
|
||||
}
|
||||
|
||||
// RegisterInt64Observer creates a new integral observer with a
|
||||
// given name, running a given callback, and customized with passed
|
||||
// options. Callback may be nil.
|
||||
RegisterInt64Observer(name string, callback Int64ObserverCallback, opts ...Option) (Int64Observer, error)
|
||||
// RegisterFloat64Observer creates a new floating point observer
|
||||
// with a given name, running a given callback, and customized with
|
||||
// passed options. Callback may be nil.
|
||||
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.
|
||||
|
||||
@@ -21,7 +21,6 @@ import (
|
||||
)
|
||||
|
||||
type NoopProvider struct{}
|
||||
type NoopMeter struct{}
|
||||
|
||||
type noopInstrument struct{}
|
||||
type noopBoundInstrument struct{}
|
||||
@@ -29,13 +28,12 @@ type NoopSync struct{ noopInstrument }
|
||||
type NoopAsync struct{ noopInstrument }
|
||||
|
||||
var _ Provider = NoopProvider{}
|
||||
var _ Meter = NoopMeter{}
|
||||
var _ SyncImpl = NoopSync{}
|
||||
var _ BoundSyncImpl = noopBoundInstrument{}
|
||||
var _ AsyncImpl = NoopAsync{}
|
||||
|
||||
func (NoopProvider) Meter(name string) Meter {
|
||||
return NoopMeter{}
|
||||
return Meter{}
|
||||
}
|
||||
|
||||
func (noopInstrument) Implementation() interface{} {
|
||||
@@ -58,30 +56,3 @@ func (NoopSync) Bind([]core.KeyValue) BoundSyncImpl {
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
// observers run.
|
||||
type Int64ObserverCallback func(result Int64ObserverResult)
|
||||
|
||||
@@ -20,10 +20,8 @@ import (
|
||||
"go.opentelemetry.io/otel/api/core"
|
||||
)
|
||||
|
||||
// MeterImpl is a convenient interface for SDK and test
|
||||
// implementations that would provide a `Meter` but do not wish to
|
||||
// re-implement the API's type-safe interfaces. Helpers provided in
|
||||
// this package will construct a `Meter` given a `MeterImpl`.
|
||||
// MeterImpl is the interface an SDK must implement to supply a Meter
|
||||
// implementation.
|
||||
type MeterImpl interface {
|
||||
// RecordBatch atomically records a batch of measurements.
|
||||
RecordBatch(context.Context, []core.KeyValue, ...Measurement)
|
||||
@@ -83,35 +81,20 @@ type BoundSyncImpl interface {
|
||||
// asynchronous instrument (e.g., Observer instruments).
|
||||
type AsyncImpl interface {
|
||||
InstrumentImpl
|
||||
|
||||
// Note: An `Unregister()` API could be supported here.
|
||||
}
|
||||
|
||||
// wrappedMeterImpl implements the `Meter` interface given a
|
||||
// `MeterImpl` implementation.
|
||||
type wrappedMeterImpl struct {
|
||||
impl MeterImpl
|
||||
libraryName string
|
||||
}
|
||||
|
||||
// int64ObserverResult is an adapter for int64-valued asynchronous
|
||||
// callbacks.
|
||||
type int64ObserverResult struct {
|
||||
// Int64ObserverResult is passed to an observer callback to capture
|
||||
// observations for one asynchronous integer metric instrument.
|
||||
type Int64ObserverResult struct {
|
||||
observe func(Number, []core.KeyValue)
|
||||
}
|
||||
|
||||
// float64ObserverResult is an adapter for float64-valued asynchronous
|
||||
// callbacks.
|
||||
type float64ObserverResult struct {
|
||||
// Float64ObserverResult is passed to an observer callback to capture
|
||||
// observations for one asynchronous floating point metric instrument.
|
||||
type Float64ObserverResult struct {
|
||||
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.
|
||||
func Configure(opts []Option) Config {
|
||||
var config Config
|
||||
@@ -124,131 +107,87 @@ func Configure(opts []Option) Config {
|
||||
// WrapMeterImpl constructs a `Meter` implementation from a
|
||||
// `MeterImpl` implementation.
|
||||
func WrapMeterImpl(impl MeterImpl, libraryName string) Meter {
|
||||
return &wrappedMeterImpl{
|
||||
return Meter{
|
||||
impl: impl,
|
||||
libraryName: libraryName,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *wrappedMeterImpl) RecordBatch(ctx context.Context, ls []core.KeyValue, ms ...Measurement) {
|
||||
m.impl.RecordBatch(ctx, ls, ms...)
|
||||
// MeterImpl returns the underlying MeterImpl of this Meter.
|
||||
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.config.LibraryName = m.libraryName
|
||||
return m.impl.NewSyncInstrument(desc)
|
||||
}
|
||||
|
||||
func (m *wrappedMeterImpl) NewInt64Counter(name string, opts ...Option) (Int64Counter, error) {
|
||||
return WrapInt64CounterInstrument(
|
||||
m.newSync(name, CounterKind, Int64NumberKind, opts))
|
||||
}
|
||||
|
||||
// WrapInt64CounterInstrument returns an `Int64Counter` from a
|
||||
// wrapInt64CounterInstrument returns an `Int64Counter` from a
|
||||
// `SyncImpl`. An error will be generated if the
|
||||
// `SyncImpl` is nil (in which case a No-op is substituted),
|
||||
// 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)
|
||||
return Int64Counter{syncInstrument: common}, err
|
||||
}
|
||||
|
||||
func (m *wrappedMeterImpl) NewFloat64Counter(name string, opts ...Option) (Float64Counter, error) {
|
||||
return WrapFloat64CounterInstrument(
|
||||
m.newSync(name, CounterKind, Float64NumberKind, opts))
|
||||
}
|
||||
|
||||
// WrapFloat64CounterInstrument returns an `Float64Counter` from a
|
||||
// wrapFloat64CounterInstrument returns an `Float64Counter` from a
|
||||
// `SyncImpl`. An error will be generated if the
|
||||
// `SyncImpl` is nil (in which case a No-op is substituted),
|
||||
// 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)
|
||||
return Float64Counter{syncInstrument: common}, err
|
||||
}
|
||||
|
||||
func (m *wrappedMeterImpl) NewInt64Measure(name string, opts ...Option) (Int64Measure, error) {
|
||||
return WrapInt64MeasureInstrument(
|
||||
m.newSync(name, MeasureKind, Int64NumberKind, opts))
|
||||
}
|
||||
|
||||
// WrapInt64MeasureInstrument returns an `Int64Measure` from a
|
||||
// wrapInt64MeasureInstrument returns an `Int64Measure` from a
|
||||
// `SyncImpl`. An error will be generated if the
|
||||
// `SyncImpl` is nil (in which case a No-op is substituted),
|
||||
// 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)
|
||||
return Int64Measure{syncInstrument: common}, err
|
||||
}
|
||||
|
||||
func (m *wrappedMeterImpl) NewFloat64Measure(name string, opts ...Option) (Float64Measure, error) {
|
||||
return WrapFloat64MeasureInstrument(
|
||||
m.newSync(name, MeasureKind, Float64NumberKind, opts))
|
||||
}
|
||||
|
||||
// WrapFloat64MeasureInstrument returns an `Float64Measure` from a
|
||||
// wrapFloat64MeasureInstrument returns an `Float64Measure` from a
|
||||
// `SyncImpl`. An error will be generated if the
|
||||
// `SyncImpl` is nil (in which case a No-op is substituted),
|
||||
// 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)
|
||||
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.config.LibraryName = m.libraryName
|
||||
return m.impl.NewAsyncInstrument(desc, callback)
|
||||
}
|
||||
|
||||
func (m *wrappedMeterImpl) RegisterInt64Observer(name string, callback Int64ObserverCallback, opts ...Option) (Int64Observer, error) {
|
||||
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
|
||||
// wrapInt64ObserverInstrument returns an `Int64Observer` from a
|
||||
// `AsyncImpl`. An error will be generated if the
|
||||
// `AsyncImpl` is nil (in which case a No-op is substituted),
|
||||
// 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)
|
||||
return Int64Observer{asyncInstrument: common}, err
|
||||
}
|
||||
|
||||
func (m *wrappedMeterImpl) RegisterFloat64Observer(name string, callback Float64ObserverCallback, opts ...Option) (Float64Observer, error) {
|
||||
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
|
||||
// wrapFloat64ObserverInstrument returns an `Float64Observer` from a
|
||||
// `AsyncImpl`. An error will be generated if the
|
||||
// `AsyncImpl` is nil (in which case a No-op is substituted),
|
||||
// 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)
|
||||
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