Skip to content

Commit 5bc90ec

Browse files
committed
create more tests on the expanded postings cache
Signed-off-by: alanprot <[email protected]>
1 parent 76adacd commit 5bc90ec

File tree

2 files changed

+183
-0
lines changed

2 files changed

+183
-0
lines changed

pkg/ingester/ingester_test.go

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5605,6 +5605,181 @@ func TestExpendedPostingsCacheIsolation(t *testing.T) {
56055605
wg.Wait()
56065606
}
56075607

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+
56085783
func TestExpendedPostingsCache(t *testing.T) {
56095784
cfg := defaultIngesterTestConfig(t)
56105785
cfg.BlocksStorageConfig.TSDB.ExpandedCachingExpireInterval = time.Second

pkg/storage/tsdb/expanded_postings_cache.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ type ExpandedPostingsCache interface {
125125
PostingsForMatchers(ctx context.Context, blockID ulid.ULID, ix tsdb.IndexReader, ms ...*labels.Matcher) (index.Postings, error)
126126
ExpireSeries(metric labels.Labels)
127127
PurgeExpiredItems()
128+
Clear()
128129
Size() int
129130
}
130131

@@ -138,6 +139,12 @@ type blocksPostingsForMatchersCache struct {
138139

139140
metrics *ExpandedPostingsCacheMetrics
140141
seedByHash *seedByHash
142+
cfg TSDBPostingsCacheConfig
143+
}
144+
145+
func (c *blocksPostingsForMatchersCache) Clear() {
146+
c.headCache = newFifoCache[[]storage.SeriesRef](c.cfg.Head, "head", c.metrics, c.cfg.timeNow)
147+
c.blocksCache = newFifoCache[[]storage.SeriesRef](c.cfg.Blocks, "block", c.metrics, c.cfg.timeNow)
141148
}
142149

143150
func newBlocksPostingsForMatchersCache(userId string, cfg TSDBPostingsCacheConfig, metrics *ExpandedPostingsCacheMetrics, seedByHash *seedByHash) ExpandedPostingsCache {
@@ -157,6 +164,7 @@ func newBlocksPostingsForMatchersCache(userId string, cfg TSDBPostingsCacheConfi
157164
metrics: metrics,
158165
seedByHash: seedByHash,
159166
userId: userId,
167+
cfg: cfg,
160168
}
161169
}
162170

0 commit comments

Comments
 (0)