Skip to content

Commit d0c45e5

Browse files
committed
Merge branch 'main' into span-onending
2 parents 35768bd + e47618f commit d0c45e5

File tree

3 files changed

+145
-18
lines changed

3 files changed

+145
-18
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
1212

1313
- Support for the `OnEnding` callback in span processors. (#5756)
1414

15+
### Fixed
16+
17+
- Fix memory leak in the global `MeterProvider` when identical instruments are repeatedly created. (#5754)
18+
1519
### Removed
1620

1721
- Drop support for [Go 1.21]. (#5736, #5740)

internal/global/meter.go

Lines changed: 127 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package global // import "go.opentelemetry.io/otel/internal/global"
55

66
import (
77
"container/list"
8+
"reflect"
89
"sync"
910
"sync/atomic"
1011

@@ -76,7 +77,7 @@ func (p *meterProvider) Meter(name string, opts ...metric.MeterOption) metric.Me
7677
return val
7778
}
7879

79-
t := &meter{name: name, opts: opts}
80+
t := &meter{name: name, opts: opts, instruments: make(map[instID]delegatedInstrument)}
8081
p.meters[key] = t
8182
return t
8283
}
@@ -92,7 +93,7 @@ type meter struct {
9293
opts []metric.MeterOption
9394

9495
mtx sync.Mutex
95-
instruments []delegatedInstrument
96+
instruments map[instID]delegatedInstrument
9697

9798
registry list.List
9899

@@ -103,6 +104,18 @@ type delegatedInstrument interface {
103104
setDelegate(metric.Meter)
104105
}
105106

107+
// instID are the identifying properties of a instrument.
108+
type instID struct {
109+
// name is the name of the stream.
110+
name string
111+
// description is the description of the stream.
112+
description string
113+
// kind defines the functional group of the instrument.
114+
kind reflect.Type
115+
// unit is the unit of the stream.
116+
unit string
117+
}
118+
106119
// setDelegate configures m to delegate all Meter functionality to Meters
107120
// created by provider.
108121
//
@@ -139,7 +152,14 @@ func (m *meter) Int64Counter(name string, options ...metric.Int64CounterOption)
139152
m.mtx.Lock()
140153
defer m.mtx.Unlock()
141154
i := &siCounter{name: name, opts: options}
142-
m.instruments = append(m.instruments, i)
155+
cfg := metric.NewInt64CounterConfig(options...)
156+
id := instID{
157+
name: name,
158+
kind: reflect.TypeOf(i),
159+
description: cfg.Description(),
160+
unit: cfg.Unit(),
161+
}
162+
m.instruments[id] = i
143163
return i, nil
144164
}
145165

@@ -150,7 +170,14 @@ func (m *meter) Int64UpDownCounter(name string, options ...metric.Int64UpDownCou
150170
m.mtx.Lock()
151171
defer m.mtx.Unlock()
152172
i := &siUpDownCounter{name: name, opts: options}
153-
m.instruments = append(m.instruments, i)
173+
cfg := metric.NewInt64UpDownCounterConfig(options...)
174+
id := instID{
175+
name: name,
176+
kind: reflect.TypeOf(i),
177+
description: cfg.Description(),
178+
unit: cfg.Unit(),
179+
}
180+
m.instruments[id] = i
154181
return i, nil
155182
}
156183

@@ -161,7 +188,14 @@ func (m *meter) Int64Histogram(name string, options ...metric.Int64HistogramOpti
161188
m.mtx.Lock()
162189
defer m.mtx.Unlock()
163190
i := &siHistogram{name: name, opts: options}
164-
m.instruments = append(m.instruments, i)
191+
cfg := metric.NewInt64HistogramConfig(options...)
192+
id := instID{
193+
name: name,
194+
kind: reflect.TypeOf(i),
195+
description: cfg.Description(),
196+
unit: cfg.Unit(),
197+
}
198+
m.instruments[id] = i
165199
return i, nil
166200
}
167201

@@ -172,7 +206,14 @@ func (m *meter) Int64Gauge(name string, options ...metric.Int64GaugeOption) (met
172206
m.mtx.Lock()
173207
defer m.mtx.Unlock()
174208
i := &siGauge{name: name, opts: options}
175-
m.instruments = append(m.instruments, i)
209+
cfg := metric.NewInt64GaugeConfig(options...)
210+
id := instID{
211+
name: name,
212+
kind: reflect.TypeOf(i),
213+
description: cfg.Description(),
214+
unit: cfg.Unit(),
215+
}
216+
m.instruments[id] = i
176217
return i, nil
177218
}
178219

@@ -183,7 +224,14 @@ func (m *meter) Int64ObservableCounter(name string, options ...metric.Int64Obser
183224
m.mtx.Lock()
184225
defer m.mtx.Unlock()
185226
i := &aiCounter{name: name, opts: options}
186-
m.instruments = append(m.instruments, i)
227+
cfg := metric.NewInt64ObservableCounterConfig(options...)
228+
id := instID{
229+
name: name,
230+
kind: reflect.TypeOf(i),
231+
description: cfg.Description(),
232+
unit: cfg.Unit(),
233+
}
234+
m.instruments[id] = i
187235
return i, nil
188236
}
189237

@@ -194,7 +242,14 @@ func (m *meter) Int64ObservableUpDownCounter(name string, options ...metric.Int6
194242
m.mtx.Lock()
195243
defer m.mtx.Unlock()
196244
i := &aiUpDownCounter{name: name, opts: options}
197-
m.instruments = append(m.instruments, i)
245+
cfg := metric.NewInt64ObservableUpDownCounterConfig(options...)
246+
id := instID{
247+
name: name,
248+
kind: reflect.TypeOf(i),
249+
description: cfg.Description(),
250+
unit: cfg.Unit(),
251+
}
252+
m.instruments[id] = i
198253
return i, nil
199254
}
200255

@@ -205,7 +260,14 @@ func (m *meter) Int64ObservableGauge(name string, options ...metric.Int64Observa
205260
m.mtx.Lock()
206261
defer m.mtx.Unlock()
207262
i := &aiGauge{name: name, opts: options}
208-
m.instruments = append(m.instruments, i)
263+
cfg := metric.NewInt64ObservableGaugeConfig(options...)
264+
id := instID{
265+
name: name,
266+
kind: reflect.TypeOf(i),
267+
description: cfg.Description(),
268+
unit: cfg.Unit(),
269+
}
270+
m.instruments[id] = i
209271
return i, nil
210272
}
211273

@@ -216,7 +278,14 @@ func (m *meter) Float64Counter(name string, options ...metric.Float64CounterOpti
216278
m.mtx.Lock()
217279
defer m.mtx.Unlock()
218280
i := &sfCounter{name: name, opts: options}
219-
m.instruments = append(m.instruments, i)
281+
cfg := metric.NewFloat64CounterConfig(options...)
282+
id := instID{
283+
name: name,
284+
kind: reflect.TypeOf(i),
285+
description: cfg.Description(),
286+
unit: cfg.Unit(),
287+
}
288+
m.instruments[id] = i
220289
return i, nil
221290
}
222291

@@ -227,7 +296,14 @@ func (m *meter) Float64UpDownCounter(name string, options ...metric.Float64UpDow
227296
m.mtx.Lock()
228297
defer m.mtx.Unlock()
229298
i := &sfUpDownCounter{name: name, opts: options}
230-
m.instruments = append(m.instruments, i)
299+
cfg := metric.NewFloat64UpDownCounterConfig(options...)
300+
id := instID{
301+
name: name,
302+
kind: reflect.TypeOf(i),
303+
description: cfg.Description(),
304+
unit: cfg.Unit(),
305+
}
306+
m.instruments[id] = i
231307
return i, nil
232308
}
233309

@@ -238,7 +314,14 @@ func (m *meter) Float64Histogram(name string, options ...metric.Float64Histogram
238314
m.mtx.Lock()
239315
defer m.mtx.Unlock()
240316
i := &sfHistogram{name: name, opts: options}
241-
m.instruments = append(m.instruments, i)
317+
cfg := metric.NewFloat64HistogramConfig(options...)
318+
id := instID{
319+
name: name,
320+
kind: reflect.TypeOf(i),
321+
description: cfg.Description(),
322+
unit: cfg.Unit(),
323+
}
324+
m.instruments[id] = i
242325
return i, nil
243326
}
244327

@@ -249,7 +332,14 @@ func (m *meter) Float64Gauge(name string, options ...metric.Float64GaugeOption)
249332
m.mtx.Lock()
250333
defer m.mtx.Unlock()
251334
i := &sfGauge{name: name, opts: options}
252-
m.instruments = append(m.instruments, i)
335+
cfg := metric.NewFloat64GaugeConfig(options...)
336+
id := instID{
337+
name: name,
338+
kind: reflect.TypeOf(i),
339+
description: cfg.Description(),
340+
unit: cfg.Unit(),
341+
}
342+
m.instruments[id] = i
253343
return i, nil
254344
}
255345

@@ -260,7 +350,14 @@ func (m *meter) Float64ObservableCounter(name string, options ...metric.Float64O
260350
m.mtx.Lock()
261351
defer m.mtx.Unlock()
262352
i := &afCounter{name: name, opts: options}
263-
m.instruments = append(m.instruments, i)
353+
cfg := metric.NewFloat64ObservableCounterConfig(options...)
354+
id := instID{
355+
name: name,
356+
kind: reflect.TypeOf(i),
357+
description: cfg.Description(),
358+
unit: cfg.Unit(),
359+
}
360+
m.instruments[id] = i
264361
return i, nil
265362
}
266363

@@ -271,7 +368,14 @@ func (m *meter) Float64ObservableUpDownCounter(name string, options ...metric.Fl
271368
m.mtx.Lock()
272369
defer m.mtx.Unlock()
273370
i := &afUpDownCounter{name: name, opts: options}
274-
m.instruments = append(m.instruments, i)
371+
cfg := metric.NewFloat64ObservableUpDownCounterConfig(options...)
372+
id := instID{
373+
name: name,
374+
kind: reflect.TypeOf(i),
375+
description: cfg.Description(),
376+
unit: cfg.Unit(),
377+
}
378+
m.instruments[id] = i
275379
return i, nil
276380
}
277381

@@ -282,7 +386,14 @@ func (m *meter) Float64ObservableGauge(name string, options ...metric.Float64Obs
282386
m.mtx.Lock()
283387
defer m.mtx.Unlock()
284388
i := &afGauge{name: name, opts: options}
285-
m.instruments = append(m.instruments, i)
389+
cfg := metric.NewFloat64ObservableGaugeConfig(options...)
390+
id := instID{
391+
name: name,
392+
kind: reflect.TypeOf(i),
393+
description: cfg.Description(),
394+
unit: cfg.Unit(),
395+
}
396+
m.instruments[id] = i
286397
return i, nil
287398
}
288399

internal/global/meter_test.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ var zeroCallback metric.Callback = func(ctx context.Context, or metric.Observer)
4242
}
4343

