Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 63 additions & 1 deletion group.go
Original file line number Diff line number Diff line change
Expand Up @@ -622,5 +622,67 @@ func (g *group) registerInstruments(meter otelmetric.Meter) error {
instruments.RemovedKeysCounter(),
)

return err
if err != nil {
return err
}

// Register cache-level instruments for mainCache and hotCache
if err := g.registerCacheInstruments(meter); err != nil {
return err
}

return nil
}

func (g *group) registerCacheInstruments(meter otelmetric.Meter) error {
cacheInstr, err := newCacheInstruments(meter)
if err != nil {
return err
}

type namedCache struct {
name string
cache func() Cache
}

caches := []namedCache{
{name: "main", cache: func() Cache { return g.mainCache }},
{name: "hot", cache: func() Cache { return g.hotCache }},
}

for _, nc := range caches {
observeOptions := []otelmetric.ObserveOption{
otelmetric.WithAttributes(
attribute.String("group.name", g.Name()),
attribute.String("cache.type", nc.name),
),
}

_, err := meter.RegisterCallback(func(ctx context.Context, o otelmetric.Observer) error {
c := nc.cache()
if c == nil {
return nil
}
stats := c.Stats()
o.ObserveInt64(cacheInstr.RejectedCounter(), stats.Rejected, observeOptions...)
o.ObserveInt64(cacheInstr.BytesGauge(), stats.Bytes, observeOptions...)
o.ObserveInt64(cacheInstr.ItemsGauge(), stats.Items, observeOptions...)
o.ObserveInt64(cacheInstr.GetsCounter(), stats.Gets, observeOptions...)
o.ObserveInt64(cacheInstr.HitsCounter(), stats.Hits, observeOptions...)
o.ObserveInt64(cacheInstr.EvictionsCounter(), stats.Evictions, observeOptions...)
return nil
},
cacheInstr.RejectedCounter(),
cacheInstr.BytesGauge(),
cacheInstr.ItemsGauge(),
cacheInstr.GetsCounter(),
cacheInstr.HitsCounter(),
cacheInstr.EvictionsCounter(),
)
if err != nil {
return err
}
}

return nil
}
17 changes: 14 additions & 3 deletions instance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,7 @@ func TestNewGroupRegistersMetricsWithMeterProvider(t *testing.T) {
require.NotNil(t, g)

expectedCounters := []string{
// group-level counters
"groupcache.group.gets",
"groupcache.group.cache_hits",
"groupcache.group.peer.loads",
Expand All @@ -525,11 +526,21 @@ func TestNewGroupRegistersMetricsWithMeterProvider(t *testing.T) {
"groupcache.group.local.load_errors",
"groupcache.group.remove_keys.requests",
"groupcache.group.removed_keys",
// cache-level counters (shared by main and hot caches)
"groupcache.cache.rejected",
"groupcache.cache.gets",
"groupcache.cache.hits",
"groupcache.cache.evictions",
}
assert.Equal(t, expectedCounters, recMeter.counterNames)
assert.Equal(t, []string{"groupcache.group.peer.latency_max_ms"}, recMeter.updownNames)
assert.Equal(t, []string{
"groupcache.group.peer.latency_max_ms",
"groupcache.cache.bytes",
"groupcache.cache.items",
}, recMeter.updownNames)
assert.True(t, recMeter.callbackRegistered)
assert.Equal(t, 11, recMeter.instrumentCount)
// 11 group instruments + 6 cache instruments per cache (main + hot) = 11 + 6 + 6 = 23
assert.Equal(t, 23, recMeter.instrumentCount)
}

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

func (m *recordingMeter) RegisterCallback(f metric.Callback, instruments ...metric.Observable) (metric.Registration, error) {
m.callbackRegistered = true
m.instrumentCount = len(instruments)
m.instrumentCount += len(instruments)
// Invoke the callback once to ensure it tolerates being called with nil ctx/observer
_ = f(context.Background(), noop.Observer{})
return noop.Registration{}, nil
Expand Down
36 changes: 18 additions & 18 deletions stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,55 +280,55 @@ func (gm *groupInstruments) RemovedKeysCounter() metric.Int64ObservableCounter {
}

type cacheInstruments struct {
rejectedCounter metric.Int64Counter
bytesGauge metric.Int64UpDownCounter
itemsGauge metric.Int64UpDownCounter
getsCounter metric.Int64Counter
hitsCounter metric.Int64Counter
evictionsCounter metric.Int64Counter
rejectedCounter metric.Int64ObservableCounter
bytesGauge metric.Int64ObservableUpDownCounter
itemsGauge metric.Int64ObservableUpDownCounter
getsCounter metric.Int64ObservableCounter
hitsCounter metric.Int64ObservableCounter
evictionsCounter metric.Int64ObservableCounter
}

func newCacheInstruments(meter metric.Meter) (*cacheInstruments, error) {
rejectedCounter, err := meter.Int64Counter("groupcache.cache.rejected",
rejectedCounter, err := meter.Int64ObservableCounter("groupcache.cache.rejected",
metric.WithDescription("Total number of items rejected from cache"),
)
if err != nil {
return nil, err
}

bytesGauge, err := meter.Int64UpDownCounter(
bytesGauge, err := meter.Int64ObservableUpDownCounter(
"groupcache.cache.bytes",
metric.WithDescription("Number of bytes in cache"),
)
if err != nil {
return nil, err
}

itemsGauge, err := meter.Int64UpDownCounter(
itemsGauge, err := meter.Int64ObservableUpDownCounter(
"groupcache.cache.items",
metric.WithDescription("Number of items in cache"),
)
if err != nil {
return nil, err
}

getsCounter, err := meter.Int64Counter(
getsCounter, err := meter.Int64ObservableCounter(
"groupcache.cache.gets",
metric.WithDescription("Total get requests"),
)
if err != nil {
return nil, err
}

hitsCounter, err := meter.Int64Counter(
hitsCounter, err := meter.Int64ObservableCounter(
"groupcache.cache.hits",
metric.WithDescription("Total successful cache hits"),
)
if err != nil {
return nil, err
}

evictionsCounter, err := meter.Int64Counter(
evictionsCounter, err := meter.Int64ObservableCounter(
"groupcache.cache.evictions",
metric.WithDescription("Total number of evictions"),
)
Expand All @@ -346,26 +346,26 @@ func newCacheInstruments(meter metric.Meter) (*cacheInstruments, error) {
}, nil
}

func (cm *cacheInstruments) RejectedCounter() metric.Int64Counter {
func (cm *cacheInstruments) RejectedCounter() metric.Int64ObservableCounter {
return cm.rejectedCounter
}

func (cm *cacheInstruments) BytesGauge() metric.Int64UpDownCounter {
func (cm *cacheInstruments) BytesGauge() metric.Int64ObservableUpDownCounter {
return cm.bytesGauge
}

func (cm *cacheInstruments) ItemsGauge() metric.Int64UpDownCounter {
func (cm *cacheInstruments) ItemsGauge() metric.Int64ObservableUpDownCounter {
return cm.itemsGauge
}

func (cm *cacheInstruments) GetsCounter() metric.Int64Counter {
func (cm *cacheInstruments) GetsCounter() metric.Int64ObservableCounter {
return cm.getsCounter
}

func (cm *cacheInstruments) HitsCounter() metric.Int64Counter {
func (cm *cacheInstruments) HitsCounter() metric.Int64ObservableCounter {
return cm.hitsCounter
}

func (cm *cacheInstruments) EvictionsCounter() metric.Int64Counter {
func (cm *cacheInstruments) EvictionsCounter() metric.Int64ObservableCounter {
return cm.evictionsCounter
}
43 changes: 3 additions & 40 deletions stats_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ func TestNewCacheInstrumentsErrorsOnCounterFailure(t *testing.T) {
t.Parallel()

expectedErr := errors.New("counter fail")
meter := &failingSyncMeter{counterErr: expectedErr}
meter := &failingObservableMeter{counterErr: expectedErr}

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

expectedErr := errors.New("updown fail")
meter := &failingSyncMeter{upDownErr: expectedErr}
meter := &failingObservableMeter{upDownErr: expectedErr}

inst, err := newCacheInstruments(meter)
require.ErrorIs(t, err, expectedErr)
Expand All @@ -150,7 +150,7 @@ func TestNewGroupPropagatesMetricRegistrationError(t *testing.T) {
func TestNewCacheInstrumentsRegistersAllCounters(t *testing.T) {
t.Parallel()

meter := &recordingSyncMeter{}
meter := &recordingMeter{}

inst, err := newCacheInstruments(meter)
require.NoError(t, err)
Expand Down Expand Up @@ -229,27 +229,6 @@ func (m *failingObservableMeter) Int64ObservableUpDownCounter(string, ...metric.
return noop.Int64ObservableUpDownCounter{}, nil
}

type failingSyncMeter struct {
noop.Meter

counterErr error
upDownErr error
}

func (m *failingSyncMeter) Int64Counter(string, ...metric.Int64CounterOption) (metric.Int64Counter, error) {
if m.counterErr != nil {
return nil, m.counterErr
}
return noop.Int64Counter{}, nil
}

func (m *failingSyncMeter) Int64UpDownCounter(string, ...metric.Int64UpDownCounterOption) (metric.Int64UpDownCounter, error) {
if m.upDownErr != nil {
return nil, m.upDownErr
}
return noop.Int64UpDownCounter{}, nil
}

type staticMeterProvider struct {
noop.MeterProvider
meter metric.Meter
Expand All @@ -259,19 +238,3 @@ func (s *staticMeterProvider) Meter(string, ...metric.MeterOption) metric.Meter
return s.meter
}

type recordingSyncMeter struct {
noop.Meter

counterNames []string
updownNames []string
}

func (m *recordingSyncMeter) Int64Counter(name string, _ ...metric.Int64CounterOption) (metric.Int64Counter, error) {
m.counterNames = append(m.counterNames, name)
return noop.Int64Counter{}, nil
}

func (m *recordingSyncMeter) Int64UpDownCounter(name string, _ ...metric.Int64UpDownCounterOption) (metric.Int64UpDownCounter, error) {
m.updownNames = append(m.updownNames, name)
return noop.Int64UpDownCounter{}, nil
}
Loading