Skip to content

Commit c2a84cc

Browse files
authored
Use RWMutex in OTEL provider (#214)
Currently, the `otel.Provider` uses a `sync.Mutex` to protect against race conditions on the maps that store instances of the different metric types. The mutex blocks to ensure the existence of a metric on metric modification. We can avoid fully blocking on reads for already existing metrics with a `sync.RWMutex`.
1 parent 9d4439f commit c2a84cc

File tree

2 files changed

+29
-5
lines changed

2 files changed

+29
-5
lines changed

go-kit/metrics/provider/otel/provider.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ type Provider struct {
4040
meterProvider *metric.MeterProvider
4141
viewCache *viewCache
4242

43-
mu sync.Mutex
43+
mu sync.RWMutex
4444
counters map[string]*Counter
4545
gauges map[string]*Gauge
4646
histograms map[string]*Histogram

go-kit/metrics/provider/otel/types.go

+28-4
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,18 @@ func (p *Provider) NewCounter(name string) metrics.Counter {
4545
}
4646

4747
func (p *Provider) newCounter(name string, labelValues ...string) metrics.Counter {
48+
k := keyName(name, labelValues...)
49+
50+
p.mu.RLock()
51+
c, ok := p.counters[k]
52+
p.mu.RUnlock()
53+
if ok {
54+
return c
55+
}
56+
4857
p.mu.Lock()
4958
defer p.mu.Unlock()
5059

51-
k := keyName(name, labelValues...)
5260
m := p.meterProvider.Meter(name)
5361

5462
if _, ok := p.counters[k]; !ok {
@@ -82,10 +90,18 @@ func (p *Provider) NewGauge(name string) metrics.Gauge {
8290
}
8391

8492
func (p *Provider) newGauge(name string, labelValues ...string) metrics.Gauge {
93+
k := keyName(name, labelValues...)
94+
95+
p.mu.RLock()
96+
g, ok := p.gauges[k]
97+
p.mu.RUnlock()
98+
if ok {
99+
return g
100+
}
101+
85102
p.mu.Lock()
86103
defer p.mu.Unlock()
87104

88-
k := keyName(name, labelValues...)
89105
m := p.meterProvider.Meter(name)
90106

91107
attributes := makeAttributes(labelValues)
@@ -166,11 +182,19 @@ func (p *Provider) NewHistogram(name string, buckets int) metrics.Histogram {
166182
}
167183

168184
func (p *Provider) newHistogram(stream sdk.Stream, labelValues ...string) metrics.Histogram {
185+
name := stream.Name
186+
k := keyName(name, labelValues...)
187+
188+
p.mu.RLock()
189+
h, ok := p.histograms[k]
190+
p.mu.RUnlock()
191+
if ok {
192+
return h
193+
}
194+
169195
p.mu.Lock()
170196
defer p.mu.Unlock()
171197

172-
name := stream.Name
173-
k := keyName(name, labelValues...)
174198
m := p.meterProvider.Meter(name)
175199

176200
if _, ok := p.histograms[k]; !ok {

0 commit comments

Comments
 (0)