4444
func TestMeterConcurrentSafe(t *testing.T) {
45-
mtr := &meter{}
45+
mtr := &meter{instruments: make(map[instID]delegatedInstrument)}
4646

4747
wg := &sync.WaitGroup{}
4848
wg.Add(1)
@@ -86,7 +86,7 @@ func TestMeterConcurrentSafe(t *testing.T) {
8686
}
8787

8888
func TestUnregisterConcurrentSafe(t *testing.T) {
89-
mtr := &meter{}
89+
mtr := &meter{instruments: make(map[instID]delegatedInstrument)}
9090
reg, err := mtr.RegisterCallback(zeroCallback)
9191
require.NoError(t, err)
9292

@@ -176,6 +176,18 @@ func testCollect(t *testing.T, m metric.Meter) {
176176
tMeter.collect()
177177
}
178178

179+
func TestInstrumentIdentity(t *testing.T) {
180+
globalMeterProvider := &meterProvider{}
181+
m := globalMeterProvider.Meter("go.opentelemetry.io/otel/metric/internal/global/meter_test")
182+
tMeter := m.(*meter)
183+
testSetupAllInstrumentTypes(t, m)
184+
assert.Len(t, tMeter.instruments, 14)
185+
// Creating the same instruments multiple times should not increase the
186+
// number of instruments.
187+
testSetupAllInstrumentTypes(t, m)
188+
assert.Len(t, tMeter.instruments, 14)
189+
}
190+
179191
func TestMeterProviderDelegatesCalls(t *testing.T) {
180192
// The global MeterProvider should directly call the underlying MeterProvider
181193
// if it is set prior to Meter() being called.

0 commit comments

Comments
 (0)