otlp创建trace和meter时单例实现查看
注意到otlp-gin的中间件库,每次请求都会用provider获取meter对象,因此担心性能问题遂看代码...文档真的看不懂,好多包只能去go.dev查api
Meter
每次请求都会使用otel.Meter(name)获取meter进行操作.
来到文件D:\Develop\golang\pkg\mod\go.opentelemetry.io\otel\sdk\metric@v1.37.0\provider.go
第92行看关键代码
return mp.meters.Lookup(s, func() *meter {
return newMeter(s, mp.pipes)
})
代码调用了lookup跳转进去.这是一个实现了私有kv,解决了并发的缓存文件.
函数具体实现如下
func (c *cache[K, V]) Lookup(key K, f func() V) V {
c.Lock()
defer c.Unlock()
if c.data == nil {
val := f()
c.data = map[K]V{key: val}
return val
}
if v, ok := c.data[key]; ok {
return v
}
val := f()
c.data[key] = val
return val
}
当首次创建时,缓存中没有查找到key,会调用之前Lookup中传递的匿名函数创建.如果缓存中查找到key会直接返回存储的value.即meter也实现了单例.同时你设置的计数器等也会存在这个单例中
计数器
随便来查看一个计数器,可以看到也使用了lookup,因此计数器等也会被缓存,旧的计数器不会被覆盖
func (m *meter) Int64Counter(name string, options ...metric.Int64CounterOption) (metric.Int64Counter, error) {
cfg := metric.NewInt64CounterConfig(options...)
const kind = InstrumentKindCounter
p := int64InstProvider{m}
i, err := p.lookup(kind, name, cfg.Description(), cfg.Unit())
if err != nil {
return i, err
}
return i, validateInstrumentName(name)
}
Trace
在你创建完provider设置到otel后
otel.Tracer(name)的注释更加清楚明了
If the same name and options are passed multiple times, the same Tracer will be returned
如果传入相同的 name 和 options,会返回相同的 Tracer
至此Meter和Trace如果opt和name全相同,则会返回相同对象,否则会创建新对象.
因而不必过于担心性能问题
Otlp col
otlp col可以理解成一个转发程序,部署在节点上接收节点上程序发送的数据,然后转发给jaeger,prometheus(或者暴露/metrics端口给prometheus采集).
因此metrics中的数据完全依赖程序传递的数据,比如计数器,之前为50,重启程序后变为了0,otlp col也会更新成0,即使是只增计数器.
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。