diff --git a/pkg/store/bucket_e2e_test.go b/pkg/store/bucket_e2e_test.go index c30ec4e36d7..27489907478 100644 --- a/pkg/store/bucket_e2e_test.go +++ b/pkg/store/bucket_e2e_test.go @@ -173,8 +173,9 @@ func testBucketStore_e2e(t testing.TB, ctx context.Context, s *storeSuite) { // TODO(bwplotka): Add those test cases to TSDB querier_test.go as well, there are no tests for matching. for i, tcase := range []struct { - req *storepb.SeriesRequest - expected [][]storepb.Label + req *storepb.SeriesRequest + expected [][]storepb.Label + expectedChunkLen int }{ { req: &storepb.SeriesRequest{ @@ -183,7 +184,9 @@ func testBucketStore_e2e(t testing.TB, ctx context.Context, s *storeSuite) { }, MinTime: mint, MaxTime: maxt, + NoChunk: false, }, + expectedChunkLen: 3, expected: [][]storepb.Label{ {{Name: "a", Value: "1"}, {Name: "b", Value: "1"}, {Name: "ext1", Value: "value1"}}, {{Name: "a", Value: "1"}, {Name: "b", Value: "2"}, {Name: "ext1", Value: "value1"}}, @@ -202,7 +205,9 @@ func testBucketStore_e2e(t testing.TB, ctx context.Context, s *storeSuite) { }, MinTime: mint, MaxTime: maxt, + NoChunk: false, }, + expectedChunkLen: 3, expected: [][]storepb.Label{ {{Name: "a", Value: "1"}, {Name: "b", Value: "1"}, {Name: "ext1", Value: "value1"}}, {{Name: "a", Value: "1"}, {Name: "b", Value: "2"}, {Name: "ext1", Value: "value1"}}, @@ -217,7 +222,9 @@ func testBucketStore_e2e(t testing.TB, ctx context.Context, s *storeSuite) { }, MinTime: mint, MaxTime: maxt, + NoChunk: false, }, + expectedChunkLen: 3, expected: [][]storepb.Label{ {{Name: "a", Value: "1"}, {Name: "b", Value: "1"}, {Name: "ext1", Value: "value1"}}, {{Name: "a", Value: "1"}, {Name: "b", Value: "2"}, {Name: "ext1", Value: "value1"}}, @@ -232,7 +239,9 @@ func testBucketStore_e2e(t testing.TB, ctx context.Context, s *storeSuite) { }, MinTime: mint, MaxTime: maxt, + NoChunk: false, }, + expectedChunkLen: 3, expected: [][]storepb.Label{ {{Name: "a", Value: "1"}, {Name: "b", Value: "1"}, {Name: "ext1", Value: "value1"}}, {{Name: "a", Value: "1"}, {Name: "b", Value: "2"}, {Name: "ext1", Value: "value1"}}, @@ -251,7 +260,9 @@ func testBucketStore_e2e(t testing.TB, ctx context.Context, s *storeSuite) { }, MinTime: mint, MaxTime: maxt, + NoChunk: false, }, + expectedChunkLen: 3, expected: [][]storepb.Label{ {{Name: "a", Value: "1"}, {Name: "b", Value: "1"}, {Name: "ext1", Value: "value1"}}, {{Name: "a", Value: "1"}, {Name: "b", Value: "2"}, {Name: "ext1", Value: "value1"}}, @@ -270,7 +281,9 @@ func testBucketStore_e2e(t testing.TB, ctx context.Context, s *storeSuite) { }, MinTime: mint, MaxTime: maxt, + NoChunk: false, }, + expectedChunkLen: 3, expected: [][]storepb.Label{ {{Name: "a", Value: "1"}, {Name: "b", Value: "2"}, {Name: "ext1", Value: "value1"}}, {{Name: "a", Value: "2"}, {Name: "b", Value: "2"}, {Name: "ext1", Value: "value1"}}, @@ -285,7 +298,9 @@ func testBucketStore_e2e(t testing.TB, ctx context.Context, s *storeSuite) { }, MinTime: mint, MaxTime: maxt, + NoChunk: false, }, + expectedChunkLen: 3, expected: [][]storepb.Label{ {{Name: "a", Value: "1"}, {Name: "c", Value: "1"}, {Name: "ext2", Value: "value2"}}, {{Name: "a", Value: "1"}, {Name: "c", Value: "2"}, {Name: "ext2", Value: "value2"}}, @@ -299,6 +314,7 @@ func testBucketStore_e2e(t testing.TB, ctx context.Context, s *storeSuite) { }, MinTime: mint, MaxTime: maxt, + NoChunk: false, }, }, { @@ -308,7 +324,9 @@ func testBucketStore_e2e(t testing.TB, ctx context.Context, s *storeSuite) { }, MinTime: mint, MaxTime: maxt, + NoChunk: false, }, + expectedChunkLen: 3, expected: [][]storepb.Label{ {{Name: "a", Value: "1"}, {Name: "b", Value: "1"}, {Name: "ext1", Value: "value1"}}, {{Name: "a", Value: "1"}, {Name: "b", Value: "2"}, {Name: "ext1", Value: "value1"}}, @@ -323,7 +341,9 @@ func testBucketStore_e2e(t testing.TB, ctx context.Context, s *storeSuite) { }, MinTime: mint, MaxTime: maxt, + NoChunk: false, }, + expectedChunkLen: 3, expected: [][]storepb.Label{ {{Name: "a", Value: "1"}, {Name: "b", Value: "1"}, {Name: "ext1", Value: "value1"}}, {{Name: "a", Value: "1"}, {Name: "b", Value: "2"}, {Name: "ext1", Value: "value1"}}, @@ -345,6 +365,25 @@ func testBucketStore_e2e(t testing.TB, ctx context.Context, s *storeSuite) { }, MinTime: mint, MaxTime: maxt, + NoChunk: false, + }, + }, + // test no-chunk option + { + req: &storepb.SeriesRequest{ + Matchers: []storepb.LabelMatcher{ + {Type: storepb.LabelMatcher_EQ, Name: "a", Value: "1"}, + }, + MinTime: mint, + MaxTime: maxt, + NoChunk: true, + }, + expectedChunkLen: 0, + expected: [][]storepb.Label{ + {{Name: "a", Value: "1"}, {Name: "b", Value: "1"}, {Name: "ext1", Value: "value1"}}, + {{Name: "a", Value: "1"}, {Name: "b", Value: "2"}, {Name: "ext1", Value: "value1"}}, + {{Name: "a", Value: "1"}, {Name: "c", Value: "1"}, {Name: "ext2", Value: "value2"}}, + {{Name: "a", Value: "1"}, {Name: "c", Value: "2"}, {Name: "ext2", Value: "value2"}}, }, }, } { @@ -357,7 +396,7 @@ func testBucketStore_e2e(t testing.TB, ctx context.Context, s *storeSuite) { for i, s := range srv.SeriesSet { testutil.Equals(t, tcase.expected[i], s.Labels) - testutil.Equals(t, 3, len(s.Chunks)) + testutil.Equals(t, tcase.expectedChunkLen, len(s.Chunks)) } } } diff --git a/pkg/store/proxy_test.go b/pkg/store/proxy_test.go index cc006a4a8e5..fbaba72cd00 100644 --- a/pkg/store/proxy_test.go +++ b/pkg/store/proxy_test.go @@ -2,6 +2,7 @@ package store import ( "context" + "fmt" "io" "math" "os" @@ -106,6 +107,7 @@ func TestProxyStore_Series(t *testing.T) { MinTime: 301, MaxTime: 400, Matchers: []storepb.LabelMatcher{{Name: "a", Value: "a", Type: storepb.LabelMatcher_EQ}}, + NoChunk: false, }, expectedWarningsLen: 1, // No store matched for this query. }, @@ -127,6 +129,7 @@ func TestProxyStore_Series(t *testing.T) { MinTime: 1, MaxTime: 300, Matchers: []storepb.LabelMatcher{{Name: "ext", Value: "2", Type: storepb.LabelMatcher_EQ}}, + NoChunk: false, }, expectedWarningsLen: 1, // No store matched for this query. }, @@ -148,6 +151,7 @@ func TestProxyStore_Series(t *testing.T) { MinTime: 1, MaxTime: 300, Matchers: []storepb.LabelMatcher{{Name: "ext", Value: "1", Type: storepb.LabelMatcher_EQ}}, + NoChunk: false, }, expectedSeries: []rawSeries{ { @@ -173,6 +177,7 @@ func TestProxyStore_Series(t *testing.T) { MinTime: 1, MaxTime: 300, Matchers: []storepb.LabelMatcher{{Name: "ext", Value: "1", Type: storepb.LabelMatcher_EQ}}, + NoChunk: false, }, expectedSeries: []rawSeries{ { @@ -199,6 +204,7 @@ func TestProxyStore_Series(t *testing.T) { MinTime: 1, MaxTime: 300, Matchers: []storepb.LabelMatcher{{Name: "ext", Value: "1", Type: storepb.LabelMatcher_EQ}}, + NoChunk: false, }, }, { @@ -218,6 +224,7 @@ func TestProxyStore_Series(t *testing.T) { MinTime: 1, MaxTime: 300, Matchers: []storepb.LabelMatcher{{Name: "a", Value: "b", Type: storepb.LabelMatcher_EQ}}, + NoChunk: false, }, expectedSeries: []rawSeries{ { @@ -284,6 +291,7 @@ func TestProxyStore_Series(t *testing.T) { MinTime: 1, MaxTime: 300, Matchers: []storepb.LabelMatcher{{Name: "ext", Value: "1", Type: storepb.LabelMatcher_EQ}}, + NoChunk: false, }, expectedSeries: []rawSeries{ { @@ -408,6 +416,32 @@ func TestProxyStore_Series(t *testing.T) { }, expectedErr: errors.New("fetch series for [name:\"ext\" value:\"1\" ] test: error!"), }, + { + title: "use no chunk to only get labels", + storeAPIs: []Client{ + &testClient{ + StoreClient: &mockedStoreAPI{ + RespSeries: []*storepb.SeriesResponse{ + storeSeriesResponse(t, labels.FromStrings("a", "a")), + }, + }, + minTime: 1, + maxTime: 300, + labelSets: []storepb.LabelSet{{Labels: []storepb.Label{{Name: "ext", Value: "1"}}}}, + }, + }, + req: &storepb.SeriesRequest{ + MinTime: 1, + MaxTime: 300, + Matchers: []storepb.LabelMatcher{{Name: "ext", Value: "1", Type: storepb.LabelMatcher_EQ}}, + NoChunk: true, + }, + expectedSeries: []rawSeries{ + { + lset: []storepb.Label{{Name: "a", Value: "a"}}, + }, + }, + }, } { if ok := t.Run(tc.title, func(t *testing.T) { @@ -420,6 +454,9 @@ func TestProxyStore_Series(t *testing.T) { s := newStoreSeriesServer(context.Background()) + if tc.req.NoChunk == true { + fmt.Println(1) + } err := q.Series(tc.req, s) if tc.expectedErr != nil { testutil.NotOk(t, err) diff --git a/pkg/store/tsdb_test.go b/pkg/store/tsdb_test.go index 3b1483f1943..275efa730ed 100644 --- a/pkg/store/tsdb_test.go +++ b/pkg/store/tsdb_test.go @@ -34,6 +34,137 @@ func TestTSDBStore_Info(t *testing.T) { testutil.Equals(t, int64(math.MaxInt64), resp.MaxTime) } +func TestTSDBStore_Series(t *testing.T) { + defer leaktest.CheckTimeout(t, 10*time.Second)() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + db, err := testutil.NewTSDB() + defer func() { testutil.Ok(t, db.Close()) }() + testutil.Ok(t, err) + + tsdbStore := NewTSDBStore(nil, nil, db, component.Rule, labels.FromStrings("region", "eu-west")) + + appender := db.Appender() + + for i := 1; i <= 3; i++ { + _, err = appender.Add(labels.FromStrings("a", "1"), int64(i), float64(i)) + testutil.Ok(t, err) + } + err = appender.Commit() + testutil.Ok(t, err) + + for _, tc := range []struct { + title string + req *storepb.SeriesRequest + expectedSeries []rawSeries + expectedError string + }{ + { + title: "total match series", + req: &storepb.SeriesRequest{ + MinTime: 1, + MaxTime: 3, + Matchers: []storepb.LabelMatcher{ + {Type: storepb.LabelMatcher_EQ, Name: "a", Value: "1"}, + }, + NoChunk: false, + }, + expectedSeries: []rawSeries{ + { + lset: []storepb.Label{{Name: "a", Value: "1"}, {Name: "region", Value: "eu-west"}}, + chunks: [][]sample{{{1, 1}, {2, 2}, {3, 3}}}, + }, + }, + }, + { + title: "partially match time range series", + req: &storepb.SeriesRequest{ + MinTime: 1, + MaxTime: 2, + Matchers: []storepb.LabelMatcher{ + {Type: storepb.LabelMatcher_EQ, Name: "a", Value: "1"}, + }, + NoChunk: false, + }, + expectedSeries: []rawSeries{ + { + lset: []storepb.Label{{Name: "a", Value: "1"}, {Name: "region", Value: "eu-west"}}, + chunks: [][]sample{{{1, 1}, {2, 2}}}, + }, + }, + }, + { + title: "dont't match time range series", + req: &storepb.SeriesRequest{ + MinTime: 4, + MaxTime: 6, + Matchers: []storepb.LabelMatcher{ + {Type: storepb.LabelMatcher_EQ, Name: "a", Value: "1"}, + }, + NoChunk: false, + }, + expectedSeries: []rawSeries{}, + }, + { + title: "only match external label", + req: &storepb.SeriesRequest{ + MinTime: 1, + MaxTime: 3, + Matchers: []storepb.LabelMatcher{ + {Type: storepb.LabelMatcher_EQ, Name: "region", Value: "eu-west"}, + }, + NoChunk: false, + }, + expectedError: "rpc error: code = InvalidArgument desc = no matchers specified (excluding external labels)", + }, + { + title: "dont't match labels", + req: &storepb.SeriesRequest{ + MinTime: 1, + MaxTime: 3, + Matchers: []storepb.LabelMatcher{ + {Type: storepb.LabelMatcher_EQ, Name: "b", Value: "1"}, + }, + NoChunk: false, + }, + expectedSeries: []rawSeries{}, + }, + { + title: "no chunk", + req: &storepb.SeriesRequest{ + MinTime: 1, + MaxTime: 3, + Matchers: []storepb.LabelMatcher{ + {Type: storepb.LabelMatcher_EQ, Name: "a", Value: "1"}, + }, + NoChunk: true, + }, + expectedSeries: []rawSeries{ + { + lset: []storepb.Label{{Name: "a", Value: "1"}, {Name: "region", Value: "eu-west"}}, + }, + }, + }, + } { + if ok := t.Run(tc.title, func(t *testing.T) { + srv := newStoreSeriesServer(ctx) + err := tsdbStore.Series(tc.req, srv) + if len(tc.expectedError) > 0 { + testutil.NotOk(t, err) + testutil.Equals(t, tc.expectedError, err.Error()) + } else { + testutil.Ok(t, err) + seriesEquals(t, tc.expectedSeries, srv.SeriesSet) + } + }); !ok { + return + } + } + +} + func TestTSDBStore_LabelNames(t *testing.T) { var err error defer leaktest.CheckTimeout(t, 10*time.Second)()