1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2025-04-13 11:30:31 +02:00

Replace meterRegistry with cache (#3255)

This commit is contained in:
Tyler Yahn 2022-10-12 12:54:51 -07:00 committed by GitHub
parent ff18552791
commit 4a3adaafd4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 7 additions and 76 deletions

View File

@ -16,7 +16,6 @@ package metric // import "go.opentelemetry.io/otel/sdk/metric"
import (
"context"
"sync"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/metric/instrument"
@ -27,49 +26,6 @@ import (
"go.opentelemetry.io/otel/sdk/instrumentation"
)
// meterRegistry keeps a record of initialized meters for instrumentation
// scopes. A meter is unique to an instrumentation scope and if multiple
// requests for that meter are made a meterRegistry ensure the same instance
// is used.
//
// The zero meterRegistry is empty and ready for use.
//
// A meterRegistry must not be copied after first use.
//
// All methods of a meterRegistry are safe to call concurrently.
type meterRegistry struct {
sync.Mutex
meters map[instrumentation.Scope]*meter
pipes pipelines
}
// Get returns a registered meter matching the instrumentation scope if it
// exists in the meterRegistry. Otherwise, a new meter configured for the
// instrumentation scope is registered and then returned.
//
// Get is safe to call concurrently.
func (r *meterRegistry) Get(s instrumentation.Scope) *meter {
r.Lock()
defer r.Unlock()
if r.meters == nil {
m := newMeter(s, r.pipes)
r.meters = map[instrumentation.Scope]*meter{s: m}
return m
}
m, ok := r.meters[s]
if ok {
return m
}
m = newMeter(s, r.pipes)
r.meters[s] = m
return m
}
// meter handles the creation and coordination of all metric instruments. A
// meter represents a single instrumentation scope; all metric telemetry
// produced by an instrumentation scope will use metric instruments from a

View File

@ -31,28 +31,6 @@ import (
"go.opentelemetry.io/otel/sdk/resource"
)
func TestMeterRegistry(t *testing.T) {
is0 := instrumentation.Scope{Name: "zero"}
is1 := instrumentation.Scope{Name: "one"}
r := meterRegistry{}
var m0 *meter
t.Run("ZeroValueGetDoesNotPanic", func(t *testing.T) {
assert.NotPanics(t, func() { m0 = r.Get(is0) })
assert.Equal(t, is0, m0.Scope, "uninitialized meter returned")
})
m01 := r.Get(is0)
t.Run("GetSameMeter", func(t *testing.T) {
assert.Samef(t, m0, m01, "returned different meters: %v", is0)
})
m1 := r.Get(is1)
t.Run("GetDifferentMeter", func(t *testing.T) {
assert.NotSamef(t, m0, m1, "returned same meters: %v", is1)
})
}
// A meter should be able to make instruments concurrently.
func TestMeterInstrumentConcurrency(t *testing.T) {
wg := &sync.WaitGroup{}

View File

@ -26,7 +26,8 @@ import (
// the same Views applied to them, and have their produced metric telemetry
// passed to the configured Readers.
type MeterProvider struct {
meters meterRegistry
pipes pipelines
meters cache[instrumentation.Scope, *meter]
forceFlush, shutdown func(context.Context) error
}
@ -42,16 +43,9 @@ var _ metric.MeterProvider = (*MeterProvider)(nil)
// Readers, will perform no operations.
func NewMeterProvider(options ...Option) *MeterProvider {
conf := newConfig(options)
flush, sdown := conf.readerSignals()
registry := newPipelines(conf.res, conf.readers)
return &MeterProvider{
meters: meterRegistry{
pipes: registry,
},
pipes: newPipelines(conf.res, conf.readers),
forceFlush: flush,
shutdown: sdown,
}
@ -72,10 +66,13 @@ func NewMeterProvider(options ...Option) *MeterProvider {
// This method is safe to call concurrently.
func (mp *MeterProvider) Meter(name string, options ...metric.MeterOption) metric.Meter {
c := metric.NewMeterConfig(options...)
return mp.meters.Get(instrumentation.Scope{
s := instrumentation.Scope{
Name: name,
Version: c.InstrumentationVersion(),
SchemaURL: c.SchemaURL(),
}
return mp.meters.Lookup(s, func() *meter {
return newMeter(s, mp.pipes)
})
}