Skip to content

feat: add instrumented go-cache wrapper with Prometheus metrics - #214

Closed
DerekFrank wants to merge 1 commit into
awslabs:mainfrom
DerekFrank:go-cache-metrics
Closed

feat: add instrumented go-cache wrapper with Prometheus metrics#214
DerekFrank wants to merge 1 commit into
awslabs:mainfrom
DerekFrank:go-cache-metrics

Conversation

@DerekFrank

Copy link
Copy Markdown
Contributor

Add operatorpkg/cache, a near drop-in wrapper around patrickmn/go-cache that emits Prometheus metrics under the operator_cache_* subsystem:

  • gets_total{name,result=hit|miss}
  • adds_total{name,result=added|exists} (exists = suppressed duplicate)
  • evictions_total{name} (TTL expiry)
  • deletes_total{name,type=explicit|flush}
  • flushes_total{name}
  • flush_size{name} (histogram, entries per flush)
  • entries{name} (gauge)

The wrapper embeds *cache.Cache so every underlying method still works; only Get/Set/SetDefault/Add/Delete/Flush are overridden. Counter/gauge series are pre-initialized to 0 to avoid sparse series. The entries gauge is updated on mutation (never at scrape time) so scrapes do no cache work. A caller-supplied OnEvicted callback is chained, not replaced.

Issue #, if available:

Description of changes:

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Add operatorpkg/cache, a near drop-in wrapper around patrickmn/go-cache
that emits Prometheus metrics under the operator_cache_* subsystem:

- gets_total{name,result=hit|miss}
- adds_total{name,result=added|exists}  (exists = suppressed duplicate)
- evictions_total{name}                 (TTL expiry)
- deletes_total{name,type=explicit|flush}
- flushes_total{name}
- flush_size{name}                       (histogram, entries per flush)
- entries{name}                          (gauge)

The wrapper embeds *cache.Cache so every underlying method still works;
only Get/Set/SetDefault/Add/Delete/Flush are overridden. Counter/gauge
series are pre-initialized to 0 to avoid sparse series. The entries gauge
is updated on mutation (never at scrape time) so scrapes do no cache work.
A caller-supplied OnEvicted callback is chained, not replaced.
@DerekFrank
DerekFrank requested a review from a team as a code owner August 5, 2026 21:25
Comment thread cache/cache.go
// Get records a hit or miss and delegates to the underlying cache.
func (c *Cache) Get(k string) (interface{}, bool) {
v, ok := c.Cache.Get(k)
if ok {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Theres a pretty small perf hit here because theres a bunch of allocations + the metric itself - it tripled the CPU usage on every cache.Get()

I don't think its that large, but since there is limited value in the metric it might not be worth it

Test Scenario: 9 NodeClasses, 9 NodePools, 0 pods

Image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea I think we can drop it

@DerekFrank DerekFrank closed this Aug 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants