From 51e6206aef1e8db001f0df40980930fa35197d45 Mon Sep 17 00:00:00 2001 From: Ahrav Dutta Date: Fri, 27 Sep 2024 12:18:41 -0700 Subject: [PATCH 1/5] add impl for lru sized cache --- pkg/cache/decorator.go | 64 +++++++++++ pkg/cache/metrics.go | 107 ++++++++++++++++++ pkg/cache/sizedlru/metrics.go | 41 +++++++ pkg/cache/sizedlru/sizedlru.go | 120 ++++++++++++++++++++ pkg/cache/sizedlru/sizedlru_test.go | 166 ++++++++++++++++++++++++++++ 5 files changed, 498 insertions(+) create mode 100644 pkg/cache/decorator.go create mode 100644 pkg/cache/metrics.go create mode 100644 pkg/cache/sizedlru/metrics.go create mode 100644 pkg/cache/sizedlru/sizedlru.go create mode 100644 pkg/cache/sizedlru/sizedlru_test.go diff --git a/pkg/cache/decorator.go b/pkg/cache/decorator.go new file mode 100644 index 000000000000..5740dec7eb0b --- /dev/null +++ b/pkg/cache/decorator.go @@ -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) +} diff --git a/pkg/cache/metrics.go b/pkg/cache/metrics.go new file mode 100644 index 000000000000..7ea11f4c740c --- /dev/null +++ b/pkg/cache/metrics.go @@ -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() } diff --git a/pkg/cache/sizedlru/metrics.go b/pkg/cache/sizedlru/metrics.go new file mode 100644 index 000000000000..b71d1bd5204f --- /dev/null +++ b/pkg/cache/sizedlru/metrics.go @@ -0,0 +1,41 @@ +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 + + totalEvicts *prometheus.CounterVec +} + +// NewSizedLRUMetricsCollector initializes a new MetricsCollector with the provided namespace and subsystem. +func NewSizedLRUMetricsCollector(namespace, subsystem string) *MetricsCollector { + base := cache.GetMetricsCollector() + + totalEvicts := prometheus.NewCounterVec(prometheus.CounterOpts{ + Namespace: namespace, + Subsystem: subsystem, + Name: "evictions_total", + Help: "Total number of cache evictions.", + }, []string{"cache_name"}) + + return &MetricsCollector{ + BaseMetricsCollector: base, + totalEvicts: totalEvicts, + } +} + +// RecordEviction increments the total number of cache evictions for the specified cache. +func (c *MetricsCollector) RecordEviction(cacheName string) { + c.totalEvicts.WithLabelValues(cacheName).Inc() +} diff --git a/pkg/cache/sizedlru/sizedlru.go b/pkg/cache/sizedlru/sizedlru.go new file mode 100644 index 000000000000..fea0ff6b4478 --- /dev/null +++ b/pkg/cache/sizedlru/sizedlru.go @@ -0,0 +1,120 @@ +// Package sizedlru provides a generic, size-limited, LRU (Least Recently Used) cache with optional +// metrics collection and reporting. It wraps the golang-lru/v2 caching library, adding support for custom +// metrics tracking cache hits, misses, evictions, and other cache operations. +// +// This package supports configuring key aspects of cache behavior, including maximum cache size, +// and custom metrics collection. +package sizedlru + +import ( + "fmt" + + lru "github.com/hashicorp/golang-lru/v2" + + "github.com/trufflesecurity/trufflehog/v3/pkg/cache" + "github.com/trufflesecurity/trufflehog/v3/pkg/common" +) + +// collector is an interface that extends cache.BaseMetricsCollector +// and adds methods for recording cache hits, misses, and evictions. +type collector interface { + cache.BaseMetricsCollector + + RecordEviction(cacheName string) +} + +// Cache is a generic LRU-sized cache that stores key-value pairs with a maximum size limit. +// It wraps the lru.Cache library and adds support for custom metrics collection. +type Cache[T any] struct { + cache *lru.Cache[string, T] + + cacheName string + capacity int + metrics collector +} + +// Option defines a functional option for configuring the Cache. +type Option[T any] func(*Cache[T]) + +// WithMetricsCollector is a functional option to set a custom metrics collector. +// It sets the metrics field of the Cache. +func WithMetricsCollector[T any](collector collector) Option[T] { + return func(lc *Cache[T]) { lc.metrics = collector } +} + +// WithCapacity is a functional option to set the maximum capacity of the cache. +// If the capacity is not set, the default value (512MB) is used. +func WithCapacity[T any](capacity int) Option[T] { + return func(lc *Cache[T]) { lc.capacity = capacity } +} + +// NewCache creates a new Cache with optional configuration parameters. +// It takes a cache name and a variadic list of options. +func NewCache[T any](cacheName string, opts ...Option[T]) (*Cache[T], error) { + // Default values for cache configuration. + const defaultSize = 1 << 29 // 512MB + + sizedLRU := &Cache[T]{ + metrics: NewSizedLRUMetricsCollector(common.MetricsNamespace, common.MetricsSubsystem), + cacheName: cacheName, + } + + for _, opt := range opts { + opt(sizedLRU) + } + + // Provide a evict callback function to record evictions. + onEvicted := func(string, T) { + sizedLRU.metrics.RecordEviction(sizedLRU.cacheName) + } + + lcache, err := lru.NewWithEvict[string, T](defaultSize, onEvicted) + if err != nil { + return nil, fmt.Errorf("failed to create Ristretto cache: %w", err) + } + + sizedLRU.cache = lcache + + return sizedLRU, nil +} + +// Set adds a key-value pair to the cache. +func (lc *Cache[T]) Set(key string, val T) { + lc.cache.Add(key, val) + lc.metrics.RecordSet(lc.cacheName) +} + +// Get retrieves a value from the cache by key. +func (lc *Cache[T]) Get(key string) (T, bool) { + value, found := lc.cache.Get(key) + if found { + lc.metrics.RecordHit(lc.cacheName) + return value, true + } + lc.metrics.RecordMiss(lc.cacheName) + var zero T + return zero, false +} + +// Exists checks if a key exists in the cache. +func (lc *Cache[T]) Exists(key string) bool { + _, found := lc.cache.Get(key) + if found { + lc.metrics.RecordHit(lc.cacheName) + } else { + lc.metrics.RecordMiss(lc.cacheName) + } + return found +} + +// Delete removes a key from the cache. +func (lc *Cache[T]) Delete(key string) { + lc.cache.Remove(key) + lc.metrics.RecordDelete(lc.cacheName) +} + +// Clear removes all keys from the cache. +func (lc *Cache[T]) Clear() { + lc.cache.Purge() + lc.metrics.RecordClear(lc.cacheName) +} diff --git a/pkg/cache/sizedlru/sizedlru_test.go b/pkg/cache/sizedlru/sizedlru_test.go new file mode 100644 index 000000000000..222d94a63870 --- /dev/null +++ b/pkg/cache/sizedlru/sizedlru_test.go @@ -0,0 +1,166 @@ +package sizedlru + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + + "github.com/trufflesecurity/trufflehog/v3/pkg/cache" + "github.com/trufflesecurity/trufflehog/v3/pkg/common" +) + +type mockCollector struct{ mock.Mock } + +func (m *mockCollector) RecordHits(cacheName string, hits uint64) { m.Called(cacheName, hits) } + +func (m *mockCollector) RecordMisses(cacheName string, misses uint64) { m.Called(cacheName, misses) } + +func (m *mockCollector) RecordEviction(cacheName string) { m.Called(cacheName) } + +func (m *mockCollector) RecordSet(cacheName string) { m.Called(cacheName) } + +func (m *mockCollector) RecordHit(cacheName string) { m.Called(cacheName) } + +func (m *mockCollector) RecordMiss(cacheName string) { m.Called(cacheName) } + +func (m *mockCollector) RecordDelete(cacheName string) { m.Called(cacheName) } + +func (m *mockCollector) RecordClear(cacheName string) { m.Called(cacheName) } + +// setupCache initializes the metrics and cache. +// If withCollector is true, it sets up a cache with a custom metrics collector. +// Otherwise, it sets up a cache without a custom metrics collector. +func setupCache[T any](t *testing.T, withCollector bool) (*Cache[T], *mockCollector) { + t.Helper() + + // Call InitializeMetrics first. + cache.InitializeMetrics(common.MetricsNamespace, common.MetricsSubsystem) + + var collector *mockCollector + var c *Cache[T] + var err error + + if withCollector { + collector = new(mockCollector) + c, err = NewCache[T]("test_cache", WithMetricsCollector[T](collector)) + } else { + c, err = NewCache[T]("test_cache") + } + + assert.NoError(t, err, "Failed to create cache") + assert.NotNil(t, c, "Cache should not be nil") + + return c, collector +} + +func TestNewLRUCache(t *testing.T) { + t.Run("default configuration", func(t *testing.T) { + c, _ := setupCache[int](t, false) + assert.Equal(t, "test_cache", c.cacheName) + assert.NotNil(t, c.metrics, "Cache metrics should not be nil") + }) + + t.Run("with custom max cost", func(t *testing.T) { + c, _ := setupCache[int](t, false) + assert.NotNil(t, c) + }) + + t.Run("with metrics collector", func(t *testing.T) { + c, collector := setupCache[int](t, true) + assert.NotNil(t, c) + assert.Equal(t, "test_cache", c.cacheName) + assert.Equal(t, collector, c.metrics, "Cache metrics should match the collector") + }) +} + +func TestCacheSet(t *testing.T) { + c, collector := setupCache[string](t, true) + + collector.On("RecordSet", "test_cache").Once() + c.Set("key", "value") + + collector.AssertCalled(t, "RecordSet", "test_cache") +} + +func TestCacheGet(t *testing.T) { + c, collector := setupCache[string](t, true) + + collector.On("RecordSet", "test_cache").Once() + collector.On("RecordHit", "test_cache").Once() + collector.On("RecordMiss", "test_cache").Once() + + c.Set("key", "value") + collector.AssertCalled(t, "RecordSet", "test_cache") + + value, found := c.Get("key") + assert.True(t, found, "Expected to find the key") + assert.Equal(t, "value", value, "Expected value to match") + collector.AssertCalled(t, "RecordHit", "test_cache") + + _, found = c.Get("non_existent") + assert.False(t, found, "Expected not to find the key") + collector.AssertCalled(t, "RecordMiss", "test_cache") +} + +func TestCacheExists(t *testing.T) { + c, collector := setupCache[string](t, true) + + collector.On("RecordSet", "test_cache").Once() + collector.On("RecordHit", "test_cache").Twice() + collector.On("RecordMiss", "test_cache").Once() + + c.Set("key", "value") + collector.AssertCalled(t, "RecordSet", "test_cache") + + exists := c.Exists("key") + assert.True(t, exists, "Expected the key to exist") + collector.AssertCalled(t, "RecordHit", "test_cache") + + exists = c.Exists("non_existent") + assert.False(t, exists, "Expected the key not to exist") + collector.AssertCalled(t, "RecordMiss", "test_cache") +} + +func TestCacheDelete(t *testing.T) { + c, collector := setupCache[string](t, true) + + collector.On("RecordSet", "test_cache").Once() + collector.On("RecordDelete", "test_cache").Once() + collector.On("RecordMiss", "test_cache").Once() + collector.On("RecordEviction", "test_cache").Once() + + c.Set("key", "value") + collector.AssertCalled(t, "RecordSet", "test_cache") + + c.Delete("key") + collector.AssertCalled(t, "RecordDelete", "test_cache") + collector.AssertCalled(t, "RecordEviction", "test_cache") + + _, found := c.Get("key") + assert.False(t, found, "Expected not to find the deleted key") + collector.AssertCalled(t, "RecordMiss", "test_cache") +} + +func TestCacheClear(t *testing.T) { + c, collector := setupCache[string](t, true) + + collector.On("RecordSet", "test_cache").Twice() + collector.On("RecordClear", "test_cache").Once() + collector.On("RecordMiss", "test_cache").Twice() + collector.On("RecordEviction", "test_cache").Twice() + + c.Set("key1", "value1") + c.Set("key2", "value2") + collector.AssertNumberOfCalls(t, "RecordSet", 2) + + c.Clear() + collector.AssertCalled(t, "RecordClear", "test_cache") + collector.AssertNumberOfCalls(t, "RecordEviction", 2) + + _, found1 := c.Get("key1") + _, found2 := c.Get("key2") + assert.False(t, found1, "Expected not to find key1 after clear") + assert.False(t, found2, "Expected not to find key2 after clear") + collector.AssertNumberOfCalls(t, "RecordMiss", 2) +} From 1db317deeddfb221c79b0472257a0f9b5085e334 Mon Sep 17 00:00:00 2001 From: Ahrav Dutta Date: Mon, 30 Sep 2024 12:21:21 -0700 Subject: [PATCH 2/5] update error message --- pkg/cache/sizedlru/sizedlru.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cache/sizedlru/sizedlru.go b/pkg/cache/sizedlru/sizedlru.go index fea0ff6b4478..dbdecdb5e207 100644 --- a/pkg/cache/sizedlru/sizedlru.go +++ b/pkg/cache/sizedlru/sizedlru.go @@ -70,7 +70,7 @@ func NewCache[T any](cacheName string, opts ...Option[T]) (*Cache[T], error) { lcache, err := lru.NewWithEvict[string, T](defaultSize, onEvicted) if err != nil { - return nil, fmt.Errorf("failed to create Ristretto cache: %w", err) + return nil, fmt.Errorf("failed to create lrusized cache: %w", err) } sizedLRU.cache = lcache From 78c1fef6de6466df91a1b7bc7b9a236cd6c1ab16 Mon Sep 17 00:00:00 2001 From: Ahrav Dutta Date: Mon, 30 Sep 2024 12:35:10 -0700 Subject: [PATCH 3/5] address comments --- pkg/cache/metrics.go | 39 +++++++++++++++-------------- pkg/cache/sizedlru/sizedlru.go | 6 ++--- pkg/cache/sizedlru/sizedlru_test.go | 6 ----- 3 files changed, 23 insertions(+), 28 deletions(-) diff --git a/pkg/cache/metrics.go b/pkg/cache/metrics.go index 7ea11f4c740c..36a6ba86730e 100644 --- a/pkg/cache/metrics.go +++ b/pkg/cache/metrics.go @@ -5,6 +5,8 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" + + "github.com/trufflesecurity/trufflehog/v3/pkg/common" ) // BaseMetricsCollector defines the interface for recording cache metrics. @@ -29,48 +31,42 @@ type MetricsCollector struct { 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) { +func init() { + // Initialize the singleton MetricsCollector. + // Set up Prometheus counters for cache operations (hits, misses, sets, deletes, clears). collectorOnce.Do(func() { collector = &MetricsCollector{ hits: promauto.NewCounterVec(prometheus.CounterOpts{ - Namespace: namespace, - Subsystem: subsystem, + Namespace: common.MetricsNamespace, + Subsystem: common.MetricsSubsystem, Name: "hits_total", Help: "Total number of cache hits.", }, []string{"cache_name"}), misses: promauto.NewCounterVec(prometheus.CounterOpts{ - Namespace: namespace, - Subsystem: subsystem, + Namespace: common.MetricsNamespace, + Subsystem: common.MetricsSubsystem, Name: "misses_total", Help: "Total number of cache misses.", }, []string{"cache_name"}), sets: promauto.NewCounterVec(prometheus.CounterOpts{ - Namespace: namespace, - Subsystem: subsystem, + Namespace: common.MetricsNamespace, + Subsystem: common.MetricsSubsystem, Name: "sets_total", Help: "Total number of cache set operations.", }, []string{"cache_name"}), deletes: promauto.NewCounterVec(prometheus.CounterOpts{ - Namespace: namespace, - Subsystem: subsystem, + Namespace: common.MetricsNamespace, + Subsystem: common.MetricsSubsystem, Name: "deletes_total", Help: "Total number of cache delete operations.", }, []string{"cache_name"}), clears: promauto.NewCounterVec(prometheus.CounterOpts{ - Namespace: namespace, - Subsystem: subsystem, + Namespace: common.MetricsNamespace, + Subsystem: common.MetricsSubsystem, Name: "clears_total", Help: "Total number of cache clear operations.", }, []string{"cache_name"}), @@ -78,6 +74,11 @@ func InitializeMetrics(namespace, subsystem string) { }) } +var ( + collectorOnce sync.Once // Ensures that the collector is initialized only once. + collector *MetricsCollector +) + // 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. diff --git a/pkg/cache/sizedlru/sizedlru.go b/pkg/cache/sizedlru/sizedlru.go index dbdecdb5e207..1c710b1722c6 100644 --- a/pkg/cache/sizedlru/sizedlru.go +++ b/pkg/cache/sizedlru/sizedlru.go @@ -42,8 +42,8 @@ func WithMetricsCollector[T any](collector collector) Option[T] { return func(lc *Cache[T]) { lc.metrics = collector } } -// WithCapacity is a functional option to set the maximum capacity of the cache. -// If the capacity is not set, the default value (512MB) is used. +// WithCapacity is a functional option to set the maximum number of items the cache can hold. +// If the capacity is not set, the default value (128_000) is used. func WithCapacity[T any](capacity int) Option[T] { return func(lc *Cache[T]) { lc.capacity = capacity } } @@ -52,7 +52,7 @@ func WithCapacity[T any](capacity int) Option[T] { // It takes a cache name and a variadic list of options. func NewCache[T any](cacheName string, opts ...Option[T]) (*Cache[T], error) { // Default values for cache configuration. - const defaultSize = 1 << 29 // 512MB + const defaultSize = 128_000 sizedLRU := &Cache[T]{ metrics: NewSizedLRUMetricsCollector(common.MetricsNamespace, common.MetricsSubsystem), diff --git a/pkg/cache/sizedlru/sizedlru_test.go b/pkg/cache/sizedlru/sizedlru_test.go index 222d94a63870..6f110b6a31e0 100644 --- a/pkg/cache/sizedlru/sizedlru_test.go +++ b/pkg/cache/sizedlru/sizedlru_test.go @@ -5,9 +5,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" - - "github.com/trufflesecurity/trufflehog/v3/pkg/cache" - "github.com/trufflesecurity/trufflehog/v3/pkg/common" ) type mockCollector struct{ mock.Mock } @@ -34,9 +31,6 @@ func (m *mockCollector) RecordClear(cacheName string) { m.Called(cacheName) } func setupCache[T any](t *testing.T, withCollector bool) (*Cache[T], *mockCollector) { t.Helper() - // Call InitializeMetrics first. - cache.InitializeMetrics(common.MetricsNamespace, common.MetricsSubsystem) - var collector *mockCollector var c *Cache[T] var err error From d7efb6197849eaa85c971a0616e16ed395dabd4b Mon Sep 17 00:00:00 2001 From: Ahrav Dutta Date: Mon, 30 Sep 2024 12:41:26 -0700 Subject: [PATCH 4/5] rename --- pkg/cache/{sizedlru/sizedlru.go => lru/lru.go} | 4 ++-- pkg/cache/{sizedlru/sizedlru_test.go => lru/lru_test.go} | 2 +- pkg/cache/{sizedlru => lru}/metrics.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) rename pkg/cache/{sizedlru/sizedlru.go => lru/lru.go} (96%) rename pkg/cache/{sizedlru/sizedlru_test.go => lru/lru_test.go} (99%) rename pkg/cache/{sizedlru => lru}/metrics.go (98%) diff --git a/pkg/cache/sizedlru/sizedlru.go b/pkg/cache/lru/lru.go similarity index 96% rename from pkg/cache/sizedlru/sizedlru.go rename to pkg/cache/lru/lru.go index 1c710b1722c6..b859daca3bf3 100644 --- a/pkg/cache/sizedlru/sizedlru.go +++ b/pkg/cache/lru/lru.go @@ -1,10 +1,10 @@ -// Package sizedlru provides a generic, size-limited, LRU (Least Recently Used) cache with optional +// Package lru provides a generic, size-limited, LRU (Least Recently Used) cache with optional // metrics collection and reporting. It wraps the golang-lru/v2 caching library, adding support for custom // metrics tracking cache hits, misses, evictions, and other cache operations. // // This package supports configuring key aspects of cache behavior, including maximum cache size, // and custom metrics collection. -package sizedlru +package lru import ( "fmt" diff --git a/pkg/cache/sizedlru/sizedlru_test.go b/pkg/cache/lru/lru_test.go similarity index 99% rename from pkg/cache/sizedlru/sizedlru_test.go rename to pkg/cache/lru/lru_test.go index 6f110b6a31e0..1bb08e04f84a 100644 --- a/pkg/cache/sizedlru/sizedlru_test.go +++ b/pkg/cache/lru/lru_test.go @@ -1,4 +1,4 @@ -package sizedlru +package lru import ( "testing" diff --git a/pkg/cache/sizedlru/metrics.go b/pkg/cache/lru/metrics.go similarity index 98% rename from pkg/cache/sizedlru/metrics.go rename to pkg/cache/lru/metrics.go index b71d1bd5204f..ed2a2b986282 100644 --- a/pkg/cache/sizedlru/metrics.go +++ b/pkg/cache/lru/metrics.go @@ -1,4 +1,4 @@ -package sizedlru +package lru import ( "github.com/prometheus/client_golang/prometheus" From dfe62949c6b9fdec04e2ce511366701ab713b6bd Mon Sep 17 00:00:00 2001 From: Ahrav Dutta Date: Mon, 30 Sep 2024 13:04:51 -0700 Subject: [PATCH 5/5] update comments --- pkg/cache/lru/lru.go | 2 +- pkg/cache/lru/metrics.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/cache/lru/lru.go b/pkg/cache/lru/lru.go index b859daca3bf3..f8e117a8a769 100644 --- a/pkg/cache/lru/lru.go +++ b/pkg/cache/lru/lru.go @@ -16,7 +16,7 @@ import ( ) // collector is an interface that extends cache.BaseMetricsCollector -// and adds methods for recording cache hits, misses, and evictions. +// and adds methods for recording cache evictions. type collector interface { cache.BaseMetricsCollector diff --git a/pkg/cache/lru/metrics.go b/pkg/cache/lru/metrics.go index ed2a2b986282..3085a4e3a9a6 100644 --- a/pkg/cache/lru/metrics.go +++ b/pkg/cache/lru/metrics.go @@ -10,7 +10,7 @@ import ( var _ collector = (*MetricsCollector)(nil) // MetricsCollector extends the BaseMetricsCollector with Sized LRU specific metrics. -// It provides methods to record cache hits, misses, and evictions. +// It provides methods to record cache evictions. type MetricsCollector struct { // BaseMetricsCollector is embedded to provide the base metrics functionality. cache.BaseMetricsCollector