From e28f2d5b403bc6ccb1f7f2912044529ade616426 Mon Sep 17 00:00:00 2001 From: Matheus Nogueira Date: Wed, 4 Oct 2023 12:42:55 -0300 Subject: [PATCH] feat: cache hit metrics (#3214) --- server/app/app.go | 2 +- server/telemetry/metrics.go | 2 +- server/test/run_repository.go | 60 +++++++++++++++++++++++++++++++---- 3 files changed, 55 insertions(+), 9 deletions(-) diff --git a/server/app/app.go b/server/app/app.go index bae622b020..cd06d4862a 100644 --- a/server/app/app.go +++ b/server/app/app.go @@ -228,7 +228,7 @@ func (app *App) Start(opts ...appOption) error { variableSetRepo := variableset.NewRepository(db) linterRepo := analyzer.NewRepository(db) testRepo := test.NewRepository(db) - runRepo := test.NewRunRepository(db, test.NewCache(instanceID)) + runRepo := test.NewRunRepository(db, test.NewCache(instanceID, test.WithMetricMeter(meter))) testRunnerRepo := testrunner.NewRepository(db) tracesRepo := traces.NewTraceRepository(db) diff --git a/server/telemetry/metrics.go b/server/telemetry/metrics.go index bab869c8d1..2d33b10012 100644 --- a/server/telemetry/metrics.go +++ b/server/telemetry/metrics.go @@ -43,7 +43,7 @@ func newMeterProvider(ctx context.Context, cfg exporterConfig) (metric.MeterProv return nil, fmt.Errorf("could not get collector exporter: %w", err) } - interval := 60 * time.Second + interval := 10 * time.Second if exporterConfig.MetricsReaderInterval != 0 { interval = exporterConfig.MetricsReaderInterval } diff --git a/server/test/run_repository.go b/server/test/run_repository.go index 2a88d567aa..fb2bea87bc 100644 --- a/server/test/run_repository.go +++ b/server/test/run_repository.go @@ -14,6 +14,9 @@ import ( "github.com/kubeshop/tracetest/server/pkg/sqlutil" "github.com/kubeshop/tracetest/server/variableset" "github.com/patrickmn/go-cache" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/metric" + "go.opentelemetry.io/otel/metric/noop" "go.opentelemetry.io/otel/trace" ) @@ -31,17 +34,46 @@ type RunRepository interface { } type Cache struct { - cache *cache.Cache - instanceID string + cache *cache.Cache + instanceID string + readRequestCounter metric.Int64Counter + cacheLatencyHistogram metric.Int64Histogram } -func NewCache(instanceID string) *Cache { - return &Cache{ - cache: cache.New(5*time.Minute, 10*time.Minute), - instanceID: instanceID, +type CacheConfig struct { + meter metric.Meter +} + +type CacheOption func(*CacheConfig) + +func WithMetricMeter(meter metric.Meter) CacheOption { + return func(c *CacheConfig) { + c.meter = meter } } +func NewCache(instanceID string, opts ...CacheOption) *Cache { + cacheConfig := &CacheConfig{ + meter: noop.NewMeterProvider().Meter("noop"), + } + + for _, opt := range opts { + opt(cacheConfig) + } + + readRequestCounter, _ := cacheConfig.meter.Int64Counter("tracetest.cache.request.count") + cacheLatencyHistogram, _ := cacheConfig.meter.Int64Histogram("tracetest.cache.latency") + + cache := &Cache{ + cache: cache.New(5*time.Minute, 10*time.Minute), + instanceID: instanceID, + readRequestCounter: readRequestCounter, + cacheLatencyHistogram: cacheLatencyHistogram, + } + + return cache +} + func (c *Cache) thisInstanceCacheKey(run Run) string { return fmt.Sprintf("%s-%s-%d", c.instanceID, run.TestID, run.ID) } @@ -62,7 +94,21 @@ func (c *Cache) Set(_ context.Context, run Run) error { } func (c *Cache) Get(ctx context.Context, testID id.ID, runID int) (Run, bool) { - cached, found := c.cache.Get(c.lastInstanceCacheKey(ctx, Run{ID: runID, TestID: testID})) + begin := time.Now() + key := c.lastInstanceCacheKey(ctx, Run{ID: runID, TestID: testID}) + cached, found := c.cache.Get(key) + + duration := time.Since(begin) + + attributeSet := attribute.NewSet( + attribute.String("object_type", "test_run"), + attribute.String("key", key), + attribute.Bool("hit", found), + ) + + c.readRequestCounter.Add(ctx, 1, metric.WithAttributeSet(attributeSet)) + c.cacheLatencyHistogram.Record(ctx, duration.Milliseconds(), metric.WithAttributeSet(attributeSet)) + if !found { return Run{}, false }