Skip to content

Commit 5c6bb39

Browse files
authored
Merge pull request #30 from Tochemey/main
fix: wire cache-level OTel instruments into metric registration path
2 parents 023fedc + cd9e63d commit 5c6bb39

File tree

4 files changed

+98
-62
lines changed

4 files changed

+98
-62
lines changed

group.go

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -622,5 +622,67 @@ func (g *group) registerInstruments(meter otelmetric.Meter) error {
622622
instruments.RemovedKeysCounter(),
623623
)
624624

625-
return err
625+
if err != nil {
626+
return err
627+
}
628+
629+
// Register cache-level instruments for mainCache and hotCache
630+
if err := g.registerCacheInstruments(meter); err != nil {
631+
return err
632+
}
633+
634+
return nil
635+
}
636+
637+
func (g *group) registerCacheInstruments(meter otelmetric.Meter) error {
638+
cacheInstr, err := newCacheInstruments(meter)
639+
if err != nil {
640+
return err
641+
}
642+
643+
type namedCache struct {
644+
name string
645+
cache func() Cache
646+
}
647+
648+
caches := []namedCache{
649+
{name: "main", cache: func() Cache { return g.mainCache }},
650+
{name: "hot", cache: func() Cache { return g.hotCache }},
651+
}
652+
653+
for _, nc := range caches {
654+
observeOptions := []otelmetric.ObserveOption{
655+
otelmetric.WithAttributes(
656+
attribute.String("group.name", g.Name()),
657+
attribute.String("cache.type", nc.name),
658+
),
659+
}
660+
661+
_, err := meter.RegisterCallback(func(ctx context.Context, o otelmetric.Observer) error {
662+
c := nc.cache()
663+
if c == nil {
664+
return nil
665+
}
666+
stats := c.Stats()
667+
o.ObserveInt64(cacheInstr.RejectedCounter(), stats.Rejected, observeOptions...)
668+
o.ObserveInt64(cacheInstr.BytesGauge(), stats.Bytes, observeOptions...)
669+
o.ObserveInt64(cacheInstr.ItemsGauge(), stats.Items, observeOptions...)
670+
o.ObserveInt64(cacheInstr.GetsCounter(), stats.Gets, observeOptions...)
671+
o.ObserveInt64(cacheInstr.HitsCounter(), stats.Hits, observeOptions...)
672+
o.ObserveInt64(cacheInstr.EvictionsCounter(), stats.Evictions, observeOptions...)
673+
return nil
674+
},
675+
cacheInstr.RejectedCounter(),
676+
cacheInstr.BytesGauge(),
677+
cacheInstr.ItemsGauge(),
678+
cacheInstr.GetsCounter(),
679+
cacheInstr.HitsCounter(),
680+
cacheInstr.EvictionsCounter(),
681+
)
682+
if err != nil {
683+
return err
684+
}
685+
}
686+
687+
return nil
626688
}

instance_test.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ func TestNewGroupRegistersMetricsWithMeterProvider(t *testing.T) {
515515
require.NotNil(t, g)
516516

517517
expectedCounters := []string{
518+
// group-level counters
518519
"groupcache.group.gets",
519520
"groupcache.group.cache_hits",
520521
"groupcache.group.peer.loads",
@@ -525,11 +526,21 @@ func TestNewGroupRegistersMetricsWithMeterProvider(t *testing.T) {
525526
"groupcache.group.local.load_errors",
526527
"groupcache.group.remove_keys.requests",
527528
"groupcache.group.removed_keys",
529+
// cache-level counters (shared by main and hot caches)
530+
"groupcache.cache.rejected",
531+
"groupcache.cache.gets",
532+
"groupcache.cache.hits",
533+
"groupcache.cache.evictions",
528534
}
529535
assert.Equal(t, expectedCounters, recMeter.counterNames)
530-
assert.Equal(t, []string{"groupcache.group.peer.latency_max_ms"}, recMeter.updownNames)
536+
assert.Equal(t, []string{
537+
"groupcache.group.peer.latency_max_ms",
538+
"groupcache.cache.bytes",
539+
"groupcache.cache.items",
540+
}, recMeter.updownNames)
531541
assert.True(t, recMeter.callbackRegistered)
532-
assert.Equal(t, 11, recMeter.instrumentCount)
542+
// 11 group instruments + 6 cache instruments per cache (main + hot) = 11 + 6 + 6 = 23
543+
assert.Equal(t, 23, recMeter.instrumentCount)
533544
}
534545

535546
func TestNewGroupFailsWhenMetricRegistrationFails(t *testing.T) {
@@ -579,7 +590,7 @@ func (m *recordingMeter) Int64ObservableUpDownCounter(name string, _ ...metric.I
579590

580591
func (m *recordingMeter) RegisterCallback(f metric.Callback, instruments ...metric.Observable) (metric.Registration, error) {
581592
m.callbackRegistered = true
582-
m.instrumentCount = len(instruments)
593+
m.instrumentCount += len(instruments)
583594
// Invoke the callback once to ensure it tolerates being called with nil ctx/observer
584595
_ = f(context.Background(), noop.Observer{})
585596
return noop.Registration{}, nil

stats.go

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -280,55 +280,55 @@ func (gm *groupInstruments) RemovedKeysCounter() metric.Int64ObservableCounter {
280280
}
281281

282282
type cacheInstruments struct {
283-
rejectedCounter metric.Int64Counter
284-
bytesGauge metric.Int64UpDownCounter
285-
itemsGauge metric.Int64UpDownCounter
286-
getsCounter metric.Int64Counter
287-
hitsCounter metric.Int64Counter
288-
evictionsCounter metric.Int64Counter
283+
rejectedCounter metric.Int64ObservableCounter
284+
bytesGauge metric.Int64ObservableUpDownCounter
285+
itemsGauge metric.Int64ObservableUpDownCounter
286+
getsCounter metric.Int64ObservableCounter
287+
hitsCounter metric.Int64ObservableCounter
288+
evictionsCounter metric.Int64ObservableCounter
289289
}
290290

291291
func newCacheInstruments(meter metric.Meter) (*cacheInstruments, error) {
292-
rejectedCounter, err := meter.Int64Counter("groupcache.cache.rejected",
292+
rejectedCounter, err := meter.Int64ObservableCounter("groupcache.cache.rejected",
293293
metric.WithDescription("Total number of items rejected from cache"),
294294
)
295295
if err != nil {
296296
return nil, err
297297
}
298298

299-
bytesGauge, err := meter.Int64UpDownCounter(
299+
bytesGauge, err := meter.Int64ObservableUpDownCounter(
300300
"groupcache.cache.bytes",
301301
metric.WithDescription("Number of bytes in cache"),
302302
)
303303
if err != nil {
304304
return nil, err
305305
}
306306

307-
itemsGauge, err := meter.Int64UpDownCounter(
307+
itemsGauge, err := meter.Int64ObservableUpDownCounter(
308308
"groupcache.cache.items",
309309
metric.WithDescription("Number of items in cache"),
310310
)
311311
if err != nil {
312312
return nil, err
313313
}
314314

315-
getsCounter, err := meter.Int64Counter(
315+
getsCounter, err := meter.Int64ObservableCounter(
316316
"groupcache.cache.gets",
317317
metric.WithDescription("Total get requests"),
318318
)
319319
if err != nil {
320320
return nil, err
321321
}
322322

323-
hitsCounter, err := meter.Int64Counter(
323+
hitsCounter, err := meter.Int64ObservableCounter(
324324
"groupcache.cache.hits",
325325
metric.WithDescription("Total successful cache hits"),
326326
)
327327
if err != nil {
328328
return nil, err
329329
}
330330

331-
evictionsCounter, err := meter.Int64Counter(
331+
evictionsCounter, err := meter.Int64ObservableCounter(
332332
"groupcache.cache.evictions",
333333
metric.WithDescription("Total number of evictions"),
334334
)
@@ -346,26 +346,26 @@ func newCacheInstruments(meter metric.Meter) (*cacheInstruments, error) {
346346
}, nil
347347
}
348348

349-
func (cm *cacheInstruments) RejectedCounter() metric.Int64Counter {
349+
func (cm *cacheInstruments) RejectedCounter() metric.Int64ObservableCounter {
350350
return cm.rejectedCounter
351351
}
352352

353-
func (cm *cacheInstruments) BytesGauge() metric.Int64UpDownCounter {
353+
func (cm *cacheInstruments) BytesGauge() metric.Int64ObservableUpDownCounter {
354354
return cm.bytesGauge
355355
}
356356

357-
func (cm *cacheInstruments) ItemsGauge() metric.Int64UpDownCounter {
357+
func (cm *cacheInstruments) ItemsGauge() metric.Int64ObservableUpDownCounter {
358358
return cm.itemsGauge
359359
}
360360

361-
func (cm *cacheInstruments) GetsCounter() metric.Int64Counter {
361+
func (cm *cacheInstruments) GetsCounter() metric.Int64ObservableCounter {
362362
return cm.getsCounter
363363
}
364364

365-
func (cm *cacheInstruments) HitsCounter() metric.Int64Counter {
365+
func (cm *cacheInstruments) HitsCounter() metric.Int64ObservableCounter {
366366
return cm.hitsCounter
367367
}
368368

369-
func (cm *cacheInstruments) EvictionsCounter() metric.Int64Counter {
369+
func (cm *cacheInstruments) EvictionsCounter() metric.Int64ObservableCounter {
370370
return cm.evictionsCounter
371371
}

stats_test.go

Lines changed: 3 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ func TestNewCacheInstrumentsErrorsOnCounterFailure(t *testing.T) {
112112
t.Parallel()
113113

114114
expectedErr := errors.New("counter fail")
115-
meter := &failingSyncMeter{counterErr: expectedErr}
115+
meter := &failingObservableMeter{counterErr: expectedErr}
116116

117117
inst, err := newCacheInstruments(meter)
118118
require.ErrorIs(t, err, expectedErr)
@@ -123,7 +123,7 @@ func TestNewCacheInstrumentsErrorsOnUpDownCounterFailure(t *testing.T) {
123123
t.Parallel()
124124

125125
expectedErr := errors.New("updown fail")
126-
meter := &failingSyncMeter{upDownErr: expectedErr}
126+
meter := &failingObservableMeter{upDownErr: expectedErr}
127127

128128
inst, err := newCacheInstruments(meter)
129129
require.ErrorIs(t, err, expectedErr)
@@ -150,7 +150,7 @@ func TestNewGroupPropagatesMetricRegistrationError(t *testing.T) {
150150
func TestNewCacheInstrumentsRegistersAllCounters(t *testing.T) {
151151
t.Parallel()
152152

153-
meter := &recordingSyncMeter{}
153+
meter := &recordingMeter{}
154154

155155
inst, err := newCacheInstruments(meter)
156156
require.NoError(t, err)
@@ -229,27 +229,6 @@ func (m *failingObservableMeter) Int64ObservableUpDownCounter(string, ...metric.
229229
return noop.Int64ObservableUpDownCounter{}, nil
230230
}
231231

232-
type failingSyncMeter struct {
233-
noop.Meter
234-
235-
counterErr error
236-
upDownErr error
237-
}
238-
239-
func (m *failingSyncMeter) Int64Counter(string, ...metric.Int64CounterOption) (metric.Int64Counter, error) {
240-
if m.counterErr != nil {
241-
return nil, m.counterErr
242-
}
243-
return noop.Int64Counter{}, nil
244-
}
245-
246-
func (m *failingSyncMeter) Int64UpDownCounter(string, ...metric.Int64UpDownCounterOption) (metric.Int64UpDownCounter, error) {
247-
if m.upDownErr != nil {
248-
return nil, m.upDownErr
249-
}
250-
return noop.Int64UpDownCounter{}, nil
251-
}
252-
253232
type staticMeterProvider struct {
254233
noop.MeterProvider
255234
meter metric.Meter
@@ -259,19 +238,3 @@ func (s *staticMeterProvider) Meter(string, ...metric.MeterOption) metric.Meter
259238
return s.meter
260239
}
261240

262-
type recordingSyncMeter struct {
263-
noop.Meter
264-
265-
counterNames []string
266-
updownNames []string
267-
}
268-
269-
func (m *recordingSyncMeter) Int64Counter(name string, _ ...metric.Int64CounterOption) (metric.Int64Counter, error) {
270-
m.counterNames = append(m.counterNames, name)
271-
return noop.Int64Counter{}, nil
272-
}
273-
274-
func (m *recordingSyncMeter) Int64UpDownCounter(name string, _ ...metric.Int64UpDownCounterOption) (metric.Int64UpDownCounter, error) {
275-
m.updownNames = append(m.updownNames, name)
276-
return noop.Int64UpDownCounter{}, nil
277-
}

0 commit comments

Comments
 (0)