1
0
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:
Joshua MacDonald
2020-05-11 20:29:06 -07:00
committed by GitHub
parent 64afb05e53
commit 32ddc16e1b
7 changed files with 175 additions and 307 deletions

View File

@@ -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) {

View File

@@ -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),

View File

@@ -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) {

View File

@@ -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.

View File

@@ -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
}

View File

@@ -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)

View File

@@ -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)
}