diff --git a/integrations/jikan/cache/store.go b/integrations/jikan/cache/store.go index 3dd8fe7..d85509e 100644 --- a/integrations/jikan/cache/store.go +++ b/integrations/jikan/cache/store.go @@ -10,32 +10,27 @@ import ( ) type Store struct { - db db.Querier - metrics *observability.Metrics + db db.Querier } -func NewStore(queries db.Querier, metrics *observability.Metrics) *Store { - return &Store{db: queries, metrics: metrics} +func NewStore(queries db.Querier) *Store { + return &Store{db: queries} } // Get retrieves a fresh cached value by key. func (s *Store) Get(parentCtx context.Context, key string, out any) bool { ctx, cancel := context.WithTimeout(parentCtx, 2*time.Second) defer cancel() - defer s.observeStats(parentCtx) data, err := s.db.GetJikanCache(ctx, key) if err != nil { - s.metrics.ObserveCache("jikan", "miss") return false } if err := json.Unmarshal([]byte(data), out); err != nil { - s.metrics.ObserveCache("jikan", "miss") return false } - s.metrics.ObserveCache("jikan", "hit") return true } @@ -43,20 +38,16 @@ func (s *Store) Get(parentCtx context.Context, key string, out any) bool { func (s *Store) GetStale(parentCtx context.Context, key string, out any) bool { ctx, cancel := context.WithTimeout(parentCtx, 2*time.Second) defer cancel() - defer s.observeStats(parentCtx) data, err := s.db.GetJikanCacheStale(ctx, key) if err != nil { - s.metrics.ObserveCache("jikan_stale", "miss") return false } if err := json.Unmarshal([]byte(data), out); err != nil { - s.metrics.ObserveCache("jikan_stale", "miss") return false } - s.metrics.ObserveCache("jikan_stale", "hit") return true } @@ -64,7 +55,6 @@ func (s *Store) GetStale(parentCtx context.Context, key string, out any) bool { func (s *Store) Set(parentCtx context.Context, key string, data any, ttl time.Duration) { ctx, cancel := context.WithTimeout(parentCtx, 2*time.Second) defer cancel() - defer s.observeStats(parentCtx) bytes, err := json.Marshal(data) if err != nil { @@ -87,22 +77,3 @@ func (s *Store) Set(parentCtx context.Context, key string, data any, ttl time.Du ) } } - -func (s *Store) observeStats(parentCtx context.Context) { - ctx, cancel := context.WithTimeout(parentCtx, 2*time.Second) - defer cancel() - - stats, err := s.db.GetJikanCacheStats(ctx) - if err != nil { - observability.LogJSON( - observability.LogLevelWarn, - "jikan_cache_stats", - "jikan", - "", - nil, - err, - ) - return - } - s.metrics.ObserveJikanCacheStats(stats.TotalRows, stats.ExpiredRows, stats.OldestExpiresAtSeconds) -} diff --git a/integrations/jikan/client.go b/integrations/jikan/client.go index 4c3efca..879da8e 100644 --- a/integrations/jikan/client.go +++ b/integrations/jikan/client.go @@ -39,21 +39,20 @@ const jikanSlowLogThreshold = 750 * time.Millisecond type APIError = jtransport.APIError -func NewClient(cfg config.Config, queries *db.Queries, metrics *observability.Metrics) *Client { +func NewClient(cfg config.Config, queries *db.Queries) *Client { limiter := rate.NewLimiter(400 * time.Millisecond) client := &Client{ baseURL: "https://api.jikan.moe/v4", db: queries, retrySignal: make(chan struct{}, 1), refreshSem: make(chan struct{}, 4), - cache: jcache.NewStore(queries, metrics), + cache: jcache.NewStore(queries), traceEnabled: cfg.JikanTrace, randomPool: make([]Anime, 0), } client.fetcher = jtransport.NewClient(jtransport.Config{ HTTPClient: jtransport.NewHTTPClient(), Limiter: limiter, - Metrics: metrics, TraceEnabled: client.jikanTraceEnabled, }) diff --git a/integrations/jikan/client_test.go b/integrations/jikan/client_test.go index 7f8de79..6a5ee47 100644 --- a/integrations/jikan/client_test.go +++ b/integrations/jikan/client_test.go @@ -7,7 +7,6 @@ import ( "io" "mal/internal/config" "mal/internal/db" - "mal/internal/observability" "net/http" "strings" "testing" @@ -31,7 +30,7 @@ func TestGetWithCacheReturnsStaleAndRefreshesAsync(t *testing.T) { }() queries := db.New(sqlDB) - client := NewClient(config.Config{}, queries, observability.NewMetrics()) + client := NewClient(config.Config{}, queries) stale := TopAnimeResponse{Data: []Anime{{MalID: 1, Title: "stale"}}} insertCachedResponse(t, sqlDB, "top:1", stale, time.Now().Add(-time.Hour)) @@ -65,7 +64,7 @@ func TestGetWithCacheAllowsEmptySearchResults(t *testing.T) { }() queries := db.New(sqlDB) - client := NewClient(config.Config{}, queries, observability.NewMetrics()) + client := NewClient(config.Config{}, queries) client.fetcher.HTTPClient = &http.Client{ Transport: roundTripFunc(func(*http.Request) (*http.Response, error) { body := `{"pagination":{"has_next_page":false},"data":[]}` @@ -95,7 +94,7 @@ func TestLoadCachedRandomPoolIgnoresExpiredAnimeCache(t *testing.T) { }() queries := db.New(sqlDB) - client := NewClient(config.Config{}, queries, observability.NewMetrics()) + client := NewClient(config.Config{}, queries) insertCachedAnime(t, sqlDB, "anime:1", Anime{MalID: 1, Title: "fresh"}, time.Now().Add(time.Hour)) insertCachedAnime(t, sqlDB, "anime:2", Anime{MalID: 2, Title: "expired"}, time.Now().Add(-time.Hour)) diff --git a/integrations/jikan/transport/client.go b/integrations/jikan/transport/client.go index fc6ac5d..cdc94b8 100644 --- a/integrations/jikan/transport/client.go +++ b/integrations/jikan/transport/client.go @@ -22,14 +22,12 @@ const slowLogThreshold = 750 * time.Millisecond type Client struct { HTTPClient *http.Client Limiter *rate.Limiter - Metrics *observability.Metrics TraceEnabled func() bool } type Config struct { HTTPClient *http.Client Limiter *rate.Limiter - Metrics *observability.Metrics TraceEnabled func() bool } @@ -58,7 +56,6 @@ func NewClient(cfg Config) *Client { return &Client{ HTTPClient: cfg.HTTPClient, Limiter: cfg.Limiter, - Metrics: cfg.Metrics, TraceEnabled: cfg.TraceEnabled, } } @@ -94,12 +91,10 @@ func (c *Client) FetchWithRetry(ctx context.Context, urlStr string, out any) err maxRetries := 5 startedAt := time.Now() attempts := 0 - endpoint := metricsEndpoint(urlStr) logAndReturn := func(statusCode int, err error) error { if isDoneContextError(ctx, err) { return err } - c.Metrics.ObserveJikanRequest(endpoint, statusCode, time.Since(startedAt), err) c.logUpstream(urlStr, statusCode, attempts, startedAt, err) return err } @@ -298,7 +293,7 @@ func (c *Client) logUpstream(urlStr string, statusCode int, attempts int, starte "", map[string]any{ "url": urlStr, - "endpoint": metricsEndpoint(urlStr), + "endpoint": endpointLabel(urlStr), "status": statusCode, "attempts": attempts, "duration_ms": float64(duration.Microseconds()) / 1000, @@ -307,7 +302,7 @@ func (c *Client) logUpstream(urlStr string, statusCode int, attempts int, starte ) } -func metricsEndpoint(urlStr string) string { +func endpointLabel(urlStr string) string { trimmed := strings.TrimSpace(urlStr) if trimmed == "" { return "unknown"