package global
import (
"container/list"
"context"
"reflect"
"sync"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/metric/embedded"
)
type meterProvider struct {
embedded .MeterProvider
mtx sync .Mutex
meters map [il ]*meter
delegate metric .MeterProvider
}
func (p *meterProvider ) setDelegate (provider metric .MeterProvider ) {
p .mtx .Lock ()
defer p .mtx .Unlock ()
p .delegate = provider
if len (p .meters ) == 0 {
return
}
for _ , meter := range p .meters {
meter .setDelegate (provider )
}
p .meters = nil
}
func (p *meterProvider ) Meter (name string , opts ...metric .MeterOption ) metric .Meter {
p .mtx .Lock ()
defer p .mtx .Unlock ()
if p .delegate != nil {
return p .delegate .Meter (name , opts ...)
}
c := metric .NewMeterConfig (opts ...)
key := il {
name : name ,
version : c .InstrumentationVersion (),
schema : c .SchemaURL (),
attrs : c .InstrumentationAttributes (),
}
if p .meters == nil {
p .meters = make (map [il ]*meter )
}
if val , ok := p .meters [key ]; ok {
return val
}
t := &meter {name : name , opts : opts , instruments : make (map [instID ]delegatedInstrument )}
p .meters [key ] = t
return t
}
type meter struct {
embedded .Meter
name string
opts []metric .MeterOption
mtx sync .Mutex
instruments map [instID ]delegatedInstrument
registry list .List
delegate metric .Meter
}
type delegatedInstrument interface {
setDelegate(metric .Meter )
}
type instID struct {
name string
description string
kind reflect .Type
unit string
}
func (m *meter ) setDelegate (provider metric .MeterProvider ) {
m .mtx .Lock ()
defer m .mtx .Unlock ()
meter := provider .Meter (m .name , m .opts ...)
m .delegate = meter
for _ , inst := range m .instruments {
inst .setDelegate (meter )
}
var n *list .Element
for e := m .registry .Front (); e != nil ; e = n {
r := e .Value .(*registration )
r .setDelegate (meter )
n = e .Next ()
m .registry .Remove (e )
}
m .instruments = nil
m .registry .Init ()
}
func (m *meter ) Int64Counter (name string , options ...metric .Int64CounterOption ) (metric .Int64Counter , error ) {
m .mtx .Lock ()
defer m .mtx .Unlock ()
if m .delegate != nil {
return m .delegate .Int64Counter (name , options ...)
}
cfg := metric .NewInt64CounterConfig (options ...)
id := instID {
name : name ,
kind : reflect .TypeOf ((*siCounter )(nil )),
description : cfg .Description (),
unit : cfg .Unit (),
}
if f , ok := m .instruments [id ]; ok {
return f .(metric .Int64Counter ), nil
}
i := &siCounter {name : name , opts : options }
m .instruments [id ] = i
return i , nil
}
func (m *meter ) Int64UpDownCounter (
name string ,
options ...metric .Int64UpDownCounterOption ,
) (metric .Int64UpDownCounter , error ) {
m .mtx .Lock ()
defer m .mtx .Unlock ()
if m .delegate != nil {
return m .delegate .Int64UpDownCounter (name , options ...)
}
cfg := metric .NewInt64UpDownCounterConfig (options ...)
id := instID {
name : name ,
kind : reflect .TypeOf ((*siUpDownCounter )(nil )),
description : cfg .Description (),
unit : cfg .Unit (),
}
if f , ok := m .instruments [id ]; ok {
return f .(metric .Int64UpDownCounter ), nil
}
i := &siUpDownCounter {name : name , opts : options }
m .instruments [id ] = i
return i , nil
}
func (m *meter ) Int64Histogram (name string , options ...metric .Int64HistogramOption ) (metric .Int64Histogram , error ) {
m .mtx .Lock ()
defer m .mtx .Unlock ()
if m .delegate != nil {
return m .delegate .Int64Histogram (name , options ...)
}
cfg := metric .NewInt64HistogramConfig (options ...)
id := instID {
name : name ,
kind : reflect .TypeOf ((*siHistogram )(nil )),
description : cfg .Description (),
unit : cfg .Unit (),
}
if f , ok := m .instruments [id ]; ok {
return f .(metric .Int64Histogram ), nil
}
i := &siHistogram {name : name , opts : options }
m .instruments [id ] = i
return i , nil
}
func (m *meter ) Int64Gauge (name string , options ...metric .Int64GaugeOption ) (metric .Int64Gauge , error ) {
m .mtx .Lock ()
defer m .mtx .Unlock ()
if m .delegate != nil {
return m .delegate .Int64Gauge (name , options ...)
}
cfg := metric .NewInt64GaugeConfig (options ...)
id := instID {
name : name ,
kind : reflect .TypeOf ((*siGauge )(nil )),
description : cfg .Description (),
unit : cfg .Unit (),
}
if f , ok := m .instruments [id ]; ok {
return f .(metric .Int64Gauge ), nil
}
i := &siGauge {name : name , opts : options }
m .instruments [id ] = i
return i , nil
}
func (m *meter ) Int64ObservableCounter (
name string ,
options ...metric .Int64ObservableCounterOption ,
) (metric .Int64ObservableCounter , error ) {
m .mtx .Lock ()
defer m .mtx .Unlock ()
if m .delegate != nil {
return m .delegate .Int64ObservableCounter (name , options ...)
}
cfg := metric .NewInt64ObservableCounterConfig (options ...)
id := instID {
name : name ,
kind : reflect .TypeOf ((*aiCounter )(nil )),
description : cfg .Description (),
unit : cfg .Unit (),
}
if f , ok := m .instruments [id ]; ok {
return f .(metric .Int64ObservableCounter ), nil
}
i := &aiCounter {name : name , opts : options }
m .instruments [id ] = i
return i , nil
}
func (m *meter ) Int64ObservableUpDownCounter (
name string ,
options ...metric .Int64ObservableUpDownCounterOption ,
) (metric .Int64ObservableUpDownCounter , error ) {
m .mtx .Lock ()
defer m .mtx .Unlock ()
if m .delegate != nil {
return m .delegate .Int64ObservableUpDownCounter (name , options ...)
}
cfg := metric .NewInt64ObservableUpDownCounterConfig (options ...)
id := instID {
name : name ,
kind : reflect .TypeOf ((*aiUpDownCounter )(nil )),
description : cfg .Description (),
unit : cfg .Unit (),
}
if f , ok := m .instruments [id ]; ok {
return f .(metric .Int64ObservableUpDownCounter ), nil
}
i := &aiUpDownCounter {name : name , opts : options }
m .instruments [id ] = i
return i , nil
}
func (m *meter ) Int64ObservableGauge (
name string ,
options ...metric .Int64ObservableGaugeOption ,
) (metric .Int64ObservableGauge , error ) {
m .mtx .Lock ()
defer m .mtx .Unlock ()
if m .delegate != nil {
return m .delegate .Int64ObservableGauge (name , options ...)
}
cfg := metric .NewInt64ObservableGaugeConfig (options ...)
id := instID {
name : name ,
kind : reflect .TypeOf ((*aiGauge )(nil )),
description : cfg .Description (),
unit : cfg .Unit (),
}
if f , ok := m .instruments [id ]; ok {
return f .(metric .Int64ObservableGauge ), nil
}
i := &aiGauge {name : name , opts : options }
m .instruments [id ] = i
return i , nil
}
func (m *meter ) Float64Counter (name string , options ...metric .Float64CounterOption ) (metric .Float64Counter , error ) {
m .mtx .Lock ()
defer m .mtx .Unlock ()
if m .delegate != nil {
return m .delegate .Float64Counter (name , options ...)
}
cfg := metric .NewFloat64CounterConfig (options ...)
id := instID {
name : name ,
kind : reflect .TypeOf ((*sfCounter )(nil )),
description : cfg .Description (),
unit : cfg .Unit (),
}
if f , ok := m .instruments [id ]; ok {
return f .(metric .Float64Counter ), nil
}
i := &sfCounter {name : name , opts : options }
m .instruments [id ] = i
return i , nil
}
func (m *meter ) Float64UpDownCounter (
name string ,
options ...metric .Float64UpDownCounterOption ,
) (metric .Float64UpDownCounter , error ) {
m .mtx .Lock ()
defer m .mtx .Unlock ()
if m .delegate != nil {
return m .delegate .Float64UpDownCounter (name , options ...)
}
cfg := metric .NewFloat64UpDownCounterConfig (options ...)
id := instID {
name : name ,
kind : reflect .TypeOf ((*sfUpDownCounter )(nil )),
description : cfg .Description (),
unit : cfg .Unit (),
}
if f , ok := m .instruments [id ]; ok {
return f .(metric .Float64UpDownCounter ), nil
}
i := &sfUpDownCounter {name : name , opts : options }
m .instruments [id ] = i
return i , nil
}
func (m *meter ) Float64Histogram (
name string ,
options ...metric .Float64HistogramOption ,
) (metric .Float64Histogram , error ) {
m .mtx .Lock ()
defer m .mtx .Unlock ()
if m .delegate != nil {
return m .delegate .Float64Histogram (name , options ...)
}
cfg := metric .NewFloat64HistogramConfig (options ...)
id := instID {
name : name ,
kind : reflect .TypeOf ((*sfHistogram )(nil )),
description : cfg .Description (),
unit : cfg .Unit (),
}
if f , ok := m .instruments [id ]; ok {
return f .(metric .Float64Histogram ), nil
}
i := &sfHistogram {name : name , opts : options }
m .instruments [id ] = i
return i , nil
}
func (m *meter ) Float64Gauge (name string , options ...metric .Float64GaugeOption ) (metric .Float64Gauge , error ) {
m .mtx .Lock ()
defer m .mtx .Unlock ()
if m .delegate != nil {
return m .delegate .Float64Gauge (name , options ...)
}
cfg := metric .NewFloat64GaugeConfig (options ...)
id := instID {
name : name ,
kind : reflect .TypeOf ((*sfGauge )(nil )),
description : cfg .Description (),
unit : cfg .Unit (),
}
if f , ok := m .instruments [id ]; ok {
return f .(metric .Float64Gauge ), nil
}
i := &sfGauge {name : name , opts : options }
m .instruments [id ] = i
return i , nil
}
func (m *meter ) Float64ObservableCounter (
name string ,
options ...metric .Float64ObservableCounterOption ,
) (metric .Float64ObservableCounter , error ) {
m .mtx .Lock ()
defer m .mtx .Unlock ()
if m .delegate != nil {
return m .delegate .Float64ObservableCounter (name , options ...)
}
cfg := metric .NewFloat64ObservableCounterConfig (options ...)
id := instID {
name : name ,
kind : reflect .TypeOf ((*afCounter )(nil )),
description : cfg .Description (),
unit : cfg .Unit (),
}
if f , ok := m .instruments [id ]; ok {
return f .(metric .Float64ObservableCounter ), nil
}
i := &afCounter {name : name , opts : options }
m .instruments [id ] = i
return i , nil
}
func (m *meter ) Float64ObservableUpDownCounter (
name string ,
options ...metric .Float64ObservableUpDownCounterOption ,
) (metric .Float64ObservableUpDownCounter , error ) {
m .mtx .Lock ()
defer m .mtx .Unlock ()
if m .delegate != nil {
return m .delegate .Float64ObservableUpDownCounter (name , options ...)
}
cfg := metric .NewFloat64ObservableUpDownCounterConfig (options ...)
id := instID {
name : name ,
kind : reflect .TypeOf ((*afUpDownCounter )(nil )),
description : cfg .Description (),
unit : cfg .Unit (),
}
if f , ok := m .instruments [id ]; ok {
return f .(metric .Float64ObservableUpDownCounter ), nil
}
i := &afUpDownCounter {name : name , opts : options }
m .instruments [id ] = i
return i , nil
}
func (m *meter ) Float64ObservableGauge (
name string ,
options ...metric .Float64ObservableGaugeOption ,
) (metric .Float64ObservableGauge , error ) {
m .mtx .Lock ()
defer m .mtx .Unlock ()
if m .delegate != nil {
return m .delegate .Float64ObservableGauge (name , options ...)
}
cfg := metric .NewFloat64ObservableGaugeConfig (options ...)
id := instID {
name : name ,
kind : reflect .TypeOf ((*afGauge )(nil )),
description : cfg .Description (),
unit : cfg .Unit (),
}
if f , ok := m .instruments [id ]; ok {
return f .(metric .Float64ObservableGauge ), nil
}
i := &afGauge {name : name , opts : options }
m .instruments [id ] = i
return i , nil
}
func (m *meter ) RegisterCallback (f metric .Callback , insts ...metric .Observable ) (metric .Registration , error ) {
m .mtx .Lock ()
defer m .mtx .Unlock ()
if m .delegate != nil {
return m .delegate .RegisterCallback (unwrapCallback (f ), unwrapInstruments (insts )...)
}
reg := ®istration {instruments : insts , function : f }
e := m .registry .PushBack (reg )
reg .unreg = func () error {
m .mtx .Lock ()
_ = m .registry .Remove (e )
m .mtx .Unlock ()
return nil
}
return reg , nil
}
func unwrapInstruments(instruments []metric .Observable ) []metric .Observable {
out := make ([]metric .Observable , 0 , len (instruments ))
for _ , inst := range instruments {
if in , ok := inst .(unwrapper ); ok {
out = append (out , in .unwrap ())
} else {
out = append (out , inst )
}
}
return out
}
type registration struct {
embedded .Registration
instruments []metric .Observable
function metric .Callback
unreg func () error
unregMu sync .Mutex
}
type unwrapObs struct {
embedded .Observer
obs metric .Observer
}
func unwrapFloat64Observable(inst metric .Float64Observable ) metric .Float64Observable {
if unwrapped , ok := inst .(unwrapper ); ok {
if floatObs , ok := unwrapped .unwrap ().(metric .Float64Observable ); ok {
inst = floatObs
}
}
return inst
}
func unwrapInt64Observable(inst metric .Int64Observable ) metric .Int64Observable {
if unwrapped , ok := inst .(unwrapper ); ok {
if unint , ok := unwrapped .unwrap ().(metric .Int64Observable ); ok {
inst = unint
}
}
return inst
}
func (uo *unwrapObs ) ObserveFloat64 (inst metric .Float64Observable , value float64 , opts ...metric .ObserveOption ) {
uo .obs .ObserveFloat64 (unwrapFloat64Observable (inst ), value , opts ...)
}
func (uo *unwrapObs ) ObserveInt64 (inst metric .Int64Observable , value int64 , opts ...metric .ObserveOption ) {
uo .obs .ObserveInt64 (unwrapInt64Observable (inst ), value , opts ...)
}
func unwrapCallback(f metric .Callback ) metric .Callback {
return func (ctx context .Context , obs metric .Observer ) error {
return f (ctx , &unwrapObs {obs : obs })
}
}
func (c *registration ) setDelegate (m metric .Meter ) {
c .unregMu .Lock ()
defer c .unregMu .Unlock ()
if c .unreg == nil {
return
}
reg , err := m .RegisterCallback (unwrapCallback (c .function ), unwrapInstruments (c .instruments )...)
if err != nil {
GetErrorHandler ().Handle (err )
return
}
c .unreg = reg .Unregister
}
func (c *registration ) Unregister () error {
c .unregMu .Lock ()
defer c .unregMu .Unlock ()
if c .unreg == nil {
return nil
}
var err error
err , c .unreg = c .unreg (), nil
return err
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .