-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
616 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package cache | ||
|
||
// WithMetrics is a decorator that adds metrics collection to any Cache implementation. | ||
type WithMetrics[T any] struct { | ||
wrapped Cache[T] | ||
metrics BaseMetricsCollector | ||
cacheName string | ||
} | ||
|
||
// NewCacheWithMetrics creates a new WithMetrics decorator that wraps the provided Cache | ||
// and collects metrics using the provided BaseMetricsCollector. | ||
// The cacheName parameter is used to identify the cache in the collected metrics. | ||
func NewCacheWithMetrics[T any](wrapped Cache[T], metrics BaseMetricsCollector, cacheName string) *WithMetrics[T] { | ||
return &WithMetrics[T]{ | ||
wrapped: wrapped, | ||
metrics: metrics, | ||
cacheName: cacheName, | ||
} | ||
} | ||
|
||
// Set sets the value for the given key in the cache. It also records a set metric | ||
// for the cache using the provided metrics collector and cache name. | ||
func (c *WithMetrics[T]) Set(key string, val T) { | ||
c.metrics.RecordSet(c.cacheName) | ||
c.wrapped.Set(key, val) | ||
} | ||
|
||
// Get retrieves the value for the given key from the underlying cache. It also records | ||
// a hit or miss metric for the cache using the provided metrics collector and cache name. | ||
func (c *WithMetrics[T]) Get(key string) (T, bool) { | ||
val, found := c.wrapped.Get(key) | ||
if found { | ||
c.metrics.RecordHit(c.cacheName) | ||
} else { | ||
c.metrics.RecordMiss(c.cacheName) | ||
} | ||
return val, found | ||
} | ||
|
||
// Exists checks if the given key exists in the cache. It records a hit or miss metric | ||
// for the cache using the provided metrics collector and cache name. | ||
func (c *WithMetrics[T]) Exists(key string) bool { | ||
found := c.wrapped.Exists(key) | ||
if found { | ||
c.metrics.RecordHit(c.cacheName) | ||
} else { | ||
c.metrics.RecordMiss(c.cacheName) | ||
} | ||
return found | ||
} | ||
|
||
// Delete removes the value for the given key from the cache. It also records a delete metric | ||
// for the cache using the provided metrics collector and cache name. | ||
func (c *WithMetrics[T]) Delete(key string) { | ||
c.wrapped.Delete(key) | ||
c.metrics.RecordDelete(c.cacheName) | ||
} | ||
|
||
// Clear removes all entries from the cache. It also records a clear metric | ||
// for the cache using the provided metrics collector and cache name. | ||
func (c *WithMetrics[T]) Clear() { | ||
c.wrapped.Clear() | ||
c.metrics.RecordClear(c.cacheName) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
package cache | ||
|
||
import ( | ||
"sync" | ||
|
||
"github.com/prometheus/client_golang/prometheus" | ||
"github.com/prometheus/client_golang/prometheus/promauto" | ||
) | ||
|
||
// BaseMetricsCollector defines the interface for recording cache metrics. | ||
// Each method corresponds to a specific cache-related operation. | ||
type BaseMetricsCollector interface { | ||
RecordHit(cacheName string) | ||
RecordMiss(cacheName string) | ||
RecordSet(cacheName string) | ||
RecordDelete(cacheName string) | ||
RecordClear(cacheName string) | ||
} | ||
|
||
// MetricsCollector encapsulates all Prometheus metrics with labels. | ||
// It holds Prometheus counters for cache operations, which help track | ||
// the performance and usage of the cache. | ||
type MetricsCollector struct { | ||
// Base metrics. | ||
hits *prometheus.CounterVec | ||
misses *prometheus.CounterVec | ||
sets *prometheus.CounterVec | ||
deletes *prometheus.CounterVec | ||
clears *prometheus.CounterVec | ||
} | ||
|
||
var ( | ||
collectorOnce sync.Once // Ensures that the collector is initialized only once. | ||
collector *MetricsCollector | ||
) | ||
|
||
// InitializeMetrics initializes the singleton MetricsCollector. | ||
// It sets up Prometheus counters for cache operations (hits, misses, sets, deletes, clears). | ||
// Should be called once at the start of the application. | ||
func InitializeMetrics(namespace, subsystem string) { | ||
collectorOnce.Do(func() { | ||
collector = &MetricsCollector{ | ||
hits: promauto.NewCounterVec(prometheus.CounterOpts{ | ||
Namespace: namespace, | ||
Subsystem: subsystem, | ||
Name: "hits_total", | ||
Help: "Total number of cache hits.", | ||
}, []string{"cache_name"}), | ||
|
||
misses: promauto.NewCounterVec(prometheus.CounterOpts{ | ||
Namespace: namespace, | ||
Subsystem: subsystem, | ||
Name: "misses_total", | ||
Help: "Total number of cache misses.", | ||
}, []string{"cache_name"}), | ||
|
||
sets: promauto.NewCounterVec(prometheus.CounterOpts{ | ||
Namespace: namespace, | ||
Subsystem: subsystem, | ||
Name: "sets_total", | ||
Help: "Total number of cache set operations.", | ||
}, []string{"cache_name"}), | ||
|
||
deletes: promauto.NewCounterVec(prometheus.CounterOpts{ | ||
Namespace: namespace, | ||
Subsystem: subsystem, | ||
Name: "deletes_total", | ||
Help: "Total number of cache delete operations.", | ||
}, []string{"cache_name"}), | ||
|
||
clears: promauto.NewCounterVec(prometheus.CounterOpts{ | ||
Namespace: namespace, | ||
Subsystem: subsystem, | ||
Name: "clears_total", | ||
Help: "Total number of cache clear operations.", | ||
}, []string{"cache_name"}), | ||
} | ||
}) | ||
} | ||
|
||
// GetMetricsCollector returns the singleton MetricsCollector instance. | ||
// It panics if InitializeMetrics has not been called to ensure metrics are properly initialized. | ||
// Must be called after InitializeMetrics to avoid runtime issues. | ||
// If you do it before, BAD THINGS WILL HAPPEN. | ||
func GetMetricsCollector() *MetricsCollector { | ||
if collector == nil { | ||
panic("MetricsCollector not initialized. Call InitializeMetrics first.") | ||
} | ||
return collector | ||
} | ||
|
||
// Implement BaseMetricsCollector interface methods. | ||
|
||
// RecordHit increments the counter for cache hits, tracking how often cache lookups succeed. | ||
func (m *MetricsCollector) RecordHit(cacheName string) { m.hits.WithLabelValues(cacheName).Inc() } | ||
|
||
// RecordMiss increments the counter for cache misses, tracking how often cache lookups fail. | ||
func (m *MetricsCollector) RecordMiss(cacheName string) { m.misses.WithLabelValues(cacheName).Inc() } | ||
|
||
// RecordSet increments the counter for cache set operations, tracking how often items are added/updated. | ||
func (m *MetricsCollector) RecordSet(cacheName string) { m.sets.WithLabelValues(cacheName).Inc() } | ||
|
||
// RecordDelete increments the counter for cache delete operations, tracking how often items are removed. | ||
func (m *MetricsCollector) RecordDelete(cacheName string) { m.deletes.WithLabelValues(cacheName).Inc() } | ||
|
||
// RecordClear increments the counter for cache clear operations, tracking how often the cache is completely cleared. | ||
func (m *MetricsCollector) RecordClear(cacheName string) { m.clears.WithLabelValues(cacheName).Inc() } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package sizedlru | ||
|
||
import ( | ||
"github.com/prometheus/client_golang/prometheus" | ||
|
||
"github.com/trufflesecurity/trufflehog/v3/pkg/cache" | ||
) | ||
|
||
// MetricsCollector should implement the collector interface. | ||
var _ collector = (*MetricsCollector)(nil) | ||
|
||
// MetricsCollector extends the BaseMetricsCollector with Sized LRU specific metrics. | ||
// It provides methods to record cache hits, misses, and evictions. | ||
type MetricsCollector struct { | ||
// BaseMetricsCollector is embedded to provide the base metrics functionality. | ||
cache.BaseMetricsCollector | ||
|
||
totalHits *prometheus.GaugeVec | ||
totalMisses *prometheus.GaugeVec | ||
totalEvicts *prometheus.GaugeVec | ||
} | ||
|
||
// NewSizedLRUMetricsCollector initializes a new MetricsCollector with the provided namespace and subsystem. | ||
func NewSizedLRUMetricsCollector(namespace, subsystem string) *MetricsCollector { | ||
base := cache.GetMetricsCollector() | ||
|
||
totalHits := prometheus.NewGaugeVec(prometheus.GaugeOpts{ | ||
Namespace: namespace, | ||
Subsystem: subsystem, | ||
Name: "total_hits", | ||
Help: "Total number of cache hits.", | ||
}, []string{"cache_name"}) | ||
|
||
totalMisses := prometheus.NewGaugeVec(prometheus.GaugeOpts{ | ||
Namespace: namespace, | ||
Subsystem: subsystem, | ||
Name: "total_misses", | ||
Help: "Total number of cache misses.", | ||
}, []string{"cache_name"}) | ||
|
||
totalEvicts := prometheus.NewGaugeVec(prometheus.GaugeOpts{ | ||
Namespace: namespace, | ||
Subsystem: subsystem, | ||
Name: "total_evicts", | ||
Help: "Total number of cache evictions.", | ||
}, []string{"cache_name"}) | ||
|
||
return &MetricsCollector{ | ||
BaseMetricsCollector: base, | ||
totalHits: totalHits, | ||
totalMisses: totalMisses, | ||
totalEvicts: totalEvicts, | ||
} | ||
} | ||
|
||
// RecordHits updates the total hits metric for the given cache name. | ||
func (c *MetricsCollector) RecordHits(cacheName string, hits uint64) { | ||
c.totalHits.WithLabelValues(cacheName).Set(float64(hits)) | ||
} | ||
|
||
// RecordMisses updates the total misses metric for the given cache name. | ||
func (c *MetricsCollector) RecordMisses(cacheName string, misses uint64) { | ||
c.totalMisses.WithLabelValues(cacheName).Set(float64(misses)) | ||
} | ||
|
||
// RecordEvictions updates the total evictions metric for the given cache name. | ||
func (c *MetricsCollector) RecordEvictions(cacheName string, evictions uint64) { | ||
c.totalEvicts.WithLabelValues(cacheName).Set(float64(evictions)) | ||
} |
Oops, something went wrong.