@@ -5605,6 +5605,181 @@ func TestExpendedPostingsCacheIsolation(t *testing.T) {
5605
5605
wg .Wait ()
5606
5606
}
5607
5607
5608
+ func TestExpendedPostingsCacheMatchers (t * testing.T ) {
5609
+ cfg := defaultIngesterTestConfig (t )
5610
+ cfg .BlocksStorageConfig .TSDB .ExpandedCachingExpireInterval = time .Second
5611
+ cfg .BlocksStorageConfig .TSDB .BlockRanges = []time.Duration {2 * time .Hour }
5612
+ cfg .BlocksStorageConfig .TSDB .PostingsCache .Blocks .Enabled = true
5613
+ cfg .BlocksStorageConfig .TSDB .PostingsCache .Head .Enabled = true
5614
+
5615
+ ctx := user .InjectOrgID (context .Background (), userID )
5616
+
5617
+ r := prometheus .NewRegistry ()
5618
+ ing , err := prepareIngesterWithBlocksStorage (t , cfg , r )
5619
+ require .NoError (t , err )
5620
+ require .NoError (t , services .StartAndAwaitRunning (context .Background (), ing ))
5621
+ defer services .StopAndAwaitTerminated (context .Background (), ing ) //nolint:errcheck
5622
+
5623
+ // Wait until the ingester is ACTIVE
5624
+ test .Poll (t , 100 * time .Millisecond , ring .ACTIVE , func () interface {} {
5625
+ return ing .lifecycler .GetState ()
5626
+ })
5627
+
5628
+ numberOfMetricNames := 10
5629
+ seriesPerMetricsNames := 25
5630
+ timeStamp := int64 (60 * 1000 )
5631
+ seriesCreated := map [string ]labels.Labels {}
5632
+
5633
+ for i := 0 ; i < numberOfMetricNames ; i ++ {
5634
+ metricName := fmt .Sprintf ("metric_%v" , i )
5635
+ for j := 0 ; j < seriesPerMetricsNames ; j ++ {
5636
+ s := labels .FromStrings (labels .MetricName , metricName , "labelA" , fmt .Sprintf ("series_%v" , j ))
5637
+ _ , err = ing .Push (ctx , cortexpb .ToWriteRequest ([]labels.Labels {s }, []cortexpb.Sample {{Value : 2 , TimestampMs : timeStamp }}, nil , nil , cortexpb .API ))
5638
+ seriesCreated [s .String ()] = s
5639
+ require .NoError (t , err )
5640
+ }
5641
+ }
5642
+
5643
+ db := ing .getTSDB (userID )
5644
+
5645
+ type testCase struct {
5646
+ matchers []* client.LabelMatcher
5647
+ }
5648
+
5649
+ cases := []testCase {}
5650
+
5651
+ nameMatcher := & client.LabelMatcher {
5652
+ Type : client .EQUAL ,
5653
+ Name : labels .MetricName ,
5654
+ Value : "metric_0" ,
5655
+ }
5656
+
5657
+ for i := 0 ; i < 4 ; i ++ {
5658
+ tc := testCase {
5659
+ matchers : []* client.LabelMatcher {nameMatcher },
5660
+ }
5661
+
5662
+ switch client .MatchType (i ) {
5663
+ case client .EQUAL | client .NOT_EQUAL :
5664
+ tc .matchers = append (tc .matchers , & client.LabelMatcher {
5665
+ Type : client .MatchType (i ),
5666
+ Name : "labelA" ,
5667
+ Value : "series_0" ,
5668
+ })
5669
+ default :
5670
+ tc .matchers = append (tc .matchers , & client.LabelMatcher {
5671
+ Type : client .MatchType (i ),
5672
+ Name : "labelA" ,
5673
+ Value : "series_.*" ,
5674
+ })
5675
+ }
5676
+ cases = append (cases , tc )
5677
+ }
5678
+
5679
+ cases = append (cases ,
5680
+ testCase {
5681
+ matchers : []* client.LabelMatcher {
5682
+ nameMatcher ,
5683
+ {
5684
+ Type : client .REGEX_MATCH ,
5685
+ Name : "labelA" ,
5686
+ Value : "" ,
5687
+ },
5688
+ },
5689
+ },
5690
+ testCase {
5691
+ matchers : []* client.LabelMatcher {
5692
+ nameMatcher ,
5693
+ {
5694
+ Type : client .REGEX_NO_MATCH ,
5695
+ Name : "labelA" ,
5696
+ Value : "" ,
5697
+ },
5698
+ },
5699
+ },
5700
+ )
5701
+
5702
+ ranges := []struct {
5703
+ startTs , endTs int64
5704
+ hasSamples bool
5705
+ }{
5706
+ // Totally in the past
5707
+ {
5708
+ startTs : 0 ,
5709
+ endTs : timeStamp / 2 ,
5710
+ hasSamples : false ,
5711
+ },
5712
+ {
5713
+ startTs : timeStamp / 2 ,
5714
+ endTs : timeStamp ,
5715
+ hasSamples : true ,
5716
+ },
5717
+ {
5718
+ startTs : timeStamp / 2 ,
5719
+ endTs : timeStamp * 2 ,
5720
+ hasSamples : true ,
5721
+ },
5722
+ {
5723
+ startTs : timeStamp + 1 ,
5724
+ endTs : timeStamp * 2 ,
5725
+ hasSamples : false ,
5726
+ },
5727
+ }
5728
+
5729
+ verify := func (t * testing.T , tc testCase , startTs , endTs int64 , hasSamples bool ) {
5730
+ s := & mockQueryStreamServer {ctx : ctx }
5731
+ err := ing .QueryStream (& client.QueryRequest {
5732
+ StartTimestampMs : startTs ,
5733
+ EndTimestampMs : endTs ,
5734
+ Matchers : tc .matchers ,
5735
+ }, s )
5736
+ require .NoError (t , err )
5737
+ if hasSamples {
5738
+ expectedCount := len (seriesCreated )
5739
+ matchers , err := client .FromLabelMatchers (ing .matchersCache , tc .matchers )
5740
+ require .NoError (t , err )
5741
+ for _ , s := range seriesCreated {
5742
+ for _ , m := range matchers {
5743
+ if ! m .Matches (s .Get (m .Name )) {
5744
+ expectedCount --
5745
+ break
5746
+ }
5747
+ }
5748
+ }
5749
+
5750
+ require .Equal (t , expectedCount , len (s .series ))
5751
+ } else {
5752
+ require .Equal (t , 0 , len (s .series ))
5753
+ }
5754
+ }
5755
+
5756
+ for _ , tc := range cases {
5757
+ testName := ""
5758
+ for _ , matcher := range tc .matchers {
5759
+ t , _ := matcher .MatcherType ()
5760
+ testName += matcher .Name + t .String () + matcher .Value + "|"
5761
+
5762
+ }
5763
+ t .Run (fmt .Sprintf ("%v" , testName ), func (t * testing.T ) {
5764
+ for _ , r := range ranges {
5765
+ t .Run (fmt .Sprintf ("start=%v,end=%v" , r .startTs , r .endTs ), func (t * testing.T ) {
5766
+ db .postingCache .Clear ()
5767
+
5768
+ // lets run 2 times to hit the cache
5769
+ for i := 0 ; i < 2 ; i ++ {
5770
+ verify (t , tc , r .startTs , r .endTs , r .hasSamples )
5771
+ }
5772
+
5773
+ // run the test again with all other ranges
5774
+ for _ , r1 := range ranges {
5775
+ verify (t , tc , r1 .startTs , r1 .endTs , r1 .hasSamples )
5776
+ }
5777
+ })
5778
+ }
5779
+ })
5780
+ }
5781
+ }
5782
+
5608
5783
func TestExpendedPostingsCache (t * testing.T ) {
5609
5784
cfg := defaultIngesterTestConfig (t )
5610
5785
cfg .BlocksStorageConfig .TSDB .ExpandedCachingExpireInterval = time .Second
0 commit comments