@@ -637,3 +637,109 @@ func Test_TenantFederation_MaxTenant(t *testing.T) {
637
637
})
638
638
}
639
639
}
640
+
641
+ func TestHandlerMetricsCleanup (t * testing.T ) {
642
+ reg := prometheus .NewPedanticRegistry ()
643
+ handler := NewHandler (HandlerConfig {QueryStatsEnabled : true }, tenantfederation.Config {}, http .DefaultTransport , log .NewNopLogger (), reg )
644
+
645
+ user1 := "user1"
646
+ user2 := "user2"
647
+ source := "api"
648
+
649
+ // Simulate activity for user1
650
+ handler .querySeconds .WithLabelValues (source , user1 ).Add (1.0 )
651
+ handler .queryFetchedSeries .WithLabelValues (source , user1 ).Add (100 )
652
+ handler .queryFetchedSamples .WithLabelValues (source , user1 ).Add (1000 )
653
+ handler .queryScannedSamples .WithLabelValues (source , user1 ).Add (2000 )
654
+ handler .queryPeakSamples .WithLabelValues (source , user1 ).Observe (500 )
655
+ handler .queryChunkBytes .WithLabelValues (source , user1 ).Add (1024 )
656
+ handler .queryDataBytes .WithLabelValues (source , user1 ).Add (2048 )
657
+ handler .rejectedQueries .WithLabelValues (reasonTooManySamples , source , user1 ).Add (5 )
658
+
659
+ // Simulate activity for user2
660
+ handler .querySeconds .WithLabelValues (source , user2 ).Add (2.0 )
661
+ handler .queryFetchedSeries .WithLabelValues (source , user2 ).Add (200 )
662
+ handler .queryFetchedSamples .WithLabelValues (source , user2 ).Add (2000 )
663
+ handler .queryScannedSamples .WithLabelValues (source , user2 ).Add (4000 )
664
+ handler .queryPeakSamples .WithLabelValues (source , user2 ).Observe (1000 )
665
+ handler .queryChunkBytes .WithLabelValues (source , user2 ).Add (2048 )
666
+ handler .queryDataBytes .WithLabelValues (source , user2 ).Add (4096 )
667
+ handler .rejectedQueries .WithLabelValues (reasonTooManySamples , source , user2 ).Add (10 )
668
+
669
+ // Verify initial state - both users should have metrics
670
+ require .NoError (t , promtest .GatherAndCompare (reg , strings .NewReader (`
671
+ # HELP cortex_query_seconds_total Total amount of wall clock time spend processing queries.
672
+ # TYPE cortex_query_seconds_total counter
673
+ cortex_query_seconds_total{source="api",user="user1"} 1
674
+ cortex_query_seconds_total{source="api",user="user2"} 2
675
+ # HELP cortex_query_fetched_series_total Number of series fetched to execute a query.
676
+ # TYPE cortex_query_fetched_series_total counter
677
+ cortex_query_fetched_series_total{source="api",user="user1"} 100
678
+ cortex_query_fetched_series_total{source="api",user="user2"} 200
679
+ # HELP cortex_query_samples_total Number of samples fetched to execute a query.
680
+ # TYPE cortex_query_samples_total counter
681
+ cortex_query_samples_total{source="api",user="user1"} 1000
682
+ cortex_query_samples_total{source="api",user="user2"} 2000
683
+ # HELP cortex_query_samples_scanned_total Number of samples scanned to execute a query.
684
+ # TYPE cortex_query_samples_scanned_total counter
685
+ cortex_query_samples_scanned_total{source="api",user="user1"} 2000
686
+ cortex_query_samples_scanned_total{source="api",user="user2"} 4000
687
+ # HELP cortex_query_peak_samples Highest count of samples considered to execute a query.
688
+ # TYPE cortex_query_peak_samples histogram
689
+ cortex_query_peak_samples_bucket{source="api",user="user1",le="+Inf"} 1
690
+ cortex_query_peak_samples_sum{source="api",user="user1"} 500
691
+ cortex_query_peak_samples_count{source="api",user="user1"} 1
692
+ cortex_query_peak_samples_bucket{source="api",user="user2",le="+Inf"} 1
693
+ cortex_query_peak_samples_sum{source="api",user="user2"} 1000
694
+ cortex_query_peak_samples_count{source="api",user="user2"} 1
695
+ # HELP cortex_query_fetched_chunks_bytes_total Size of all chunks fetched to execute a query in bytes.
696
+ # TYPE cortex_query_fetched_chunks_bytes_total counter
697
+ cortex_query_fetched_chunks_bytes_total{source="api",user="user1"} 1024
698
+ cortex_query_fetched_chunks_bytes_total{source="api",user="user2"} 2048
699
+ # HELP cortex_query_fetched_data_bytes_total Size of all data fetched to execute a query in bytes.
700
+ # TYPE cortex_query_fetched_data_bytes_total counter
701
+ cortex_query_fetched_data_bytes_total{source="api",user="user1"} 2048
702
+ cortex_query_fetched_data_bytes_total{source="api",user="user2"} 4096
703
+ # HELP cortex_rejected_queries_total The total number of queries that were rejected.
704
+ # TYPE cortex_rejected_queries_total counter
705
+ cortex_rejected_queries_total{reason="too_many_samples",source="api",user="user1"} 5
706
+ cortex_rejected_queries_total{reason="too_many_samples",source="api",user="user2"} 10
707
+ ` ), "cortex_query_seconds_total" , "cortex_query_fetched_series_total" , "cortex_query_samples_total" ,
708
+ "cortex_query_samples_scanned_total" , "cortex_query_peak_samples" , "cortex_query_fetched_chunks_bytes_total" ,
709
+ "cortex_query_fetched_data_bytes_total" , "cortex_rejected_queries_total" ))
710
+
711
+ // Clean up metrics for user1
712
+ handler .cleanupMetricsForInactiveUser (user1 )
713
+
714
+ // Verify final state - only user2 should have metrics
715
+ require .NoError (t , promtest .GatherAndCompare (reg , strings .NewReader (`
716
+ # HELP cortex_query_seconds_total Total amount of wall clock time spend processing queries.
717
+ # TYPE cortex_query_seconds_total counter
718
+ cortex_query_seconds_total{source="api",user="user2"} 2
719
+ # HELP cortex_query_fetched_series_total Number of series fetched to execute a query.
720
+ # TYPE cortex_query_fetched_series_total counter
721
+ cortex_query_fetched_series_total{source="api",user="user2"} 200
722
+ # HELP cortex_query_samples_total Number of samples fetched to execute a query.
723
+ # TYPE cortex_query_samples_total counter
724
+ cortex_query_samples_total{source="api",user="user2"} 2000
725
+ # HELP cortex_query_samples_scanned_total Number of samples scanned to execute a query.
726
+ # TYPE cortex_query_samples_scanned_total counter
727
+ cortex_query_samples_scanned_total{source="api",user="user2"} 4000
728
+ # HELP cortex_query_peak_samples Highest count of samples considered to execute a query.
729
+ # TYPE cortex_query_peak_samples histogram
730
+ cortex_query_peak_samples_bucket{source="api",user="user2",le="+Inf"} 1
731
+ cortex_query_peak_samples_sum{source="api",user="user2"} 1000
732
+ cortex_query_peak_samples_count{source="api",user="user2"} 1
733
+ # HELP cortex_query_fetched_chunks_bytes_total Size of all chunks fetched to execute a query in bytes.
734
+ # TYPE cortex_query_fetched_chunks_bytes_total counter
735
+ cortex_query_fetched_chunks_bytes_total{source="api",user="user2"} 2048
736
+ # HELP cortex_query_fetched_data_bytes_total Size of all data fetched to execute a query in bytes.
737
+ # TYPE cortex_query_fetched_data_bytes_total counter
738
+ cortex_query_fetched_data_bytes_total{source="api",user="user2"} 4096
739
+ # HELP cortex_rejected_queries_total The total number of queries that were rejected.
740
+ # TYPE cortex_rejected_queries_total counter
741
+ cortex_rejected_queries_total{reason="too_many_samples",source="api",user="user2"} 10
742
+ ` ), "cortex_query_seconds_total" , "cortex_query_fetched_series_total" , "cortex_query_samples_total" ,
743
+ "cortex_query_samples_scanned_total" , "cortex_query_peak_samples" , "cortex_query_fetched_chunks_bytes_total" ,
744
+ "cortex_query_fetched_data_bytes_total" , "cortex_rejected_queries_total" ))
745
+ }
0 commit comments