You've already forked opentelemetry-go
							
							
				mirror of
				https://github.com/open-telemetry/opentelemetry-go.git
				synced 2025-10-31 00:07:40 +02:00 
			
		
		
		
	* Rename *Provider names There is overlap in naming with MeterProviders and TracerProviders. This is means the specification is not implemented and these types can not exist in the same package (#1179). This makes each type and related functions and types explicit. * Add changes to CHANGELOG
		
			
				
	
	
		
			171 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			171 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // 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 registry // import "go.opentelemetry.io/otel/api/metric/registry"
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"fmt"
 | |
| 	"sync"
 | |
| 
 | |
| 	"go.opentelemetry.io/otel/api/metric"
 | |
| 	"go.opentelemetry.io/otel/label"
 | |
| )
 | |
| 
 | |
| // MeterProvider is a standard MeterProvider for wrapping `MeterImpl`
 | |
| type MeterProvider struct {
 | |
| 	impl metric.MeterImpl
 | |
| }
 | |
| 
 | |
| var _ metric.MeterProvider = (*MeterProvider)(nil)
 | |
| 
 | |
| // uniqueInstrumentMeterImpl implements the metric.MeterImpl interface, adding
 | |
| // uniqueness checking for instrument descriptors.  Use NewUniqueInstrumentMeter
 | |
| // to wrap an implementation with uniqueness checking.
 | |
| type uniqueInstrumentMeterImpl struct {
 | |
| 	lock  sync.Mutex
 | |
| 	impl  metric.MeterImpl
 | |
| 	state map[key]metric.InstrumentImpl
 | |
| }
 | |
| 
 | |
| var _ metric.MeterImpl = (*uniqueInstrumentMeterImpl)(nil)
 | |
| 
 | |
| type key struct {
 | |
| 	instrumentName         string
 | |
| 	instrumentationName    string
 | |
| 	InstrumentationVersion string
 | |
| }
 | |
| 
 | |
| // NewMeterProvider returns a new provider that implements instrument
 | |
| // name-uniqueness checking.
 | |
| func NewMeterProvider(impl metric.MeterImpl) *MeterProvider {
 | |
| 	return &MeterProvider{
 | |
| 		impl: NewUniqueInstrumentMeterImpl(impl),
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Meter implements MeterProvider.
 | |
| func (p *MeterProvider) Meter(instrumentationName string, opts ...metric.MeterOption) metric.Meter {
 | |
| 	return metric.WrapMeterImpl(p.impl, instrumentationName, opts...)
 | |
| }
 | |
| 
 | |
| // ErrMetricKindMismatch is the standard error for mismatched metric
 | |
| // instrument definitions.
 | |
| var ErrMetricKindMismatch = fmt.Errorf(
 | |
| 	"A metric was already registered by this name with another kind or number type")
 | |
| 
 | |
| // NewUniqueInstrumentMeterImpl returns a wrapped metric.MeterImpl with
 | |
| // the addition of uniqueness checking.
 | |
| func NewUniqueInstrumentMeterImpl(impl metric.MeterImpl) metric.MeterImpl {
 | |
| 	return &uniqueInstrumentMeterImpl{
 | |
| 		impl:  impl,
 | |
| 		state: map[key]metric.InstrumentImpl{},
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // RecordBatch implements metric.MeterImpl.
 | |
| func (u *uniqueInstrumentMeterImpl) RecordBatch(ctx context.Context, labels []label.KeyValue, ms ...metric.Measurement) {
 | |
| 	u.impl.RecordBatch(ctx, labels, ms...)
 | |
| }
 | |
| 
 | |
| func keyOf(descriptor metric.Descriptor) key {
 | |
| 	return key{
 | |
| 		descriptor.Name(),
 | |
| 		descriptor.InstrumentationName(),
 | |
| 		descriptor.InstrumentationVersion(),
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // NewMetricKindMismatchError formats an error that describes a
 | |
| // mismatched metric instrument definition.
 | |
| func NewMetricKindMismatchError(desc metric.Descriptor) error {
 | |
| 	return fmt.Errorf("Metric was %s (%s %s)registered as a %s %s: %w",
 | |
| 		desc.Name(),
 | |
| 		desc.InstrumentationName(),
 | |
| 		desc.InstrumentationVersion(),
 | |
| 		desc.NumberKind(),
 | |
| 		desc.MetricKind(),
 | |
| 		ErrMetricKindMismatch)
 | |
| }
 | |
| 
 | |
| // Compatible determines whether two metric.Descriptors are considered
 | |
| // the same for the purpose of uniqueness checking.
 | |
| func Compatible(candidate, existing metric.Descriptor) bool {
 | |
| 	return candidate.MetricKind() == existing.MetricKind() &&
 | |
| 		candidate.NumberKind() == existing.NumberKind()
 | |
| }
 | |
| 
 | |
| // checkUniqueness returns an ErrMetricKindMismatch error if there is
 | |
| // a conflict between a descriptor that was already registered and the
 | |
| // `descriptor` argument.  If there is an existing compatible
 | |
| // registration, this returns the already-registered instrument.  If
 | |
| // there is no conflict and no prior registration, returns (nil, nil).
 | |
| func (u *uniqueInstrumentMeterImpl) checkUniqueness(descriptor metric.Descriptor) (metric.InstrumentImpl, error) {
 | |
| 	impl, ok := u.state[keyOf(descriptor)]
 | |
| 	if !ok {
 | |
| 		return nil, nil
 | |
| 	}
 | |
| 
 | |
| 	if !Compatible(descriptor, impl.Descriptor()) {
 | |
| 		return nil, NewMetricKindMismatchError(impl.Descriptor())
 | |
| 	}
 | |
| 
 | |
| 	return impl, nil
 | |
| }
 | |
| 
 | |
| // NewSyncInstrument implements metric.MeterImpl.
 | |
| func (u *uniqueInstrumentMeterImpl) NewSyncInstrument(descriptor metric.Descriptor) (metric.SyncImpl, error) {
 | |
| 	u.lock.Lock()
 | |
| 	defer u.lock.Unlock()
 | |
| 
 | |
| 	impl, err := u.checkUniqueness(descriptor)
 | |
| 
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	} else if impl != nil {
 | |
| 		return impl.(metric.SyncImpl), nil
 | |
| 	}
 | |
| 
 | |
| 	syncInst, err := u.impl.NewSyncInstrument(descriptor)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	u.state[keyOf(descriptor)] = syncInst
 | |
| 	return syncInst, nil
 | |
| }
 | |
| 
 | |
| // NewAsyncInstrument implements metric.MeterImpl.
 | |
| func (u *uniqueInstrumentMeterImpl) NewAsyncInstrument(
 | |
| 	descriptor metric.Descriptor,
 | |
| 	runner metric.AsyncRunner,
 | |
| ) (metric.AsyncImpl, error) {
 | |
| 	u.lock.Lock()
 | |
| 	defer u.lock.Unlock()
 | |
| 
 | |
| 	impl, err := u.checkUniqueness(descriptor)
 | |
| 
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	} else if impl != nil {
 | |
| 		return impl.(metric.AsyncImpl), nil
 | |
| 	}
 | |
| 
 | |
| 	asyncInst, err := u.impl.NewAsyncInstrument(descriptor, runner)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	u.state[keyOf(descriptor)] = asyncInst
 | |
| 	return asyncInst, nil
 | |
| }
 |