mirror of
https://github.com/go-gitea/gitea
synced 2025-07-25 11:48:37 +00:00
[Vendor] Update go-redis to v8.5.0 (#13749)
* Update go-redis to v8.4.0 * github.com/go-redis/redis/v8 v8.4.0 -> v8.5.0 * Apply suggestions from code review Co-authored-by: zeripath <art27@cantab.net> * TODO * Use the Queue termination channel as the default context for pushes Signed-off-by: Andrew Thornton <art27@cantab.net> * missed one Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: zeripath <art27@cantab.net>
This commit is contained in:
338
vendor/go.opentelemetry.io/otel/internal/baggage/baggage.go
generated
vendored
Normal file
338
vendor/go.opentelemetry.io/otel/internal/baggage/baggage.go
generated
vendored
Normal file
@@ -0,0 +1,338 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package baggage provides types and functions to manage W3C Baggage.
|
||||
package baggage
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.opentelemetry.io/otel/label"
|
||||
)
|
||||
|
||||
type rawMap map[label.Key]label.Value
|
||||
type keySet map[label.Key]struct{}
|
||||
|
||||
// Map is an immutable storage for correlations.
|
||||
type Map struct {
|
||||
m rawMap
|
||||
}
|
||||
|
||||
// MapUpdate contains information about correlation changes to be
|
||||
// made.
|
||||
type MapUpdate struct {
|
||||
// DropSingleK contains a single key to be dropped from
|
||||
// correlations. Use this to avoid an overhead of a slice
|
||||
// allocation if there is only one key to drop.
|
||||
DropSingleK label.Key
|
||||
// DropMultiK contains all the keys to be dropped from
|
||||
// correlations.
|
||||
DropMultiK []label.Key
|
||||
|
||||
// SingleKV contains a single key-value pair to be added to
|
||||
// correlations. Use this to avoid an overhead of a slice
|
||||
// allocation if there is only one key-value pair to add.
|
||||
SingleKV label.KeyValue
|
||||
// MultiKV contains all the key-value pairs to be added to
|
||||
// correlations.
|
||||
MultiKV []label.KeyValue
|
||||
}
|
||||
|
||||
func newMap(raw rawMap) Map {
|
||||
return Map{
|
||||
m: raw,
|
||||
}
|
||||
}
|
||||
|
||||
// NewEmptyMap creates an empty correlations map.
|
||||
func NewEmptyMap() Map {
|
||||
return newMap(nil)
|
||||
}
|
||||
|
||||
// NewMap creates a map with the contents of the update applied. In
|
||||
// this function, having an update with DropSingleK or DropMultiK
|
||||
// makes no sense - those fields are effectively ignored.
|
||||
func NewMap(update MapUpdate) Map {
|
||||
return NewEmptyMap().Apply(update)
|
||||
}
|
||||
|
||||
// Apply creates a copy of the map with the contents of the update
|
||||
// applied. Apply will first drop the keys from DropSingleK and
|
||||
// DropMultiK, then add key-value pairs from SingleKV and MultiKV.
|
||||
func (m Map) Apply(update MapUpdate) Map {
|
||||
delSet, addSet := getModificationSets(update)
|
||||
mapSize := getNewMapSize(m.m, delSet, addSet)
|
||||
|
||||
r := make(rawMap, mapSize)
|
||||
for k, v := range m.m {
|
||||
// do not copy items we want to drop
|
||||
if _, ok := delSet[k]; ok {
|
||||
continue
|
||||
}
|
||||
// do not copy items we would overwrite
|
||||
if _, ok := addSet[k]; ok {
|
||||
continue
|
||||
}
|
||||
r[k] = v
|
||||
}
|
||||
if update.SingleKV.Key.Defined() {
|
||||
r[update.SingleKV.Key] = update.SingleKV.Value
|
||||
}
|
||||
for _, kv := range update.MultiKV {
|
||||
r[kv.Key] = kv.Value
|
||||
}
|
||||
if len(r) == 0 {
|
||||
r = nil
|
||||
}
|
||||
return newMap(r)
|
||||
}
|
||||
|
||||
func getModificationSets(update MapUpdate) (delSet, addSet keySet) {
|
||||
deletionsCount := len(update.DropMultiK)
|
||||
if update.DropSingleK.Defined() {
|
||||
deletionsCount++
|
||||
}
|
||||
if deletionsCount > 0 {
|
||||
delSet = make(map[label.Key]struct{}, deletionsCount)
|
||||
for _, k := range update.DropMultiK {
|
||||
delSet[k] = struct{}{}
|
||||
}
|
||||
if update.DropSingleK.Defined() {
|
||||
delSet[update.DropSingleK] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
additionsCount := len(update.MultiKV)
|
||||
if update.SingleKV.Key.Defined() {
|
||||
additionsCount++
|
||||
}
|
||||
if additionsCount > 0 {
|
||||
addSet = make(map[label.Key]struct{}, additionsCount)
|
||||
for _, k := range update.MultiKV {
|
||||
addSet[k.Key] = struct{}{}
|
||||
}
|
||||
if update.SingleKV.Key.Defined() {
|
||||
addSet[update.SingleKV.Key] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func getNewMapSize(m rawMap, delSet, addSet keySet) int {
|
||||
mapSizeDiff := 0
|
||||
for k := range addSet {
|
||||
if _, ok := m[k]; !ok {
|
||||
mapSizeDiff++
|
||||
}
|
||||
}
|
||||
for k := range delSet {
|
||||
if _, ok := m[k]; ok {
|
||||
if _, inAddSet := addSet[k]; !inAddSet {
|
||||
mapSizeDiff--
|
||||
}
|
||||
}
|
||||
}
|
||||
return len(m) + mapSizeDiff
|
||||
}
|
||||
|
||||
// Value gets a value from correlations map and returns a boolean
|
||||
// value indicating whether the key exist in the map.
|
||||
func (m Map) Value(k label.Key) (label.Value, bool) {
|
||||
value, ok := m.m[k]
|
||||
return value, ok
|
||||
}
|
||||
|
||||
// HasValue returns a boolean value indicating whether the key exist
|
||||
// in the map.
|
||||
func (m Map) HasValue(k label.Key) bool {
|
||||
_, has := m.Value(k)
|
||||
return has
|
||||
}
|
||||
|
||||
// Len returns a length of the map.
|
||||
func (m Map) Len() int {
|
||||
return len(m.m)
|
||||
}
|
||||
|
||||
// Foreach calls a passed callback once on each key-value pair until
|
||||
// all the key-value pairs of the map were iterated or the callback
|
||||
// returns false, whichever happens first.
|
||||
func (m Map) Foreach(f func(label.KeyValue) bool) {
|
||||
for k, v := range m.m {
|
||||
if !f(label.KeyValue{
|
||||
Key: k,
|
||||
Value: v,
|
||||
}) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type correlationsType struct{}
|
||||
|
||||
// SetHookFunc describes a type of a callback that is called when
|
||||
// storing baggage in the context.
|
||||
type SetHookFunc func(context.Context) context.Context
|
||||
|
||||
// GetHookFunc describes a type of a callback that is called when
|
||||
// getting baggage from the context.
|
||||
type GetHookFunc func(context.Context, Map) Map
|
||||
|
||||
// value under this key is either of type Map or correlationsData
|
||||
var correlationsKey = &correlationsType{}
|
||||
|
||||
type correlationsData struct {
|
||||
m Map
|
||||
setHook SetHookFunc
|
||||
getHook GetHookFunc
|
||||
}
|
||||
|
||||
func (d correlationsData) isHookless() bool {
|
||||
return d.setHook == nil && d.getHook == nil
|
||||
}
|
||||
|
||||
type hookKind int
|
||||
|
||||
const (
|
||||
hookKindSet hookKind = iota
|
||||
hookKindGet
|
||||
)
|
||||
|
||||
func (d *correlationsData) overrideHook(kind hookKind, setHook SetHookFunc, getHook GetHookFunc) {
|
||||
switch kind {
|
||||
case hookKindSet:
|
||||
d.setHook = setHook
|
||||
case hookKindGet:
|
||||
d.getHook = getHook
|
||||
}
|
||||
}
|
||||
|
||||
// ContextWithSetHook installs a hook function that will be invoked
|
||||
// every time ContextWithMap is called. To avoid unnecessary callback
|
||||
// invocations (recursive or not), the callback can temporarily clear
|
||||
// the hooks from the context with the ContextWithNoHooks function.
|
||||
//
|
||||
// Note that NewContext also calls ContextWithMap, so the hook will be
|
||||
// invoked.
|
||||
//
|
||||
// Passing nil SetHookFunc creates a context with no set hook to call.
|
||||
//
|
||||
// This function should not be used by applications or libraries. It
|
||||
// is mostly for interoperation with other observability APIs.
|
||||
func ContextWithSetHook(ctx context.Context, hook SetHookFunc) context.Context {
|
||||
return contextWithHook(ctx, hookKindSet, hook, nil)
|
||||
}
|
||||
|
||||
// ContextWithGetHook installs a hook function that will be invoked
|
||||
// every time MapFromContext is called. To avoid unnecessary callback
|
||||
// invocations (recursive or not), the callback can temporarily clear
|
||||
// the hooks from the context with the ContextWithNoHooks function.
|
||||
//
|
||||
// Note that NewContext also calls MapFromContext, so the hook will be
|
||||
// invoked.
|
||||
//
|
||||
// Passing nil GetHookFunc creates a context with no get hook to call.
|
||||
//
|
||||
// This function should not be used by applications or libraries. It
|
||||
// is mostly for interoperation with other observability APIs.
|
||||
func ContextWithGetHook(ctx context.Context, hook GetHookFunc) context.Context {
|
||||
return contextWithHook(ctx, hookKindGet, nil, hook)
|
||||
}
|
||||
|
||||
func contextWithHook(ctx context.Context, kind hookKind, setHook SetHookFunc, getHook GetHookFunc) context.Context {
|
||||
switch v := ctx.Value(correlationsKey).(type) {
|
||||
case correlationsData:
|
||||
v.overrideHook(kind, setHook, getHook)
|
||||
if v.isHookless() {
|
||||
return context.WithValue(ctx, correlationsKey, v.m)
|
||||
}
|
||||
return context.WithValue(ctx, correlationsKey, v)
|
||||
case Map:
|
||||
return contextWithOneHookAndMap(ctx, kind, setHook, getHook, v)
|
||||
default:
|
||||
m := NewEmptyMap()
|
||||
return contextWithOneHookAndMap(ctx, kind, setHook, getHook, m)
|
||||
}
|
||||
}
|
||||
|
||||
func contextWithOneHookAndMap(ctx context.Context, kind hookKind, setHook SetHookFunc, getHook GetHookFunc, m Map) context.Context {
|
||||
d := correlationsData{m: m}
|
||||
d.overrideHook(kind, setHook, getHook)
|
||||
if d.isHookless() {
|
||||
return ctx
|
||||
}
|
||||
return context.WithValue(ctx, correlationsKey, d)
|
||||
}
|
||||
|
||||
// ContextWithNoHooks creates a context with all the hooks
|
||||
// disabled. Also returns old set and get hooks. This function can be
|
||||
// used to temporarily clear the context from hooks and then reinstate
|
||||
// them by calling ContextWithSetHook and ContextWithGetHook functions
|
||||
// passing the hooks returned by this function.
|
||||
//
|
||||
// This function should not be used by applications or libraries. It
|
||||
// is mostly for interoperation with other observability APIs.
|
||||
func ContextWithNoHooks(ctx context.Context) (context.Context, SetHookFunc, GetHookFunc) {
|
||||
switch v := ctx.Value(correlationsKey).(type) {
|
||||
case correlationsData:
|
||||
return context.WithValue(ctx, correlationsKey, v.m), v.setHook, v.getHook
|
||||
default:
|
||||
return ctx, nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
// ContextWithMap returns a context with the Map entered into it.
|
||||
func ContextWithMap(ctx context.Context, m Map) context.Context {
|
||||
switch v := ctx.Value(correlationsKey).(type) {
|
||||
case correlationsData:
|
||||
v.m = m
|
||||
ctx = context.WithValue(ctx, correlationsKey, v)
|
||||
if v.setHook != nil {
|
||||
ctx = v.setHook(ctx)
|
||||
}
|
||||
return ctx
|
||||
default:
|
||||
return context.WithValue(ctx, correlationsKey, m)
|
||||
}
|
||||
}
|
||||
|
||||
// ContextWithNoCorrelationData returns a context stripped of correlation
|
||||
// data.
|
||||
func ContextWithNoCorrelationData(ctx context.Context) context.Context {
|
||||
return context.WithValue(ctx, correlationsKey, nil)
|
||||
}
|
||||
|
||||
// NewContext returns a context with the map from passed context
|
||||
// updated with the passed key-value pairs.
|
||||
func NewContext(ctx context.Context, keyvalues ...label.KeyValue) context.Context {
|
||||
return ContextWithMap(ctx, MapFromContext(ctx).Apply(MapUpdate{
|
||||
MultiKV: keyvalues,
|
||||
}))
|
||||
}
|
||||
|
||||
// MapFromContext gets the current Map from a Context.
|
||||
func MapFromContext(ctx context.Context) Map {
|
||||
switch v := ctx.Value(correlationsKey).(type) {
|
||||
case correlationsData:
|
||||
if v.getHook != nil {
|
||||
return v.getHook(ctx, v.m)
|
||||
}
|
||||
return v.m
|
||||
case Map:
|
||||
return v
|
||||
default:
|
||||
return NewEmptyMap()
|
||||
}
|
||||
}
|
348
vendor/go.opentelemetry.io/otel/internal/global/meter.go
generated
vendored
Normal file
348
vendor/go.opentelemetry.io/otel/internal/global/meter.go
generated
vendored
Normal file
@@ -0,0 +1,348 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package global
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
|
||||
"go.opentelemetry.io/otel/label"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
"go.opentelemetry.io/otel/metric/number"
|
||||
"go.opentelemetry.io/otel/metric/registry"
|
||||
)
|
||||
|
||||
// This file contains the forwarding implementation of MeterProvider used as
|
||||
// the default global instance. Metric events using instruments provided by
|
||||
// this implementation are no-ops until the first Meter implementation is set
|
||||
// as the global provider.
|
||||
//
|
||||
// The implementation here uses Mutexes to maintain a list of active Meters in
|
||||
// the MeterProvider and Instruments in each Meter, under the assumption that
|
||||
// these interfaces are not performance-critical.
|
||||
//
|
||||
// We have the invariant that setDelegate() will be called before a new
|
||||
// MeterProvider implementation is registered as the global provider. Mutexes
|
||||
// in the MeterProvider and Meters ensure that each instrument has a delegate
|
||||
// before the global provider is set.
|
||||
//
|
||||
// Bound instrument operations are implemented by delegating to the
|
||||
// instrument after it is registered, with a sync.Once initializer to
|
||||
// protect against races with Release().
|
||||
//
|
||||
// Metric uniqueness checking is implemented by calling the exported
|
||||
// methods of the api/metric/registry package.
|
||||
|
||||
type meterKey struct {
|
||||
Name, Version string
|
||||
}
|
||||
|
||||
type meterProvider struct {
|
||||
delegate metric.MeterProvider
|
||||
|
||||
// lock protects `delegate` and `meters`.
|
||||
lock sync.Mutex
|
||||
|
||||
// meters maintains a unique entry for every named Meter
|
||||
// that has been registered through the global instance.
|
||||
meters map[meterKey]*meterEntry
|
||||
}
|
||||
|
||||
type meterImpl struct {
|
||||
delegate unsafe.Pointer // (*metric.MeterImpl)
|
||||
|
||||
lock sync.Mutex
|
||||
syncInsts []*syncImpl
|
||||
asyncInsts []*asyncImpl
|
||||
}
|
||||
|
||||
type meterEntry struct {
|
||||
unique metric.MeterImpl
|
||||
impl meterImpl
|
||||
}
|
||||
|
||||
type instrument struct {
|
||||
descriptor metric.Descriptor
|
||||
}
|
||||
|
||||
type syncImpl struct {
|
||||
delegate unsafe.Pointer // (*metric.SyncImpl)
|
||||
|
||||
instrument
|
||||
}
|
||||
|
||||
type asyncImpl struct {
|
||||
delegate unsafe.Pointer // (*metric.AsyncImpl)
|
||||
|
||||
instrument
|
||||
|
||||
runner metric.AsyncRunner
|
||||
}
|
||||
|
||||
// SyncImpler is implemented by all of the sync metric
|
||||
// instruments.
|
||||
type SyncImpler interface {
|
||||
SyncImpl() metric.SyncImpl
|
||||
}
|
||||
|
||||
// AsyncImpler is implemented by all of the async
|
||||
// metric instruments.
|
||||
type AsyncImpler interface {
|
||||
AsyncImpl() metric.AsyncImpl
|
||||
}
|
||||
|
||||
type syncHandle struct {
|
||||
delegate unsafe.Pointer // (*metric.BoundInstrumentImpl)
|
||||
|
||||
inst *syncImpl
|
||||
labels []label.KeyValue
|
||||
|
||||
initialize sync.Once
|
||||
}
|
||||
|
||||
var _ metric.MeterProvider = &meterProvider{}
|
||||
var _ metric.MeterImpl = &meterImpl{}
|
||||
var _ metric.InstrumentImpl = &syncImpl{}
|
||||
var _ metric.BoundSyncImpl = &syncHandle{}
|
||||
var _ metric.AsyncImpl = &asyncImpl{}
|
||||
|
||||
func (inst *instrument) Descriptor() metric.Descriptor {
|
||||
return inst.descriptor
|
||||
}
|
||||
|
||||
// MeterProvider interface and delegation
|
||||
|
||||
func newMeterProvider() *meterProvider {
|
||||
return &meterProvider{
|
||||
meters: map[meterKey]*meterEntry{},
|
||||
}
|
||||
}
|
||||
|
||||
func (p *meterProvider) setDelegate(provider metric.MeterProvider) {
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
|
||||
p.delegate = provider
|
||||
for key, entry := range p.meters {
|
||||
entry.impl.setDelegate(key.Name, key.Version, provider)
|
||||
}
|
||||
p.meters = nil
|
||||
}
|
||||
|
||||
func (p *meterProvider) Meter(instrumentationName string, opts ...metric.MeterOption) metric.Meter {
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
|
||||
if p.delegate != nil {
|
||||
return p.delegate.Meter(instrumentationName, opts...)
|
||||
}
|
||||
|
||||
key := meterKey{
|
||||
Name: instrumentationName,
|
||||
Version: metric.NewMeterConfig(opts...).InstrumentationVersion,
|
||||
}
|
||||
entry, ok := p.meters[key]
|
||||
if !ok {
|
||||
entry = &meterEntry{}
|
||||
entry.unique = registry.NewUniqueInstrumentMeterImpl(&entry.impl)
|
||||
p.meters[key] = entry
|
||||
|
||||
}
|
||||
return metric.WrapMeterImpl(entry.unique, key.Name, metric.WithInstrumentationVersion(key.Version))
|
||||
}
|
||||
|
||||
// Meter interface and delegation
|
||||
|
||||
func (m *meterImpl) setDelegate(name, version string, provider metric.MeterProvider) {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
d := new(metric.MeterImpl)
|
||||
*d = provider.Meter(name, metric.WithInstrumentationVersion(version)).MeterImpl()
|
||||
m.delegate = unsafe.Pointer(d)
|
||||
|
||||
for _, inst := range m.syncInsts {
|
||||
inst.setDelegate(*d)
|
||||
}
|
||||
m.syncInsts = nil
|
||||
for _, obs := range m.asyncInsts {
|
||||
obs.setDelegate(*d)
|
||||
}
|
||||
m.asyncInsts = nil
|
||||
}
|
||||
|
||||
func (m *meterImpl) NewSyncInstrument(desc metric.Descriptor) (metric.SyncImpl, error) {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
if meterPtr := (*metric.MeterImpl)(atomic.LoadPointer(&m.delegate)); meterPtr != nil {
|
||||
return (*meterPtr).NewSyncInstrument(desc)
|
||||
}
|
||||
|
||||
inst := &syncImpl{
|
||||
instrument: instrument{
|
||||
descriptor: desc,
|
||||
},
|
||||
}
|
||||
m.syncInsts = append(m.syncInsts, inst)
|
||||
return inst, nil
|
||||
}
|
||||
|
||||
// Synchronous delegation
|
||||
|
||||
func (inst *syncImpl) setDelegate(d metric.MeterImpl) {
|
||||
implPtr := new(metric.SyncImpl)
|
||||
|
||||
var err error
|
||||
*implPtr, err = d.NewSyncInstrument(inst.descriptor)
|
||||
|
||||
if err != nil {
|
||||
// TODO: There is no standard way to deliver this error to the user.
|
||||
// See https://github.com/open-telemetry/opentelemetry-go/issues/514
|
||||
// Note that the default SDK will not generate any errors yet, this is
|
||||
// only for added safety.
|
||||
panic(err)
|
||||
}
|
||||
|
||||
atomic.StorePointer(&inst.delegate, unsafe.Pointer(implPtr))
|
||||
}
|
||||
|
||||
func (inst *syncImpl) Implementation() interface{} {
|
||||
if implPtr := (*metric.SyncImpl)(atomic.LoadPointer(&inst.delegate)); implPtr != nil {
|
||||
return (*implPtr).Implementation()
|
||||
}
|
||||
return inst
|
||||
}
|
||||
|
||||
func (inst *syncImpl) Bind(labels []label.KeyValue) metric.BoundSyncImpl {
|
||||
if implPtr := (*metric.SyncImpl)(atomic.LoadPointer(&inst.delegate)); implPtr != nil {
|
||||
return (*implPtr).Bind(labels)
|
||||
}
|
||||
return &syncHandle{
|
||||
inst: inst,
|
||||
labels: labels,
|
||||
}
|
||||
}
|
||||
|
||||
func (bound *syncHandle) Unbind() {
|
||||
bound.initialize.Do(func() {})
|
||||
|
||||
implPtr := (*metric.BoundSyncImpl)(atomic.LoadPointer(&bound.delegate))
|
||||
|
||||
if implPtr == nil {
|
||||
return
|
||||
}
|
||||
|
||||
(*implPtr).Unbind()
|
||||
}
|
||||
|
||||
// Async delegation
|
||||
|
||||
func (m *meterImpl) NewAsyncInstrument(
|
||||
desc metric.Descriptor,
|
||||
runner metric.AsyncRunner,
|
||||
) (metric.AsyncImpl, error) {
|
||||
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
|
||||
if meterPtr := (*metric.MeterImpl)(atomic.LoadPointer(&m.delegate)); meterPtr != nil {
|
||||
return (*meterPtr).NewAsyncInstrument(desc, runner)
|
||||
}
|
||||
|
||||
inst := &asyncImpl{
|
||||
instrument: instrument{
|
||||
descriptor: desc,
|
||||
},
|
||||
runner: runner,
|
||||
}
|
||||
m.asyncInsts = append(m.asyncInsts, inst)
|
||||
return inst, nil
|
||||
}
|
||||
|
||||
func (obs *asyncImpl) Implementation() interface{} {
|
||||
if implPtr := (*metric.AsyncImpl)(atomic.LoadPointer(&obs.delegate)); implPtr != nil {
|
||||
return (*implPtr).Implementation()
|
||||
}
|
||||
return obs
|
||||
}
|
||||
|
||||
func (obs *asyncImpl) setDelegate(d metric.MeterImpl) {
|
||||
implPtr := new(metric.AsyncImpl)
|
||||
|
||||
var err error
|
||||
*implPtr, err = d.NewAsyncInstrument(obs.descriptor, obs.runner)
|
||||
|
||||
if err != nil {
|
||||
// TODO: There is no standard way to deliver this error to the user.
|
||||
// See https://github.com/open-telemetry/opentelemetry-go/issues/514
|
||||
// Note that the default SDK will not generate any errors yet, this is
|
||||
// only for added safety.
|
||||
panic(err)
|
||||
}
|
||||
|
||||
atomic.StorePointer(&obs.delegate, unsafe.Pointer(implPtr))
|
||||
}
|
||||
|
||||
// Metric updates
|
||||
|
||||
func (m *meterImpl) RecordBatch(ctx context.Context, labels []label.KeyValue, measurements ...metric.Measurement) {
|
||||
if delegatePtr := (*metric.MeterImpl)(atomic.LoadPointer(&m.delegate)); delegatePtr != nil {
|
||||
(*delegatePtr).RecordBatch(ctx, labels, measurements...)
|
||||
}
|
||||
}
|
||||
|
||||
func (inst *syncImpl) RecordOne(ctx context.Context, number number.Number, labels []label.KeyValue) {
|
||||
if instPtr := (*metric.SyncImpl)(atomic.LoadPointer(&inst.delegate)); instPtr != nil {
|
||||
(*instPtr).RecordOne(ctx, number, labels)
|
||||
}
|
||||
}
|
||||
|
||||
// Bound instrument initialization
|
||||
|
||||
func (bound *syncHandle) RecordOne(ctx context.Context, number number.Number) {
|
||||
instPtr := (*metric.SyncImpl)(atomic.LoadPointer(&bound.inst.delegate))
|
||||
if instPtr == nil {
|
||||
return
|
||||
}
|
||||
var implPtr *metric.BoundSyncImpl
|
||||
bound.initialize.Do(func() {
|
||||
implPtr = new(metric.BoundSyncImpl)
|
||||
*implPtr = (*instPtr).Bind(bound.labels)
|
||||
atomic.StorePointer(&bound.delegate, unsafe.Pointer(implPtr))
|
||||
})
|
||||
if implPtr == nil {
|
||||
implPtr = (*metric.BoundSyncImpl)(atomic.LoadPointer(&bound.delegate))
|
||||
}
|
||||
// This may still be nil if instrument was created and bound
|
||||
// without a delegate, then the instrument was set to have a
|
||||
// delegate and unbound.
|
||||
if implPtr == nil {
|
||||
return
|
||||
}
|
||||
(*implPtr).RecordOne(ctx, number)
|
||||
}
|
||||
|
||||
func AtomicFieldOffsets() map[string]uintptr {
|
||||
return map[string]uintptr{
|
||||
"meterProvider.delegate": unsafe.Offsetof(meterProvider{}.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),
|
||||
}
|
||||
}
|
82
vendor/go.opentelemetry.io/otel/internal/global/propagator.go
generated
vendored
Normal file
82
vendor/go.opentelemetry.io/otel/internal/global/propagator.go
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package global
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
)
|
||||
|
||||
// textMapPropagator is a default TextMapPropagator that delegates calls to a
|
||||
// registered delegate if one is set, otherwise it defaults to delegating the
|
||||
// calls to a the default no-op propagation.TextMapPropagator.
|
||||
type textMapPropagator struct {
|
||||
mtx sync.Mutex
|
||||
once sync.Once
|
||||
delegate propagation.TextMapPropagator
|
||||
noop propagation.TextMapPropagator
|
||||
}
|
||||
|
||||
// Compile-time guarantee that textMapPropagator implements the
|
||||
// propagation.TextMapPropagator interface.
|
||||
var _ propagation.TextMapPropagator = (*textMapPropagator)(nil)
|
||||
|
||||
func newTextMapPropagator() *textMapPropagator {
|
||||
return &textMapPropagator{
|
||||
noop: propagation.NewCompositeTextMapPropagator(),
|
||||
}
|
||||
}
|
||||
|
||||
// SetDelegate sets a delegate propagation.TextMapPropagator that all calls are
|
||||
// forwarded to. Delegation can only be performed once, all subsequent calls
|
||||
// perform no delegation.
|
||||
func (p *textMapPropagator) SetDelegate(delegate propagation.TextMapPropagator) {
|
||||
if delegate == nil {
|
||||
return
|
||||
}
|
||||
|
||||
p.mtx.Lock()
|
||||
p.once.Do(func() { p.delegate = delegate })
|
||||
p.mtx.Unlock()
|
||||
}
|
||||
|
||||
// effectiveDelegate returns the current delegate of p if one is set,
|
||||
// otherwise the default noop TextMapPropagator is returned. This method
|
||||
// can be called concurrently.
|
||||
func (p *textMapPropagator) effectiveDelegate() propagation.TextMapPropagator {
|
||||
p.mtx.Lock()
|
||||
defer p.mtx.Unlock()
|
||||
if p.delegate != nil {
|
||||
return p.delegate
|
||||
}
|
||||
return p.noop
|
||||
}
|
||||
|
||||
// Inject set cross-cutting concerns from the Context into the carrier.
|
||||
func (p *textMapPropagator) Inject(ctx context.Context, carrier propagation.TextMapCarrier) {
|
||||
p.effectiveDelegate().Inject(ctx, carrier)
|
||||
}
|
||||
|
||||
// Extract reads cross-cutting concerns from the carrier into a Context.
|
||||
func (p *textMapPropagator) Extract(ctx context.Context, carrier propagation.TextMapCarrier) context.Context {
|
||||
return p.effectiveDelegate().Extract(ctx, carrier)
|
||||
}
|
||||
|
||||
// Fields returns the keys whose values are set with Inject.
|
||||
func (p *textMapPropagator) Fields() []string {
|
||||
return p.effectiveDelegate().Fields()
|
||||
}
|
143
vendor/go.opentelemetry.io/otel/internal/global/state.go
generated
vendored
Normal file
143
vendor/go.opentelemetry.io/otel/internal/global/state.go
generated
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package global
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
type (
|
||||
tracerProviderHolder struct {
|
||||
tp trace.TracerProvider
|
||||
}
|
||||
|
||||
meterProviderHolder struct {
|
||||
mp metric.MeterProvider
|
||||
}
|
||||
|
||||
propagatorsHolder struct {
|
||||
tm propagation.TextMapPropagator
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
globalTracer = defaultTracerValue()
|
||||
globalMeter = defaultMeterValue()
|
||||
globalPropagators = defaultPropagatorsValue()
|
||||
|
||||
delegateMeterOnce sync.Once
|
||||
delegateTraceOnce sync.Once
|
||||
delegateTextMapPropagatorOnce sync.Once
|
||||
)
|
||||
|
||||
// TracerProvider is the internal implementation for global.TracerProvider.
|
||||
func TracerProvider() trace.TracerProvider {
|
||||
return globalTracer.Load().(tracerProviderHolder).tp
|
||||
}
|
||||
|
||||
// SetTracerProvider is the internal implementation for global.SetTracerProvider.
|
||||
func SetTracerProvider(tp trace.TracerProvider) {
|
||||
delegateTraceOnce.Do(func() {
|
||||
current := TracerProvider()
|
||||
if current == tp {
|
||||
// Setting the provider to the prior default is nonsense, panic.
|
||||
// Panic is acceptable because we are likely still early in the
|
||||
// process lifetime.
|
||||
panic("invalid TracerProvider, the global instance cannot be reinstalled")
|
||||
} else if def, ok := current.(*tracerProvider); ok {
|
||||
def.setDelegate(tp)
|
||||
}
|
||||
|
||||
})
|
||||
globalTracer.Store(tracerProviderHolder{tp: tp})
|
||||
}
|
||||
|
||||
// MeterProvider is the internal implementation for global.MeterProvider.
|
||||
func MeterProvider() metric.MeterProvider {
|
||||
return globalMeter.Load().(meterProviderHolder).mp
|
||||
}
|
||||
|
||||
// SetMeterProvider is the internal implementation for global.SetMeterProvider.
|
||||
func SetMeterProvider(mp metric.MeterProvider) {
|
||||
delegateMeterOnce.Do(func() {
|
||||
current := MeterProvider()
|
||||
|
||||
if current == mp {
|
||||
// Setting the provider to the prior default is nonsense, panic.
|
||||
// Panic is acceptable because we are likely still early in the
|
||||
// process lifetime.
|
||||
panic("invalid MeterProvider, the global instance cannot be reinstalled")
|
||||
} else if def, ok := current.(*meterProvider); ok {
|
||||
def.setDelegate(mp)
|
||||
}
|
||||
})
|
||||
globalMeter.Store(meterProviderHolder{mp: mp})
|
||||
}
|
||||
|
||||
// TextMapPropagator is the internal implementation for global.TextMapPropagator.
|
||||
func TextMapPropagator() propagation.TextMapPropagator {
|
||||
return globalPropagators.Load().(propagatorsHolder).tm
|
||||
}
|
||||
|
||||
// SetTextMapPropagator is the internal implementation for global.SetTextMapPropagator.
|
||||
func SetTextMapPropagator(p propagation.TextMapPropagator) {
|
||||
// For the textMapPropagator already returned by TextMapPropagator
|
||||
// delegate to p.
|
||||
delegateTextMapPropagatorOnce.Do(func() {
|
||||
if current := TextMapPropagator(); current == p {
|
||||
// Setting the provider to the prior default is nonsense, panic.
|
||||
// Panic is acceptable because we are likely still early in the
|
||||
// process lifetime.
|
||||
panic("invalid TextMapPropagator, the global instance cannot be reinstalled")
|
||||
} else if def, ok := current.(*textMapPropagator); ok {
|
||||
def.SetDelegate(p)
|
||||
}
|
||||
})
|
||||
// Return p when subsequent calls to TextMapPropagator are made.
|
||||
globalPropagators.Store(propagatorsHolder{tm: p})
|
||||
}
|
||||
|
||||
func defaultTracerValue() *atomic.Value {
|
||||
v := &atomic.Value{}
|
||||
v.Store(tracerProviderHolder{tp: &tracerProvider{}})
|
||||
return v
|
||||
}
|
||||
|
||||
func defaultMeterValue() *atomic.Value {
|
||||
v := &atomic.Value{}
|
||||
v.Store(meterProviderHolder{mp: newMeterProvider()})
|
||||
return v
|
||||
}
|
||||
|
||||
func defaultPropagatorsValue() *atomic.Value {
|
||||
v := &atomic.Value{}
|
||||
v.Store(propagatorsHolder{tm: newTextMapPropagator()})
|
||||
return v
|
||||
}
|
||||
|
||||
// ResetForTest restores the initial global state, for testing purposes.
|
||||
func ResetForTest() {
|
||||
globalTracer = defaultTracerValue()
|
||||
globalMeter = defaultMeterValue()
|
||||
globalPropagators = defaultPropagatorsValue()
|
||||
delegateMeterOnce = sync.Once{}
|
||||
delegateTraceOnce = sync.Once{}
|
||||
delegateTextMapPropagatorOnce = sync.Once{}
|
||||
}
|
128
vendor/go.opentelemetry.io/otel/internal/global/trace.go
generated
vendored
Normal file
128
vendor/go.opentelemetry.io/otel/internal/global/trace.go
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package global
|
||||
|
||||
/*
|
||||
This file contains the forwarding implementation of the TracerProvider used as
|
||||
the default global instance. Prior to initialization of an SDK, Tracers
|
||||
returned by the global TracerProvider will provide no-op functionality. This
|
||||
means that all Span created prior to initialization are no-op Spans.
|
||||
|
||||
Once an SDK has been initialized, all provided no-op Tracers are swapped for
|
||||
Tracers provided by the SDK defined TracerProvider. However, any Span started
|
||||
prior to this initialization does not change its behavior. Meaning, the Span
|
||||
remains a no-op Span.
|
||||
|
||||
The implementation to track and swap Tracers locks all new Tracer creation
|
||||
until the swap is complete. This assumes that this operation is not
|
||||
performance-critical. If that assumption is incorrect, be sure to configure an
|
||||
SDK prior to any Tracer creation.
|
||||
*/
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"go.opentelemetry.io/otel/internal/trace/noop"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// tracerProvider is a placeholder for a configured SDK TracerProvider.
|
||||
//
|
||||
// All TracerProvider functionality is forwarded to a delegate once
|
||||
// configured.
|
||||
type tracerProvider struct {
|
||||
mtx sync.Mutex
|
||||
tracers []*tracer
|
||||
|
||||
delegate trace.TracerProvider
|
||||
}
|
||||
|
||||
// Compile-time guarantee that tracerProvider implements the TracerProvider
|
||||
// interface.
|
||||
var _ trace.TracerProvider = &tracerProvider{}
|
||||
|
||||
// setDelegate configures p to delegate all TracerProvider functionality to
|
||||
// provider.
|
||||
//
|
||||
// All Tracers provided prior to this function call are switched out to be
|
||||
// Tracers provided by provider.
|
||||
//
|
||||
// Delegation only happens on the first call to this method. All subsequent
|
||||
// calls result in no delegation changes.
|
||||
func (p *tracerProvider) setDelegate(provider trace.TracerProvider) {
|
||||
if p.delegate != nil {
|
||||
return
|
||||
}
|
||||
|
||||
p.mtx.Lock()
|
||||
defer p.mtx.Unlock()
|
||||
|
||||
p.delegate = provider
|
||||
for _, t := range p.tracers {
|
||||
t.setDelegate(provider)
|
||||
}
|
||||
|
||||
p.tracers = nil
|
||||
}
|
||||
|
||||
// Tracer implements TracerProvider.
|
||||
func (p *tracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.Tracer {
|
||||
p.mtx.Lock()
|
||||
defer p.mtx.Unlock()
|
||||
|
||||
if p.delegate != nil {
|
||||
return p.delegate.Tracer(name, opts...)
|
||||
}
|
||||
|
||||
t := &tracer{name: name, opts: opts}
|
||||
p.tracers = append(p.tracers, t)
|
||||
return t
|
||||
}
|
||||
|
||||
// tracer is a placeholder for a trace.Tracer.
|
||||
//
|
||||
// All Tracer functionality is forwarded to a delegate once configured.
|
||||
// Otherwise, all functionality is forwarded to a NoopTracer.
|
||||
type tracer struct {
|
||||
once sync.Once
|
||||
name string
|
||||
opts []trace.TracerOption
|
||||
|
||||
delegate trace.Tracer
|
||||
}
|
||||
|
||||
// Compile-time guarantee that tracer implements the trace.Tracer interface.
|
||||
var _ trace.Tracer = &tracer{}
|
||||
|
||||
// setDelegate configures t to delegate all Tracer functionality to Tracers
|
||||
// created by provider.
|
||||
//
|
||||
// All subsequent calls to the Tracer methods will be passed to the delegate.
|
||||
//
|
||||
// Delegation only happens on the first call to this method. All subsequent
|
||||
// calls result in no delegation changes.
|
||||
func (t *tracer) setDelegate(provider trace.TracerProvider) {
|
||||
t.once.Do(func() { t.delegate = provider.Tracer(t.name, t.opts...) })
|
||||
}
|
||||
|
||||
// Start implements trace.Tracer by forwarding the call to t.delegate if
|
||||
// set, otherwise it forwards the call to a NoopTracer.
|
||||
func (t *tracer) Start(ctx context.Context, name string, opts ...trace.SpanOption) (context.Context, trace.Span) {
|
||||
if t.delegate != nil {
|
||||
return t.delegate.Start(ctx, name, opts...)
|
||||
}
|
||||
return noop.Tracer.Start(ctx, name, opts...)
|
||||
}
|
91
vendor/go.opentelemetry.io/otel/internal/rawhelpers.go
generated
vendored
Normal file
91
vendor/go.opentelemetry.io/otel/internal/rawhelpers.go
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"math"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func BoolToRaw(b bool) uint64 {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func RawToBool(r uint64) bool {
|
||||
return r != 0
|
||||
}
|
||||
|
||||
func Int64ToRaw(i int64) uint64 {
|
||||
return uint64(i)
|
||||
}
|
||||
|
||||
func RawToInt64(r uint64) int64 {
|
||||
return int64(r)
|
||||
}
|
||||
|
||||
func Uint64ToRaw(u uint64) uint64 {
|
||||
return u
|
||||
}
|
||||
|
||||
func RawToUint64(r uint64) uint64 {
|
||||
return r
|
||||
}
|
||||
|
||||
func Float64ToRaw(f float64) uint64 {
|
||||
return math.Float64bits(f)
|
||||
}
|
||||
|
||||
func RawToFloat64(r uint64) float64 {
|
||||
return math.Float64frombits(r)
|
||||
}
|
||||
|
||||
func Int32ToRaw(i int32) uint64 {
|
||||
return uint64(i)
|
||||
}
|
||||
|
||||
func RawToInt32(r uint64) int32 {
|
||||
return int32(r)
|
||||
}
|
||||
|
||||
func Uint32ToRaw(u uint32) uint64 {
|
||||
return uint64(u)
|
||||
}
|
||||
|
||||
func RawToUint32(r uint64) uint32 {
|
||||
return uint32(r)
|
||||
}
|
||||
|
||||
func Float32ToRaw(f float32) uint64 {
|
||||
return Uint32ToRaw(math.Float32bits(f))
|
||||
}
|
||||
|
||||
func RawToFloat32(r uint64) float32 {
|
||||
return math.Float32frombits(RawToUint32(r))
|
||||
}
|
||||
|
||||
func RawPtrToFloat64Ptr(r *uint64) *float64 {
|
||||
return (*float64)(unsafe.Pointer(r))
|
||||
}
|
||||
|
||||
func RawPtrToInt64Ptr(r *uint64) *int64 {
|
||||
return (*int64)(unsafe.Pointer(r))
|
||||
}
|
||||
|
||||
func RawPtrToUint64Ptr(r *uint64) *uint64 {
|
||||
return r
|
||||
}
|
35
vendor/go.opentelemetry.io/otel/internal/trace/noop/noop.go
generated
vendored
Normal file
35
vendor/go.opentelemetry.io/otel/internal/trace/noop/noop.go
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
// Copyright The OpenTelemetry Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package noop provides noop tracing implementations for tracer and span.
|
||||
package noop
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
var (
|
||||
// Tracer is a noop tracer that starts noop spans.
|
||||
Tracer trace.Tracer
|
||||
|
||||
// Span is a noop Span.
|
||||
Span trace.Span
|
||||
)
|
||||
|
||||
func init() {
|
||||
Tracer = trace.NewNoopTracerProvider().Tracer("")
|
||||
_, Span = Tracer.Start(context.Background(), "")
|
||||
}
|
Reference in New Issue
Block a user