From ac097acb137e23e829593c758a974f8b6c274e0c Mon Sep 17 00:00:00 2001 From: Santi Leira Date: Mon, 3 Feb 2025 20:13:28 -0300 Subject: [PATCH] Make use of LabelHints.Limit for `LabelNames` and `LabelValues` requests (#8805) (#10410) * Use LabelHints.Limit WIP Add limit field on LabelNamesRequest and LabelValuesRequest Add support for limit on gateway.proto Rename variables to keep consistency Fix tests Add tests Add tests Add tests Add tests Add changelog Fix changelog Fix tests Fix imports empty commit Update pkg/distributor/distributor.go Co-authored-by: Arve Knudsen Update pkg/distributor/distributor_test.go Co-authored-by: Arve Knudsen Update pkg/distributor/distributor_test.go Co-authored-by: Arve Knudsen Update pkg/distributor/distributor_test.go Co-authored-by: Arve Knudsen Update pkg/distributor/distributor_test.go Co-authored-by: Arve Knudsen Update pkg/querier/tenantfederation/merge_queryable_test.go Co-authored-by: Arve Knudsen Update pkg/distributor/distributor_test.go Co-authored-by: Arve Knudsen Update pkg/querier/tenantfederation/merge_queryable_test.go Co-authored-by: Arve Knudsen Update pkg/storegateway/bucket.go Co-authored-by: Arve Knudsen Update pkg/storegateway/bucket.go Co-authored-by: Arve Knudsen Update CHANGELOG.md Co-authored-by: Arve Knudsen Update pkg/distributor/distributor.go Co-authored-by: Arve Knudsen Update pkg/distributor/distributor_test.go Co-authored-by: Arve Knudsen Update pkg/distributor/distributor_test.go Co-authored-by: Arve Knudsen Update pkg/distributor/distributor_test.go Co-authored-by: Arve Knudsen Update pkg/ingester/client/compat.go Co-authored-by: Arve Knudsen Update pkg/ingester/client/compat.go Co-authored-by: Arve Knudsen Apply suggestions from code review Co-authored-by: Arve Knudsen Apply suggestions from code review Co-authored-by: Arve Knudsen Fix pipeline Fix tests empty commit * Rebase * Apply suggestions from code review Co-authored-by: Arve Knudsen * Addressed feedback PR * Addressed feedback PR * Addressed feedback PR from charleskorn * Fix test * Update CHANGELOG.md --------- Co-authored-by: Arve Knudsen Co-authored-by: Charles Korn --- CHANGELOG.md | 1 + pkg/distributor/distributor.go | 17 +- pkg/distributor/distributor_test.go | 99 +++++- pkg/ingester/client/compat.go | 39 ++- pkg/ingester/client/compat_test.go | 7 +- pkg/ingester/client/ingester.pb.go | 299 +++++++++++------- pkg/ingester/client/ingester.proto | 2 + pkg/ingester/ingester.go | 20 +- pkg/ingester/ingester_test.go | 78 ++++- pkg/querier/blocks_store_queryable.go | 41 ++- pkg/querier/distributor_queryable.go | 12 +- pkg/querier/distributor_queryable_test.go | 48 ++- pkg/querier/querier_test.go | 22 +- .../tenantfederation/merge_queryable_test.go | 14 +- pkg/storegateway/bucket.go | 14 +- pkg/storegateway/bucket_e2e_test.go | 17 + pkg/storegateway/storepb/rpc.pb.go | 166 +++++++--- pkg/storegateway/storepb/rpc.proto | 4 + 18 files changed, 667 insertions(+), 233 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f2fed7965..854b79de1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ * `cortex_ingester_tsdb_block_postings_for_matchers_cache_skips_total` * `cortex_ingester_tsdb_block_postings_for_matchers_cache_evictions_total` * [ENHANCEMENT] Compactor: Shuffle users' order in `BlocksCleaner`. Prevents bucket indexes from going an extended period without cleanup during compactor restarts. #10513 +* [ENHANCEMENT] Distributor, querier, ingester and store-gateway: Add support for `limit` parameter for label names and values requests. #10410 * [BUGFIX] Distributor: Use a boolean to track changes while merging the ReplicaDesc components, rather than comparing the objects directly. #10185 * [BUGFIX] Querier: fix timeout responding to query-frontend when response size is very close to `-querier.frontend-client.grpc-max-send-msg-size`. #10154 * [BUGFIX] Query-frontend and querier: show warning/info annotations in some cases where they were missing (if a lazy querier was used). #10277 diff --git a/pkg/distributor/distributor.go b/pkg/distributor/distributor.go index 03ffdd2066..80418c1e98 100644 --- a/pkg/distributor/distributor.go +++ b/pkg/distributor/distributor.go @@ -44,6 +44,7 @@ import ( "github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/model/relabel" "github.com/prometheus/prometheus/scrape" + "github.com/prometheus/prometheus/storage" "go.uber.org/atomic" "golang.org/x/sync/errgroup" @@ -1971,13 +1972,13 @@ func queryIngesterPartitionsRingZoneSorter(preferredZone string) ring.ZoneSorter // LabelValuesForLabelName returns the label values associated with the given labelName, among all series with samples // timestamp between from and to, and series labels matching the optional matchers. -func (d *Distributor) LabelValuesForLabelName(ctx context.Context, from, to model.Time, labelName model.LabelName, matchers ...*labels.Matcher) ([]string, error) { +func (d *Distributor) LabelValuesForLabelName(ctx context.Context, from, to model.Time, labelName model.LabelName, hints *storage.LabelHints, matchers ...*labels.Matcher) ([]string, error) { replicationSets, err := d.getIngesterReplicationSetsForQuery(ctx) if err != nil { return nil, err } - req, err := ingester_client.ToLabelValuesRequest(labelName, from, to, matchers) + req, err := ingester_client.ToLabelValuesRequest(labelName, from, to, hints, matchers) if err != nil { return nil, err } @@ -2004,6 +2005,10 @@ func (d *Distributor) LabelValuesForLabelName(ctx context.Context, from, to mode // We need the values returned to be sorted. slices.Sort(values) + if hints != nil && hints.Limit > 0 && len(values) > hints.Limit { + values = values[:hints.Limit] + } + return values, nil } @@ -2693,13 +2698,13 @@ func maxFromZones[T ~float64 | ~uint64](seriesCountByZone map[string]T) (val T) // LabelNames returns the names of all labels from series with samples timestamp between from and to, and matching // the input optional series label matchers. The returned label names are sorted. -func (d *Distributor) LabelNames(ctx context.Context, from, to model.Time, matchers ...*labels.Matcher) ([]string, error) { +func (d *Distributor) LabelNames(ctx context.Context, from, to model.Time, hints *storage.LabelHints, matchers ...*labels.Matcher) ([]string, error) { replicationSets, err := d.getIngesterReplicationSetsForQuery(ctx) if err != nil { return nil, err } - req, err := ingester_client.ToLabelNamesRequest(from, to, matchers) + req, err := ingester_client.ToLabelNamesRequest(from, to, hints, matchers) if err != nil { return nil, err } @@ -2725,6 +2730,10 @@ func (d *Distributor) LabelNames(ctx context.Context, from, to model.Time, match slices.Sort(values) + if hints != nil && hints.Limit > 0 && len(values) > hints.Limit { + values = values[:hints.Limit] + } + return values, nil } diff --git a/pkg/distributor/distributor_test.go b/pkg/distributor/distributor_test.go index f6393788a4..5f4ffd0b54 100644 --- a/pkg/distributor/distributor_test.go +++ b/pkg/distributor/distributor_test.go @@ -42,6 +42,7 @@ import ( "github.com/prometheus/prometheus/model/labels" "github.com/prometheus/prometheus/model/relabel" "github.com/prometheus/prometheus/scrape" + "github.com/prometheus/prometheus/storage" promtestutil "github.com/prometheus/prometheus/util/testutil" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -3290,6 +3291,7 @@ func TestDistributor_LabelNames(t *testing.T) { tests := map[string]struct { shuffleShardSize int + hints *storage.LabelHints matchers []*labels.Matcher expectedResult []string expectedIngesters int @@ -3308,6 +3310,38 @@ func TestDistributor_LabelNames(t *testing.T) { expectedResult: []string{labels.MetricName, "reason", "status"}, expectedIngesters: numIngesters, }, + "should filter metrics by single matcher and apply limit": { + hints: &storage.LabelHints{Limit: 2}, + matchers: []*labels.Matcher{ + mustNewMatcher(labels.MatchEqual, model.MetricNameLabel, "test_1"), + }, + expectedResult: []string{labels.MetricName, "reason"}, + expectedIngesters: numIngesters, + }, + "should filter metrics by single matcher and ignore limit when it is zero": { + hints: &storage.LabelHints{Limit: 0}, + matchers: []*labels.Matcher{ + mustNewMatcher(labels.MatchEqual, model.MetricNameLabel, "test_1"), + }, + expectedResult: []string{labels.MetricName, "reason", "status"}, + expectedIngesters: numIngesters, + }, + "should filter metrics by single matcher and ignore limit when it is equal than the number of items returned": { + hints: &storage.LabelHints{Limit: 3}, + matchers: []*labels.Matcher{ + mustNewMatcher(labels.MatchEqual, model.MetricNameLabel, "test_1"), + }, + expectedResult: []string{labels.MetricName, "reason", "status"}, + expectedIngesters: numIngesters, + }, + "should filter metrics by single matcher and ignore limit when it is greater than the number of items returned": { + hints: &storage.LabelHints{Limit: 5}, + matchers: []*labels.Matcher{ + mustNewMatcher(labels.MatchEqual, model.MetricNameLabel, "test_1"), + }, + expectedResult: []string{labels.MetricName, "reason", "status"}, + expectedIngesters: numIngesters, + }, "should filter metrics by multiple matchers": { matchers: []*labels.Matcher{ mustNewMatcher(labels.MatchEqual, "status", "200"), @@ -3316,6 +3350,15 @@ func TestDistributor_LabelNames(t *testing.T) { expectedResult: []string{labels.MetricName, "status"}, expectedIngesters: numIngesters, }, + "should filter metrics by multiple matchers and apply limit": { + hints: &storage.LabelHints{Limit: 1}, + matchers: []*labels.Matcher{ + mustNewMatcher(labels.MatchEqual, "status", "200"), + mustNewMatcher(labels.MatchEqual, model.MetricNameLabel, "test_1"), + }, + expectedResult: []string{labels.MetricName}, + expectedIngesters: numIngesters, + }, "should query only ingesters belonging to tenant's subring if shuffle sharding is enabled": { shuffleShardSize: 3, matchers: []*labels.Matcher{ @@ -3324,6 +3367,15 @@ func TestDistributor_LabelNames(t *testing.T) { expectedResult: []string{labels.MetricName, "reason", "status"}, expectedIngesters: 3, }, + "should query only ingesters belonging to tenant's subring if shuffle sharding is enabled and apply limit": { + shuffleShardSize: 3, + hints: &storage.LabelHints{Limit: 1}, + matchers: []*labels.Matcher{ + mustNewMatcher(labels.MatchEqual, model.MetricNameLabel, "test_1"), + }, + expectedResult: []string{labels.MetricName}, + expectedIngesters: 3, + }, } for testName, testData := range tests { @@ -3365,7 +3417,7 @@ func TestDistributor_LabelNames(t *testing.T) { require.NoError(t, err) } - names, err := ds[0].LabelNames(ctx, now, now, testData.matchers...) + names, err := ds[0].LabelNames(ctx, now, now, testData.hints, testData.matchers...) require.NoError(t, err) assert.ElementsMatch(t, testData.expectedResult, names) @@ -3551,6 +3603,7 @@ func TestDistributor_LabelValuesForLabelName(t *testing.T) { tests := map[string]struct { from, to model.Time expectedLabelValues []string + hints *storage.LabelHints matchers []*labels.Matcher }{ "all time selected, no matchers": { @@ -3569,6 +3622,30 @@ func TestDistributor_LabelValuesForLabelName(t *testing.T) { expectedLabelValues: []string{"label_1"}, matchers: []*labels.Matcher{mustNewMatcher(labels.MatchEqual, "reason", "broken")}, }, + "all time selected, no matchers, hints provided without limit": { + from: 0, + to: 300_000, + hints: &storage.LabelHints{Limit: 0}, + expectedLabelValues: []string{"label_0", "label_1"}, + }, + "all time selected, no matchers, limit provided": { + from: 0, + to: 300_000, + hints: &storage.LabelHints{Limit: 1}, + expectedLabelValues: []string{"label_0"}, + }, + "all time selected, no matchers, limit equal to number of label values": { + from: 0, + to: 300_000, + hints: &storage.LabelHints{Limit: 2}, + expectedLabelValues: []string{"label_0", "label_1"}, + }, + "all time selected, no matchers, limit greater than number of label values": { + from: 0, + to: 300_000, + hints: &storage.LabelHints{Limit: 4}, + expectedLabelValues: []string{"label_0", "label_1"}, + }, } for testName, testCase := range tests { @@ -3599,7 +3676,7 @@ func TestDistributor_LabelValuesForLabelName(t *testing.T) { require.NoError(t, err) } - response, err := ds[0].LabelValuesForLabelName(ctx, testCase.from, testCase.to, labels.MetricName, testCase.matchers...) + response, err := ds[0].LabelValuesForLabelName(ctx, testCase.from, testCase.to, labels.MetricName, testCase.hints, testCase.matchers...) require.NoError(t, err) assert.ElementsMatch(t, response, testCase.expectedLabelValues) }) @@ -6447,7 +6524,7 @@ func (i *mockIngester) LabelValues(ctx context.Context, req *client.LabelValuesR return nil, errFail } - labelName, from, to, matchers, err := client.FromLabelValuesRequest(req) + labelName, from, to, hints, matchers, err := client.FromLabelValuesRequest(req) if err != nil { return nil, err } @@ -6481,6 +6558,9 @@ func (i *mockIngester) LabelValues(ctx context.Context, req *client.LabelValuesR slices.Sort(response) + if hints != nil && hints.Limit > 0 && len(response) > hints.Limit { + response = response[:hints.Limit] + } return &client.LabelValuesResponse{LabelValues: response}, nil } @@ -6498,21 +6578,32 @@ func (i *mockIngester) LabelNames(ctx context.Context, req *client.LabelNamesReq return nil, errFail } - _, _, matchers, err := client.FromLabelNamesRequest(req) + _, _, hints, matchers, err := client.FromLabelNamesRequest(req) if err != nil { return nil, err } response := client.LabelNamesResponse{} + labelsSet := map[string]struct{}{} + for _, ts := range i.timeseries { if match(ts.Labels, matchers) { for _, lbl := range ts.Labels { + if _, ok := labelsSet[lbl.Name]; ok { + continue + } + + labelsSet[lbl.Name] = struct{}{} response.LabelNames = append(response.LabelNames, lbl.Name) } } } slices.Sort(response.LabelNames) + if hints != nil && hints.Limit > 0 && len(response.LabelNames) > hints.Limit { + response.LabelNames = response.LabelNames[:hints.Limit] + } + return &response, nil } diff --git a/pkg/ingester/client/compat.go b/pkg/ingester/client/compat.go index f79b1010d8..3907a5bb95 100644 --- a/pkg/ingester/client/compat.go +++ b/pkg/ingester/client/compat.go @@ -10,6 +10,7 @@ import ( "github.com/prometheus/common/model" "github.com/prometheus/prometheus/model/labels" + "github.com/prometheus/prometheus/storage" "github.com/grafana/mimir/pkg/mimirpb" ) @@ -108,62 +109,82 @@ func FromMetricsForLabelMatchersResponse(resp *MetricsForLabelMatchersResponse) } // ToLabelValuesRequest builds a LabelValuesRequest proto -func ToLabelValuesRequest(labelName model.LabelName, from, to model.Time, matchers []*labels.Matcher) (*LabelValuesRequest, error) { +func ToLabelValuesRequest(labelName model.LabelName, from, to model.Time, hints *storage.LabelHints, matchers []*labels.Matcher) (*LabelValuesRequest, error) { ms, err := ToLabelMatchers(matchers) if err != nil { return nil, err } + var limit int64 + if hints != nil && hints.Limit > 0 { + limit = int64(hints.Limit) + } return &LabelValuesRequest{ LabelName: string(labelName), StartTimestampMs: int64(from), EndTimestampMs: int64(to), Matchers: &LabelMatchers{Matchers: ms}, + Limit: limit, }, nil } // FromLabelValuesRequest unpacks a LabelValuesRequest proto -func FromLabelValuesRequest(req *LabelValuesRequest) (string, int64, int64, []*labels.Matcher, error) { +func FromLabelValuesRequest(req *LabelValuesRequest) (string, int64, int64, *storage.LabelHints, []*labels.Matcher, error) { var err error + var hints *storage.LabelHints var matchers []*labels.Matcher if req.Matchers != nil { matchers, err = FromLabelMatchers(req.Matchers.Matchers) if err != nil { - return "", 0, 0, nil, err + return "", 0, 0, nil, nil, err } } - return req.LabelName, req.StartTimestampMs, req.EndTimestampMs, matchers, nil + if req.Limit > 0 { + hints = &storage.LabelHints{Limit: int(req.Limit)} + } + + return req.LabelName, req.StartTimestampMs, req.EndTimestampMs, hints, matchers, nil } // ToLabelNamesRequest builds a LabelNamesRequest proto -func ToLabelNamesRequest(from, to model.Time, matchers []*labels.Matcher) (*LabelNamesRequest, error) { +func ToLabelNamesRequest(from, to model.Time, hints *storage.LabelHints, matchers []*labels.Matcher) (*LabelNamesRequest, error) { ms, err := ToLabelMatchers(matchers) if err != nil { return nil, err } + var limit int64 + if hints != nil && hints.Limit > 0 { + limit = int64(hints.Limit) + } + return &LabelNamesRequest{ StartTimestampMs: int64(from), EndTimestampMs: int64(to), Matchers: &LabelMatchers{Matchers: ms}, + Limit: limit, }, nil } // FromLabelNamesRequest unpacks a LabelNamesRequest proto -func FromLabelNamesRequest(req *LabelNamesRequest) (int64, int64, []*labels.Matcher, error) { +func FromLabelNamesRequest(req *LabelNamesRequest) (int64, int64, *storage.LabelHints, []*labels.Matcher, error) { var err error + var hints *storage.LabelHints var matchers []*labels.Matcher - if req.Matchers != nil { matchers, err = FromLabelMatchers(req.Matchers.Matchers) if err != nil { - return 0, 0, nil, err + return 0, 0, nil, nil, err } } - return req.StartTimestampMs, req.EndTimestampMs, matchers, nil + if req.Limit != 0 { + hints = &storage.LabelHints{Limit: int(req.Limit)} + } + + return req.StartTimestampMs, req.EndTimestampMs, hints, matchers, nil } func ToActiveSeriesRequest(matchers []*labels.Matcher) (*ActiveSeriesRequest, error) { diff --git a/pkg/ingester/client/compat_test.go b/pkg/ingester/client/compat_test.go index 4f13346419..fd8d0af4d1 100644 --- a/pkg/ingester/client/compat_test.go +++ b/pkg/ingester/client/compat_test.go @@ -11,6 +11,7 @@ import ( "github.com/prometheus/common/model" "github.com/prometheus/prometheus/model/labels" + "github.com/prometheus/prometheus/storage" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -73,15 +74,17 @@ func TestLabelNamesRequest(t *testing.T) { mint, maxt = 0, 10 ) + hints := &storage.LabelHints{Limit: 10} matchers := []*labels.Matcher{labels.MustNewMatcher(labels.MatchEqual, "foo", "bar")} - req, err := ToLabelNamesRequest(mint, maxt, matchers) + req, err := ToLabelNamesRequest(mint, maxt, hints, matchers) require.NoError(t, err) - actualMinT, actualMaxT, actualMatchers, err := FromLabelNamesRequest(req) + actualMinT, actualMaxT, actualHints, actualMatchers, err := FromLabelNamesRequest(req) require.NoError(t, err) assert.Equal(t, int64(mint), actualMinT) assert.Equal(t, int64(maxt), actualMaxT) + assert.Equal(t, hints, actualHints) assert.Equal(t, matchers, actualMatchers) } diff --git a/pkg/ingester/client/ingester.pb.go b/pkg/ingester/client/ingester.pb.go index bbefc14b1e..0e243c4905 100644 --- a/pkg/ingester/client/ingester.pb.go +++ b/pkg/ingester/client/ingester.pb.go @@ -850,6 +850,7 @@ type LabelValuesRequest struct { StartTimestampMs int64 `protobuf:"varint,2,opt,name=start_timestamp_ms,json=startTimestampMs,proto3" json:"start_timestamp_ms,omitempty"` EndTimestampMs int64 `protobuf:"varint,3,opt,name=end_timestamp_ms,json=endTimestampMs,proto3" json:"end_timestamp_ms,omitempty"` Matchers *LabelMatchers `protobuf:"bytes,4,opt,name=matchers,proto3" json:"matchers,omitempty"` + Limit int64 `protobuf:"varint,5,opt,name=limit,proto3" json:"limit,omitempty"` } func (m *LabelValuesRequest) Reset() { *m = LabelValuesRequest{} } @@ -912,6 +913,13 @@ func (m *LabelValuesRequest) GetMatchers() *LabelMatchers { return nil } +func (m *LabelValuesRequest) GetLimit() int64 { + if m != nil { + return m.Limit + } + return 0 +} + type LabelValuesResponse struct { LabelValues []string `protobuf:"bytes,1,rep,name=label_values,json=labelValues,proto3" json:"label_values,omitempty"` } @@ -959,6 +967,7 @@ type LabelNamesRequest struct { StartTimestampMs int64 `protobuf:"varint,1,opt,name=start_timestamp_ms,json=startTimestampMs,proto3" json:"start_timestamp_ms,omitempty"` EndTimestampMs int64 `protobuf:"varint,2,opt,name=end_timestamp_ms,json=endTimestampMs,proto3" json:"end_timestamp_ms,omitempty"` Matchers *LabelMatchers `protobuf:"bytes,3,opt,name=matchers,proto3" json:"matchers,omitempty"` + Limit int64 `protobuf:"varint,4,opt,name=limit,proto3" json:"limit,omitempty"` } func (m *LabelNamesRequest) Reset() { *m = LabelNamesRequest{} } @@ -1014,6 +1023,13 @@ func (m *LabelNamesRequest) GetMatchers() *LabelMatchers { return nil } +func (m *LabelNamesRequest) GetLimit() int64 { + if m != nil { + return m.Limit + } + return 0 +} + type LabelNamesResponse struct { LabelNames []string `protobuf:"bytes,1,rep,name=label_names,json=labelNames,proto3" json:"label_names,omitempty"` } @@ -1781,117 +1797,118 @@ func init() { func init() { proto.RegisterFile("ingester.proto", fileDescriptor_60f6df4f3586b478) } var fileDescriptor_60f6df4f3586b478 = []byte{ - // 1748 bytes of a gzipped FileDescriptorProto + // 1761 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x58, 0x4b, 0x6f, 0x1b, 0xc9, 0x11, 0x66, 0xf3, 0xb5, 0x62, 0x91, 0x92, 0xa8, 0xa6, 0x24, 0x72, 0x47, 0xab, 0x91, 0x76, 0x02, 0xef, 0x32, 0x9b, 0x5d, 0xc9, 0xaf, 0x2c, 0xbc, 0x9b, 0x0d, 0x02, 0x4a, 0xa6, 0x2d, 0xda, 0xa6, 0x24, 0x0f, 0x25, 0xe7, 0x01, 0x18, 0x83, 0x21, 0xd9, 0x92, 0x06, 0xe2, 0x0c, 0x99, 0x99, 0xa6, - 0x61, 0xf9, 0x94, 0x53, 0xce, 0xf9, 0x01, 0x41, 0x80, 0xdc, 0x82, 0x1c, 0x73, 0xc9, 0x25, 0xc8, - 0xd9, 0x97, 0x00, 0xbe, 0xc5, 0x08, 0x10, 0x23, 0x96, 0x2f, 0xc9, 0xcd, 0x40, 0xfe, 0x40, 0x30, - 0xdd, 0x3d, 0x4f, 0x52, 0x12, 0x65, 0xc4, 0x3e, 0x91, 0x5d, 0xaf, 0xfe, 0xaa, 0xba, 0xba, 0xaa, - 0xa6, 0x61, 0xc6, 0xb0, 0x0e, 0x89, 0x43, 0x89, 0xbd, 0x36, 0xb0, 0xfb, 0xb4, 0x8f, 0xb3, 0x9d, - 0xbe, 0x4d, 0xc9, 0x53, 0xe9, 0xab, 0x43, 0x83, 0x1e, 0x0d, 0xdb, 0x6b, 0x9d, 0xbe, 0xb9, 0x7e, - 0xd8, 0x3f, 0xec, 0xaf, 0x33, 0x76, 0x7b, 0x78, 0xc0, 0x56, 0x6c, 0xc1, 0xfe, 0x71, 0x35, 0xe9, - 0x6a, 0x58, 0xdc, 0xd6, 0x0f, 0x74, 0x4b, 0x5f, 0x37, 0x0d, 0xd3, 0xb0, 0xd7, 0x07, 0xc7, 0x87, - 0xfc, 0xdf, 0xa0, 0xcd, 0x7f, 0xb9, 0x86, 0xf2, 0x6b, 0x04, 0xd2, 0x03, 0xbd, 0x4d, 0x7a, 0xdb, - 0xba, 0x49, 0x9c, 0x9a, 0xd5, 0x7d, 0xa4, 0xf7, 0x86, 0xc4, 0x51, 0xc9, 0x2f, 0x87, 0xc4, 0xa1, - 0xf8, 0x2a, 0x4c, 0x99, 0x3a, 0xed, 0x1c, 0x11, 0xdb, 0xa9, 0xa0, 0xd5, 0x54, 0x35, 0x7f, 0x7d, - 0x7e, 0x8d, 0x43, 0x5b, 0x63, 0x5a, 0x4d, 0xce, 0x54, 0x7d, 0x29, 0xfc, 0x35, 0x14, 0x3a, 0xfd, - 0xa1, 0x45, 0x35, 0x93, 0xd0, 0xa3, 0x7e, 0xb7, 0x92, 0x5c, 0x45, 0xd5, 0x99, 0xeb, 0x25, 0x4f, - 0x6b, 0xd3, 0xe5, 0x35, 0x19, 0x4b, 0xcd, 0x77, 0x82, 0x85, 0xb2, 0x05, 0x4b, 0x63, 0x71, 0x38, - 0x83, 0xbe, 0xe5, 0x10, 0xfc, 0x7d, 0xc8, 0x18, 0x94, 0x98, 0x1e, 0x8a, 0x52, 0x04, 0x85, 0x90, - 0xe5, 0x12, 0xca, 0x6d, 0xc8, 0x87, 0xa8, 0x78, 0x19, 0xa0, 0xe7, 0x2e, 0x35, 0x4b, 0x37, 0x49, - 0x05, 0xad, 0xa2, 0x6a, 0x4e, 0xcd, 0xf5, 0xbc, 0xad, 0xf0, 0x22, 0x64, 0x9f, 0x30, 0xc1, 0x4a, - 0x72, 0x35, 0x55, 0xcd, 0xa9, 0x62, 0xa5, 0xfc, 0x11, 0xc1, 0x72, 0xc8, 0xcc, 0xa6, 0x6e, 0x77, - 0x0d, 0x4b, 0xef, 0x19, 0xf4, 0xc4, 0x8b, 0xcd, 0x0a, 0xe4, 0x03, 0xc3, 0x1c, 0x58, 0x4e, 0x05, - 0xdf, 0xb2, 0x13, 0x09, 0x5e, 0xf2, 0x9d, 0x82, 0x97, 0x9a, 0x30, 0x78, 0xfb, 0x20, 0x9f, 0x85, - 0x55, 0xc4, 0xef, 0x46, 0x34, 0x7e, 0xcb, 0xa3, 0xf1, 0x6b, 0x11, 0xdb, 0x20, 0x0e, 0xdb, 0xc2, - 0x8b, 0xe4, 0x2b, 0x04, 0x0b, 0x63, 0x05, 0x2e, 0x0a, 0xaa, 0x0e, 0x98, 0xb3, 0x59, 0x30, 0x35, - 0x87, 0x69, 0x8a, 0x18, 0xdc, 0x38, 0x77, 0xeb, 0x11, 0x6a, 0xdd, 0xa2, 0xf6, 0x89, 0x5a, 0xec, - 0xc5, 0xc8, 0xd2, 0xe6, 0x28, 0x34, 0x26, 0x8a, 0x8b, 0x90, 0x3a, 0x26, 0x27, 0x02, 0x93, 0xfb, - 0x17, 0xcf, 0x43, 0x86, 0xe1, 0x60, 0xb9, 0x98, 0x56, 0xf9, 0xe2, 0xdb, 0xe4, 0x2d, 0xa4, 0xfc, - 0x1d, 0x41, 0xe1, 0xe1, 0x90, 0xd8, 0xfe, 0x99, 0x7e, 0x09, 0xd8, 0xa1, 0xba, 0x4d, 0x35, 0x6a, - 0x98, 0xc4, 0xa1, 0xba, 0x39, 0xd0, 0x58, 0xcc, 0x50, 0x35, 0xa5, 0x16, 0x19, 0x67, 0xcf, 0x63, - 0x34, 0x1d, 0x5c, 0x85, 0x22, 0xb1, 0xba, 0x51, 0xd9, 0x24, 0x93, 0x9d, 0x21, 0x56, 0x37, 0x2c, - 0x19, 0x4e, 0x85, 0xd4, 0x44, 0xa9, 0xf0, 0x63, 0x58, 0x72, 0xa8, 0x4d, 0x74, 0xd3, 0xb0, 0x0e, - 0xb5, 0xce, 0xd1, 0xd0, 0x3a, 0x76, 0xb4, 0xb6, 0xcb, 0xd4, 0x1c, 0xe3, 0x19, 0xa9, 0x74, 0x99, - 0x2b, 0x15, 0x5f, 0x64, 0x93, 0x49, 0x6c, 0xb8, 0x02, 0x2d, 0xe3, 0x19, 0x51, 0x7e, 0x8f, 0x60, - 0xbe, 0xfe, 0x94, 0x98, 0x83, 0x9e, 0x6e, 0x7f, 0x10, 0x0f, 0xaf, 0x8d, 0x78, 0xb8, 0x30, 0xce, - 0x43, 0x27, 0x70, 0x51, 0xf9, 0x0b, 0x82, 0x52, 0xad, 0x43, 0x8d, 0x27, 0xe2, 0xfc, 0xde, 0xbd, - 0xe8, 0xfc, 0x08, 0xd2, 0xf4, 0x64, 0x40, 0x44, 0xb1, 0xf9, 0xdc, 0x93, 0x1e, 0x63, 0x7c, 0x4d, - 0xfc, 0xee, 0x9d, 0x0c, 0x88, 0xca, 0x94, 0x94, 0xaf, 0x21, 0x1f, 0x22, 0x62, 0x80, 0x6c, 0xab, - 0xae, 0x36, 0xea, 0xad, 0x62, 0x02, 0x2f, 0x41, 0x79, 0xbb, 0xb6, 0xd7, 0x78, 0x54, 0xd7, 0xb6, - 0x1a, 0xad, 0xbd, 0x9d, 0xbb, 0x6a, 0xad, 0xa9, 0x09, 0x26, 0x52, 0xee, 0xc3, 0xb4, 0x88, 0xac, - 0xb8, 0x63, 0xdf, 0x02, 0xb0, 0x40, 0xf1, 0x6c, 0x8f, 0x22, 0x1f, 0xb4, 0xd7, 0xdc, 0x68, 0x71, - 0x2c, 0x1b, 0xe9, 0xe7, 0xaf, 0x56, 0x12, 0x6a, 0x48, 0x5a, 0xf9, 0x6f, 0x12, 0x4a, 0xcc, 0x5a, - 0x8b, 0x9d, 0xa8, 0x6f, 0xf3, 0x27, 0x90, 0xe7, 0x87, 0x1f, 0x36, 0x5a, 0xf6, 0x1c, 0x0c, 0x4c, - 0xb2, 0xf3, 0x17, 0x76, 0xc3, 0x1a, 0x31, 0x50, 0xc9, 0xcb, 0x80, 0xc2, 0xf7, 0xa0, 0x18, 0xe4, - 0xa0, 0xb0, 0xc0, 0xcf, 0xf6, 0x63, 0x0f, 0x41, 0x08, 0x73, 0xc4, 0xcc, 0xac, 0xaf, 0xc8, 0xc9, - 0xf8, 0x26, 0x94, 0x0d, 0x47, 0x73, 0x93, 0xa9, 0x7f, 0x20, 0x6c, 0x69, 0x5c, 0xa6, 0x92, 0x5e, - 0x45, 0xd5, 0x29, 0xb5, 0x64, 0x38, 0x75, 0xab, 0xbb, 0x73, 0xc0, 0xe5, 0xb9, 0x49, 0xfc, 0x18, - 0xca, 0x71, 0x04, 0xe2, 0x32, 0x54, 0x32, 0x0c, 0xc8, 0xca, 0x99, 0x40, 0xc4, 0x8d, 0xe0, 0x70, - 0x16, 0x62, 0x70, 0x38, 0x53, 0xf9, 0x2d, 0x82, 0xb9, 0x11, 0x45, 0x7c, 0x00, 0x59, 0x56, 0x6e, - 0xe2, 0xcd, 0x66, 0xd0, 0xe6, 0xf9, 0xb7, 0xab, 0x1b, 0xf6, 0xc6, 0x37, 0xae, 0xdd, 0x7f, 0xbc, - 0x5a, 0xb9, 0x36, 0x49, 0xcb, 0xe5, 0x7a, 0xb5, 0xae, 0x3e, 0xa0, 0xc4, 0x56, 0x85, 0x75, 0xb7, - 0x81, 0x30, 0x5f, 0x34, 0x56, 0xca, 0xc5, 0xbd, 0x02, 0x46, 0x62, 0xb5, 0x50, 0x31, 0xa0, 0x7c, - 0x86, 0x5b, 0xf8, 0x53, 0x28, 0x88, 0x70, 0x18, 0x56, 0x97, 0x3c, 0x65, 0x17, 0x38, 0xad, 0xe6, - 0x39, 0xad, 0xe1, 0x92, 0xf0, 0x0f, 0x20, 0x2b, 0x42, 0xc5, 0x4f, 0x7d, 0xda, 0x6f, 0x23, 0xa1, - 0x5c, 0x11, 0x22, 0x4a, 0x0b, 0x16, 0x62, 0xe5, 0xe2, 0xff, 0x90, 0xd4, 0x7f, 0x45, 0x80, 0xc3, - 0x0d, 0x5a, 0xdc, 0xef, 0x0b, 0x9a, 0xc7, 0xf8, 0x0a, 0x95, 0xbc, 0x44, 0x85, 0x4a, 0x5d, 0x58, - 0xa1, 0xdc, 0x94, 0x9b, 0xa0, 0x42, 0xdd, 0x82, 0x52, 0x04, 0xbf, 0x88, 0xc9, 0xa7, 0x50, 0x08, - 0xb5, 0x37, 0xaf, 0xf5, 0xe7, 0x83, 0x1e, 0xe5, 0x28, 0xbf, 0x43, 0x30, 0x17, 0xcc, 0x33, 0x1f, - 0xb6, 0xf8, 0x4e, 0xe4, 0xda, 0x0f, 0xc5, 0xd1, 0x08, 0x7c, 0xc2, 0xb3, 0x8b, 0x66, 0x1a, 0xe5, - 0x1e, 0x14, 0xf7, 0x1d, 0x62, 0xb7, 0xa8, 0x4e, 0x7d, 0xaf, 0xe2, 0x53, 0x0b, 0x9a, 0x70, 0x6a, - 0xf9, 0x33, 0x82, 0xb9, 0x90, 0x31, 0x01, 0xe1, 0x8a, 0x37, 0x0c, 0x1b, 0x7d, 0x4b, 0xb3, 0x75, - 0xca, 0x33, 0x04, 0xa9, 0xd3, 0x3e, 0x55, 0xd5, 0x29, 0x71, 0x93, 0xc8, 0x1a, 0x9a, 0xc1, 0x68, - 0xe1, 0xa6, 0x7f, 0xce, 0x1a, 0x7a, 0x77, 0xf8, 0x4b, 0xc0, 0xfa, 0xc0, 0xd0, 0x62, 0x96, 0x52, - 0xcc, 0x52, 0x51, 0x1f, 0x18, 0x8d, 0x88, 0xb1, 0x35, 0x28, 0xd9, 0xc3, 0x1e, 0x89, 0x8b, 0xa7, - 0x99, 0xf8, 0x9c, 0xcb, 0x8a, 0xc8, 0x2b, 0x8f, 0xa1, 0xe4, 0x02, 0x6f, 0xdc, 0x8e, 0x42, 0x2f, - 0xc3, 0x47, 0x43, 0x87, 0xd8, 0x9a, 0xd1, 0x15, 0x59, 0x9d, 0x75, 0x97, 0x8d, 0x2e, 0xfe, 0x0a, - 0xd2, 0x5d, 0x9d, 0xea, 0x0c, 0x66, 0xa8, 0x78, 0x8e, 0x38, 0xaf, 0x32, 0x31, 0xe5, 0x2e, 0x60, - 0x97, 0xe5, 0x44, 0xad, 0x5f, 0x83, 0x8c, 0xe3, 0x12, 0xc4, 0x25, 0x5c, 0x0a, 0x5b, 0x89, 0x21, - 0x51, 0xb9, 0xa4, 0xf2, 0x27, 0x04, 0x72, 0x93, 0x50, 0xdb, 0xe8, 0x38, 0x77, 0xfa, 0x76, 0x34, - 0x15, 0xde, 0x73, 0x4a, 0xde, 0x82, 0x82, 0x97, 0x6b, 0x9a, 0x43, 0xe8, 0xf9, 0x33, 0x41, 0xde, - 0x13, 0x6d, 0x11, 0xaa, 0xdc, 0x87, 0x95, 0x33, 0x31, 0x8b, 0x50, 0x54, 0x21, 0x6b, 0x32, 0x11, - 0x11, 0x8b, 0x62, 0x50, 0x90, 0xb8, 0xaa, 0x2a, 0xf8, 0xca, 0x00, 0x16, 0x85, 0xb1, 0x26, 0xa1, - 0xba, 0x1b, 0x5d, 0xcf, 0xf1, 0x79, 0xc8, 0xf4, 0x0c, 0xd3, 0xa0, 0xcc, 0xd7, 0x39, 0x95, 0x2f, - 0x5c, 0x07, 0xd9, 0x1f, 0x6d, 0x40, 0x6c, 0x4d, 0xec, 0x91, 0x64, 0x02, 0x33, 0x8c, 0xbe, 0x4b, - 0x6c, 0x6e, 0xcf, 0xfd, 0x70, 0x10, 0xfc, 0x14, 0x3f, 0x6b, 0xb1, 0xe3, 0x0e, 0x94, 0x47, 0x76, - 0x14, 0xb0, 0x6f, 0xc2, 0x94, 0x29, 0x68, 0x02, 0x78, 0x25, 0x0e, 0xdc, 0xd7, 0xf1, 0x25, 0x95, - 0x0e, 0xcc, 0x47, 0x07, 0x99, 0xcb, 0x06, 0xc1, 0xad, 0x57, 0xed, 0x61, 0xe7, 0x98, 0x50, 0xbf, - 0xd3, 0xa4, 0xdc, 0x66, 0xc1, 0x69, 0xbc, 0xd5, 0xfc, 0x07, 0xc1, 0x6c, 0x6c, 0x9a, 0x70, 0x63, - 0x71, 0x60, 0xf7, 0x4d, 0xcd, 0xfb, 0x36, 0x0d, 0xf2, 0x7a, 0xc6, 0xa5, 0x37, 0x04, 0xb9, 0xd1, - 0x0d, 0x27, 0x7e, 0x32, 0x92, 0xf8, 0x41, 0x2b, 0x4d, 0xbd, 0xd7, 0x56, 0x1a, 0xf4, 0xba, 0xf4, - 0xc5, 0xbd, 0xee, 0x6f, 0x08, 0x32, 0xdc, 0xc3, 0xf7, 0x95, 0xfc, 0x12, 0x4c, 0x11, 0xab, 0xd3, - 0xef, 0x1a, 0xd6, 0x21, 0xcb, 0x8e, 0x8c, 0xea, 0xaf, 0xf1, 0xae, 0xa8, 0x05, 0x6e, 0x71, 0x29, - 0x6c, 0x7c, 0x27, 0x7c, 0xbf, 0x39, 0x91, 0xef, 0xfb, 0x96, 0xa3, 0x1f, 0x90, 0x8d, 0x13, 0x4a, - 0x5a, 0x3d, 0xa3, 0xe3, 0x95, 0x8b, 0x1a, 0x4c, 0x47, 0xae, 0xc9, 0xe5, 0x07, 0x68, 0x45, 0x83, - 0x42, 0x98, 0x83, 0xaf, 0x88, 0x81, 0x9a, 0x97, 0xf2, 0x39, 0x4f, 0x9b, 0xb1, 0x83, 0xd1, 0x19, - 0x63, 0x48, 0xb3, 0x1e, 0xce, 0x0f, 0x9d, 0xfd, 0x0f, 0xbe, 0xb6, 0xf8, 0xb5, 0xe0, 0x8b, 0x2f, - 0xaa, 0x90, 0x0f, 0xf5, 0x01, 0x3c, 0x0d, 0xb9, 0xc6, 0xb6, 0xd6, 0xac, 0x37, 0x77, 0xd4, 0x9f, - 0x17, 0x13, 0xee, 0xcc, 0x5d, 0xdb, 0x74, 0xe7, 0xec, 0x22, 0xfa, 0xe2, 0x1e, 0xe4, 0xfc, 0x6d, - 0x70, 0x0e, 0x32, 0xf5, 0x87, 0xfb, 0xb5, 0x07, 0xc5, 0x84, 0xab, 0xb2, 0xbd, 0xb3, 0xa7, 0xf1, - 0x25, 0xc2, 0xb3, 0x90, 0x57, 0xeb, 0x77, 0xeb, 0x3f, 0xd3, 0x9a, 0xb5, 0xbd, 0xcd, 0xad, 0x62, - 0x12, 0x63, 0x98, 0xe1, 0x84, 0xed, 0x1d, 0x41, 0x4b, 0x5d, 0xff, 0xe7, 0x47, 0x30, 0xe5, 0xa5, - 0x29, 0xfe, 0x06, 0xd2, 0xbb, 0x43, 0xe7, 0x08, 0x2f, 0x06, 0x39, 0xf8, 0x53, 0xdb, 0xa0, 0x44, - 0x14, 0x04, 0xa9, 0x3c, 0x42, 0xe7, 0x17, 0x4d, 0x49, 0xe0, 0xdb, 0x90, 0x0f, 0x0d, 0x62, 0x78, - 0x3e, 0x32, 0x74, 0x7a, 0xfa, 0x4b, 0x63, 0x46, 0xd1, 0xc0, 0xc6, 0x55, 0x84, 0x77, 0x60, 0x86, - 0xb1, 0xbc, 0x41, 0xcb, 0xc1, 0x9f, 0x78, 0x2a, 0xe3, 0x3e, 0xd5, 0xa4, 0xe5, 0x33, 0xb8, 0x3e, - 0xac, 0xad, 0xe8, 0x4b, 0x87, 0x34, 0xee, 0x51, 0x24, 0x0e, 0x6e, 0xcc, 0x3c, 0xa3, 0x24, 0x70, - 0x1d, 0x20, 0x98, 0x06, 0xf0, 0xc7, 0x11, 0xe1, 0xf0, 0x04, 0x23, 0x49, 0xe3, 0x58, 0xbe, 0x99, - 0x0d, 0xc8, 0xf9, 0x3d, 0x0d, 0x57, 0xc6, 0xb4, 0x39, 0x6e, 0xe4, 0xec, 0x06, 0xa8, 0x24, 0xf0, - 0x1d, 0x28, 0xd4, 0x7a, 0xbd, 0x49, 0xcc, 0x48, 0x61, 0x8e, 0x13, 0xb7, 0xd3, 0xf3, 0xeb, 0x70, - 0xbc, 0x8d, 0xe0, 0xcf, 0xfc, 0x7c, 0x3e, 0xb7, 0x37, 0x4a, 0x9f, 0x5f, 0x28, 0xe7, 0xef, 0xb6, - 0x07, 0xb3, 0xb1, 0xaa, 0x8f, 0xe5, 0x98, 0x76, 0xac, 0x01, 0x49, 0x2b, 0x67, 0xf2, 0x7d, 0xab, - 0x6d, 0x31, 0x7f, 0x46, 0x1f, 0xc5, 0xb0, 0x32, 0x7a, 0x08, 0xf1, 0x97, 0x3b, 0xe9, 0x7b, 0xe7, - 0xca, 0x84, 0xb2, 0xf2, 0x18, 0x16, 0xc7, 0xbf, 0x1d, 0xe1, 0x2b, 0x63, 0x72, 0x66, 0xf4, 0x1d, - 0x4c, 0xfa, 0xec, 0x22, 0xb1, 0xd0, 0x66, 0x4d, 0x28, 0x84, 0x7b, 0x19, 0x5e, 0x3a, 0xe7, 0x53, - 0x5d, 0xfa, 0x64, 0x3c, 0x33, 0x30, 0xb7, 0xf1, 0xdd, 0x8b, 0xd7, 0x72, 0xe2, 0xe5, 0x6b, 0x39, - 0xf1, 0xf6, 0xb5, 0x8c, 0x7e, 0x75, 0x2a, 0xa3, 0x3f, 0x9c, 0xca, 0xe8, 0xf9, 0xa9, 0x8c, 0x5e, - 0x9c, 0xca, 0xe8, 0x5f, 0xa7, 0x32, 0xfa, 0xf7, 0xa9, 0x9c, 0x78, 0x7b, 0x2a, 0xa3, 0xdf, 0xbc, - 0x91, 0x13, 0x2f, 0xde, 0xc8, 0x89, 0x97, 0x6f, 0xe4, 0xc4, 0x2f, 0xb2, 0x9d, 0x9e, 0x41, 0x2c, - 0xda, 0xce, 0xb2, 0x27, 0xd0, 0x1b, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x69, 0x8a, 0xb2, 0x58, - 0x7d, 0x15, 0x00, 0x00, + 0x61, 0xf9, 0x94, 0x53, 0xce, 0xf9, 0x01, 0xb9, 0xe4, 0x16, 0xe4, 0x18, 0x04, 0xc8, 0x25, 0x3f, + 0xc0, 0x97, 0x00, 0x3e, 0x04, 0x88, 0x11, 0x20, 0x46, 0x2c, 0x5f, 0x92, 0x9b, 0x81, 0xfc, 0x81, + 0x60, 0xba, 0x7b, 0x9e, 0xa4, 0x44, 0xc9, 0x88, 0x7d, 0x22, 0xbb, 0x5e, 0xfd, 0x55, 0x75, 0x75, + 0x55, 0x4d, 0xc3, 0x8c, 0x61, 0x1d, 0x12, 0x87, 0x12, 0x7b, 0x6d, 0x60, 0xf7, 0x69, 0x1f, 0x67, + 0x3b, 0x7d, 0x9b, 0x92, 0xa7, 0xd2, 0x57, 0x87, 0x06, 0x3d, 0x1a, 0xb6, 0xd7, 0x3a, 0x7d, 0x73, + 0xfd, 0xb0, 0x7f, 0xd8, 0x5f, 0x67, 0xec, 0xf6, 0xf0, 0x80, 0xad, 0xd8, 0x82, 0xfd, 0xe3, 0x6a, + 0xd2, 0xd5, 0xb0, 0xb8, 0xad, 0x1f, 0xe8, 0x96, 0xbe, 0x6e, 0x1a, 0xa6, 0x61, 0xaf, 0x0f, 0x8e, + 0x0f, 0xf9, 0xbf, 0x41, 0x9b, 0xff, 0x72, 0x0d, 0xe5, 0xd7, 0x08, 0xa4, 0x07, 0x7a, 0x9b, 0xf4, + 0xb6, 0x75, 0x93, 0x38, 0x35, 0xab, 0xfb, 0x48, 0xef, 0x0d, 0x89, 0xa3, 0x92, 0x5f, 0x0e, 0x89, + 0x43, 0xf1, 0x55, 0x98, 0x32, 0x75, 0xda, 0x39, 0x22, 0xb6, 0x53, 0x41, 0xab, 0xa9, 0x6a, 0xfe, + 0xfa, 0xfc, 0x1a, 0x87, 0xb6, 0xc6, 0xb4, 0x9a, 0x9c, 0xa9, 0xfa, 0x52, 0xf8, 0x6b, 0x28, 0x74, + 0xfa, 0x43, 0x8b, 0x6a, 0x26, 0xa1, 0x47, 0xfd, 0x6e, 0x25, 0xb9, 0x8a, 0xaa, 0x33, 0xd7, 0x4b, + 0x9e, 0xd6, 0xa6, 0xcb, 0x6b, 0x32, 0x96, 0x9a, 0xef, 0x04, 0x0b, 0x65, 0x0b, 0x96, 0xc6, 0xe2, + 0x70, 0x06, 0x7d, 0xcb, 0x21, 0xf8, 0xfb, 0x90, 0x31, 0x28, 0x31, 0x3d, 0x14, 0xa5, 0x08, 0x0a, + 0x21, 0xcb, 0x25, 0x94, 0xdb, 0x90, 0x0f, 0x51, 0xf1, 0x32, 0x40, 0xcf, 0x5d, 0x6a, 0x96, 0x6e, + 0x92, 0x0a, 0x5a, 0x45, 0xd5, 0x9c, 0x9a, 0xeb, 0x79, 0x5b, 0xe1, 0x45, 0xc8, 0x3e, 0x61, 0x82, + 0x95, 0xe4, 0x6a, 0xaa, 0x9a, 0x53, 0xc5, 0x4a, 0xf9, 0x03, 0x82, 0xe5, 0x90, 0x99, 0x4d, 0xdd, + 0xee, 0x1a, 0x96, 0xde, 0x33, 0xe8, 0x89, 0x17, 0x9b, 0x15, 0xc8, 0x07, 0x86, 0x39, 0xb0, 0x9c, + 0x0a, 0xbe, 0x65, 0x27, 0x12, 0xbc, 0xe4, 0x3b, 0x05, 0x2f, 0x75, 0xc1, 0xe0, 0xed, 0x83, 0x7c, + 0x16, 0x56, 0x11, 0xbf, 0x1b, 0xd1, 0xf8, 0x2d, 0x8f, 0xc6, 0xaf, 0x45, 0x6c, 0x83, 0x38, 0x6c, + 0x0b, 0x2f, 0x92, 0xaf, 0x10, 0x2c, 0x8c, 0x15, 0x98, 0x14, 0x54, 0x1d, 0x30, 0x67, 0xb3, 0x60, + 0x6a, 0x0e, 0xd3, 0x14, 0x31, 0xb8, 0x71, 0xee, 0xd6, 0x23, 0xd4, 0xba, 0x45, 0xed, 0x13, 0xb5, + 0xd8, 0x8b, 0x91, 0xa5, 0xcd, 0x51, 0x68, 0x4c, 0x14, 0x17, 0x21, 0x75, 0x4c, 0x4e, 0x04, 0x26, + 0xf7, 0x2f, 0x9e, 0x87, 0x0c, 0xc3, 0xc1, 0x72, 0x31, 0xad, 0xf2, 0xc5, 0xb7, 0xc9, 0x5b, 0x48, + 0xf9, 0x3b, 0x82, 0xc2, 0xc3, 0x21, 0xb1, 0xfd, 0x33, 0xfd, 0x12, 0xb0, 0x43, 0x75, 0x9b, 0x6a, + 0xd4, 0x30, 0x89, 0x43, 0x75, 0x73, 0xa0, 0xb1, 0x98, 0xa1, 0x6a, 0x4a, 0x2d, 0x32, 0xce, 0x9e, + 0xc7, 0x68, 0x3a, 0xb8, 0x0a, 0x45, 0x62, 0x75, 0xa3, 0xb2, 0x49, 0x26, 0x3b, 0x43, 0xac, 0x6e, + 0x58, 0x32, 0x9c, 0x0a, 0xa9, 0x0b, 0xa5, 0xc2, 0x8f, 0x61, 0xc9, 0xa1, 0x36, 0xd1, 0x4d, 0xc3, + 0x3a, 0xd4, 0x3a, 0x47, 0x43, 0xeb, 0xd8, 0xd1, 0xda, 0x2e, 0x53, 0x73, 0x8c, 0x67, 0xa4, 0xd2, + 0x65, 0xae, 0x54, 0x7c, 0x91, 0x4d, 0x26, 0xb1, 0xe1, 0x0a, 0xb4, 0x8c, 0x67, 0x44, 0xf9, 0x1d, + 0x82, 0xf9, 0xfa, 0x53, 0x62, 0x0e, 0x7a, 0xba, 0xfd, 0x41, 0x3c, 0xbc, 0x36, 0xe2, 0xe1, 0xc2, + 0x38, 0x0f, 0x9d, 0xc0, 0x45, 0xe5, 0x2f, 0x08, 0x4a, 0xb5, 0x0e, 0x35, 0x9e, 0x88, 0xf3, 0x7b, + 0xf7, 0xa2, 0xf3, 0x23, 0x48, 0xd3, 0x93, 0x01, 0x11, 0xc5, 0xe6, 0x73, 0x4f, 0x7a, 0x8c, 0xf1, + 0x35, 0xf1, 0xbb, 0x77, 0x32, 0x20, 0x2a, 0x53, 0x52, 0xbe, 0x86, 0x7c, 0x88, 0x88, 0x01, 0xb2, + 0xad, 0xba, 0xda, 0xa8, 0xb7, 0x8a, 0x09, 0xbc, 0x04, 0xe5, 0xed, 0xda, 0x5e, 0xe3, 0x51, 0x5d, + 0xdb, 0x6a, 0xb4, 0xf6, 0x76, 0xee, 0xaa, 0xb5, 0xa6, 0x26, 0x98, 0x48, 0xb9, 0x0f, 0xd3, 0x22, + 0xb2, 0xe2, 0x8e, 0x7d, 0x0b, 0xc0, 0x02, 0xc5, 0xb3, 0x3d, 0x8a, 0x7c, 0xd0, 0x5e, 0x73, 0xa3, + 0xc5, 0xb1, 0x6c, 0xa4, 0x9f, 0xbf, 0x5a, 0x49, 0xa8, 0x21, 0x69, 0xe5, 0xbf, 0x49, 0x28, 0x31, + 0x6b, 0x2d, 0x76, 0xa2, 0xbe, 0xcd, 0x9f, 0x40, 0x9e, 0x1f, 0x7e, 0xd8, 0x68, 0xd9, 0x73, 0x30, + 0x30, 0xc9, 0xce, 0x5f, 0xd8, 0x0d, 0x6b, 0xc4, 0x40, 0x25, 0x2f, 0x03, 0x0a, 0xdf, 0x83, 0x62, + 0x90, 0x83, 0xc2, 0x02, 0x3f, 0xdb, 0x8f, 0x3d, 0x04, 0x21, 0xcc, 0x11, 0x33, 0xb3, 0xbe, 0x22, + 0x27, 0xe3, 0x9b, 0x50, 0x36, 0x1c, 0xcd, 0x4d, 0xa6, 0xfe, 0x81, 0xb0, 0xa5, 0x71, 0x99, 0x4a, + 0x7a, 0x15, 0x55, 0xa7, 0xd4, 0x92, 0xe1, 0xd4, 0xad, 0xee, 0xce, 0x01, 0x97, 0xe7, 0x26, 0xf1, + 0x63, 0x28, 0xc7, 0x11, 0x88, 0xcb, 0x50, 0xc9, 0x30, 0x20, 0x2b, 0x67, 0x02, 0x11, 0x37, 0x82, + 0xc3, 0x59, 0x88, 0xc1, 0xe1, 0x4c, 0xe5, 0xb7, 0x08, 0xe6, 0x46, 0x14, 0xf1, 0x01, 0x64, 0x59, + 0xb9, 0x89, 0x37, 0x9b, 0x41, 0x9b, 0xe7, 0xdf, 0xae, 0x6e, 0xd8, 0x1b, 0xdf, 0xb8, 0x76, 0xff, + 0xf1, 0x6a, 0xe5, 0xda, 0x45, 0x5a, 0x2e, 0xd7, 0xab, 0x75, 0xf5, 0x01, 0x25, 0xb6, 0x2a, 0xac, + 0xbb, 0x0d, 0x84, 0xf9, 0xa2, 0xb1, 0x52, 0x2e, 0xee, 0x15, 0x30, 0x12, 0xab, 0x85, 0x8a, 0x01, + 0xe5, 0x33, 0xdc, 0xc2, 0x9f, 0x42, 0x41, 0x84, 0xc3, 0xb0, 0xba, 0xe4, 0x29, 0xbb, 0xc0, 0x69, + 0x35, 0xcf, 0x69, 0x0d, 0x97, 0x84, 0x7f, 0x00, 0x59, 0x11, 0x2a, 0x7e, 0xea, 0xd3, 0x7e, 0x1b, + 0x09, 0xe5, 0x8a, 0x10, 0x51, 0x5a, 0xb0, 0x10, 0x2b, 0x17, 0xff, 0x87, 0xa4, 0xfe, 0x1b, 0x02, + 0x1c, 0x6e, 0xd0, 0xe2, 0x7e, 0x4f, 0x68, 0x1e, 0xe3, 0x2b, 0x54, 0xf2, 0x12, 0x15, 0x2a, 0x35, + 0xb1, 0x42, 0xb9, 0x29, 0x37, 0xb9, 0x42, 0xb9, 0x9d, 0xa3, 0x67, 0x98, 0x06, 0xad, 0x64, 0x98, + 0x45, 0xbe, 0x50, 0x6e, 0x41, 0x29, 0xe2, 0x95, 0x88, 0xd4, 0xa7, 0x50, 0x08, 0x35, 0x3d, 0x6f, + 0x20, 0xc8, 0x07, 0x9d, 0xcb, 0x51, 0xfe, 0x84, 0x60, 0x2e, 0x98, 0x72, 0x3e, 0x6c, 0x49, 0xbe, + 0x9c, 0xc3, 0xe9, 0xb0, 0xc3, 0x3f, 0x14, 0xc7, 0x28, 0x50, 0x0b, 0x7f, 0x27, 0xcd, 0x3f, 0xca, + 0x3d, 0x28, 0xee, 0x3b, 0xc4, 0x6e, 0x51, 0x9d, 0xfa, 0xbe, 0xc6, 0x27, 0x1c, 0x74, 0xc1, 0x09, + 0xe7, 0xcf, 0x08, 0xe6, 0x42, 0xc6, 0x04, 0x84, 0x2b, 0xde, 0xe0, 0x6c, 0xf4, 0x2d, 0xcd, 0xd6, + 0x29, 0xcf, 0x26, 0xa4, 0x4e, 0xfb, 0x54, 0x55, 0xa7, 0xc4, 0x4d, 0x38, 0x6b, 0x68, 0x06, 0x63, + 0x88, 0x7b, 0x55, 0x72, 0xd6, 0xd0, 0xbb, 0xef, 0x5f, 0x02, 0xd6, 0x07, 0x86, 0x16, 0xb3, 0x94, + 0x62, 0x96, 0x8a, 0xfa, 0xc0, 0x68, 0x44, 0x8c, 0xad, 0x41, 0xc9, 0x1e, 0xf6, 0x48, 0x5c, 0x3c, + 0xcd, 0xc4, 0xe7, 0x5c, 0x56, 0x44, 0x5e, 0x79, 0x0c, 0x25, 0x17, 0x78, 0xe3, 0x76, 0x14, 0x7a, + 0x19, 0x3e, 0x1a, 0x3a, 0xc4, 0xd6, 0x8c, 0xae, 0xb8, 0x01, 0x59, 0x77, 0xd9, 0xe8, 0xe2, 0xaf, + 0x20, 0xdd, 0xd5, 0xa9, 0xce, 0x60, 0x86, 0x0a, 0xed, 0x88, 0xf3, 0x2a, 0x13, 0x53, 0xee, 0x02, + 0x76, 0x59, 0x4e, 0xd4, 0xfa, 0x35, 0xc8, 0x38, 0x2e, 0x41, 0x5c, 0xd8, 0xa5, 0xb0, 0x95, 0x18, + 0x12, 0x95, 0x4b, 0x2a, 0x7f, 0x44, 0x20, 0x37, 0x09, 0xb5, 0x8d, 0x8e, 0x73, 0xa7, 0x6f, 0x47, + 0x13, 0xe4, 0x3d, 0x27, 0xea, 0x2d, 0x28, 0x78, 0x19, 0xa8, 0x39, 0x84, 0x9e, 0x3f, 0x3f, 0xe4, + 0x3d, 0xd1, 0x16, 0xa1, 0xca, 0x7d, 0x58, 0x39, 0x13, 0xb3, 0x08, 0x45, 0x15, 0xb2, 0x26, 0x13, + 0x11, 0xb1, 0x28, 0x06, 0xc5, 0x8b, 0xab, 0xaa, 0x82, 0xaf, 0x0c, 0x60, 0x51, 0x18, 0x6b, 0x12, + 0xaa, 0xbb, 0xd1, 0xf5, 0x1c, 0xf7, 0xaf, 0x85, 0xeb, 0xeb, 0x9c, 0xb8, 0x16, 0xae, 0x83, 0xec, + 0x8f, 0x36, 0x20, 0xb6, 0x26, 0xf6, 0x48, 0x32, 0x81, 0x19, 0x46, 0xdf, 0x25, 0x36, 0xb7, 0xe7, + 0x7e, 0x64, 0x08, 0x7e, 0x8a, 0x9f, 0xb5, 0xd8, 0x71, 0x07, 0xca, 0x23, 0x3b, 0x0a, 0xd8, 0x37, + 0x61, 0xca, 0x14, 0x34, 0x01, 0xbc, 0x12, 0x07, 0xee, 0xeb, 0xf8, 0x92, 0x4a, 0x07, 0xe6, 0xa3, + 0x43, 0xcf, 0x65, 0x83, 0xe0, 0x56, 0xb1, 0xf6, 0xb0, 0x73, 0x4c, 0xa8, 0xdf, 0x95, 0x52, 0x6e, + 0x63, 0xe1, 0x34, 0xde, 0x96, 0xfe, 0x83, 0x60, 0x36, 0x36, 0x79, 0xb8, 0xb1, 0x38, 0xb0, 0xfb, + 0xa6, 0xe6, 0x7d, 0xc7, 0x06, 0x79, 0x3d, 0xe3, 0xd2, 0x1b, 0x82, 0xdc, 0xe8, 0x86, 0x13, 0x3f, + 0x19, 0x49, 0xfc, 0xa0, 0xed, 0xa6, 0xde, 0x6b, 0xdb, 0x0d, 0xfa, 0x62, 0x7a, 0x72, 0x5f, 0xfc, + 0x2b, 0x82, 0x0c, 0xf7, 0xf0, 0x7d, 0x25, 0xbf, 0x04, 0x53, 0xc4, 0xea, 0xf4, 0xbb, 0x86, 0x75, + 0xc8, 0xb2, 0x23, 0xa3, 0xfa, 0x6b, 0xbc, 0x2b, 0x6a, 0x81, 0x5b, 0x5c, 0x0a, 0x1b, 0xdf, 0x09, + 0xdf, 0x6f, 0x5e, 0xc8, 0xf7, 0x7d, 0xcb, 0xd1, 0x0f, 0xc8, 0xc6, 0x09, 0x25, 0xad, 0x9e, 0xd1, + 0xf1, 0xca, 0x45, 0x0d, 0xa6, 0x23, 0xd7, 0xe4, 0xf2, 0xc3, 0xb6, 0xa2, 0x41, 0x21, 0xcc, 0xc1, + 0x57, 0xc4, 0xf0, 0xcd, 0x4b, 0xf9, 0x9c, 0xa7, 0xcd, 0xd8, 0xc1, 0x98, 0x8d, 0x31, 0xa4, 0x59, + 0xbf, 0xe7, 0x87, 0xce, 0xfe, 0x07, 0x5f, 0x66, 0xfc, 0x5a, 0xf0, 0xc5, 0x17, 0x55, 0xc8, 0x87, + 0xfa, 0x00, 0x9e, 0x86, 0x5c, 0x63, 0x5b, 0x6b, 0xd6, 0x9b, 0x3b, 0xea, 0xcf, 0x8b, 0x09, 0x77, + 0x3e, 0xaf, 0x6d, 0xba, 0x33, 0x79, 0x11, 0x7d, 0x71, 0x0f, 0x72, 0xfe, 0x36, 0x38, 0x07, 0x99, + 0xfa, 0xc3, 0xfd, 0xda, 0x83, 0x62, 0xc2, 0x55, 0xd9, 0xde, 0xd9, 0xd3, 0xf8, 0x12, 0xe1, 0x59, + 0xc8, 0xab, 0xf5, 0xbb, 0xf5, 0x9f, 0x69, 0xcd, 0xda, 0xde, 0xe6, 0x56, 0x31, 0x89, 0x31, 0xcc, + 0x70, 0xc2, 0xf6, 0x8e, 0xa0, 0xa5, 0xae, 0xff, 0xf3, 0x23, 0x98, 0xf2, 0xd2, 0x14, 0x7f, 0x03, + 0xe9, 0xdd, 0xa1, 0x73, 0x84, 0x17, 0x83, 0x1c, 0xfc, 0xa9, 0x6d, 0x50, 0x22, 0x0a, 0x82, 0x54, + 0x1e, 0xa1, 0xf3, 0x8b, 0xa6, 0x24, 0xf0, 0x6d, 0xc8, 0x87, 0x86, 0x36, 0x3c, 0x1f, 0x19, 0x50, + 0x3d, 0xfd, 0xa5, 0x31, 0x63, 0x6b, 0x60, 0xe3, 0x2a, 0xc2, 0x3b, 0x30, 0xc3, 0x58, 0xde, 0x50, + 0xe6, 0xe0, 0x4f, 0x3c, 0x95, 0x71, 0x9f, 0x75, 0xd2, 0xf2, 0x19, 0x5c, 0x1f, 0xd6, 0x56, 0xf4, + 0x55, 0x44, 0x1a, 0xf7, 0x80, 0x12, 0x07, 0x37, 0x66, 0xca, 0x51, 0x12, 0xb8, 0x0e, 0x10, 0x4c, + 0x03, 0xf8, 0xe3, 0x88, 0x70, 0x78, 0xae, 0x91, 0xa4, 0x71, 0x2c, 0xdf, 0xcc, 0x06, 0xe4, 0xfc, + 0x9e, 0x86, 0x2b, 0x63, 0xda, 0x1c, 0x37, 0x72, 0x76, 0x03, 0x54, 0x12, 0xf8, 0x0e, 0x14, 0x6a, + 0xbd, 0xde, 0x45, 0xcc, 0x48, 0x61, 0x8e, 0x13, 0xb7, 0xd3, 0xf3, 0xeb, 0x70, 0xbc, 0x8d, 0xe0, + 0xcf, 0xfc, 0x7c, 0x3e, 0xb7, 0x37, 0x4a, 0x9f, 0x4f, 0x94, 0xf3, 0x77, 0xdb, 0x83, 0xd9, 0x58, + 0xd5, 0xc7, 0x72, 0x4c, 0x3b, 0xd6, 0x80, 0xa4, 0x95, 0x33, 0xf9, 0xbe, 0xd5, 0xb6, 0x98, 0x4a, + 0xa3, 0x0f, 0x68, 0x58, 0x19, 0x3d, 0x84, 0xf8, 0x2b, 0x9f, 0xf4, 0xbd, 0x73, 0x65, 0x42, 0x59, + 0x79, 0x0c, 0x8b, 0xe3, 0xdf, 0x99, 0xf0, 0x95, 0x31, 0x39, 0x33, 0xfa, 0x66, 0x26, 0x7d, 0x36, + 0x49, 0x2c, 0xb4, 0x59, 0x13, 0x0a, 0xe1, 0x5e, 0x86, 0x97, 0xce, 0xf9, 0xac, 0x97, 0x3e, 0x19, + 0xcf, 0x0c, 0xcc, 0x6d, 0x7c, 0xf7, 0xe2, 0xb5, 0x9c, 0x78, 0xf9, 0x5a, 0x4e, 0xbc, 0x7d, 0x2d, + 0xa3, 0x5f, 0x9d, 0xca, 0xe8, 0xf7, 0xa7, 0x32, 0x7a, 0x7e, 0x2a, 0xa3, 0x17, 0xa7, 0x32, 0xfa, + 0xd7, 0xa9, 0x8c, 0xfe, 0x7d, 0x2a, 0x27, 0xde, 0x9e, 0xca, 0xe8, 0x37, 0x6f, 0xe4, 0xc4, 0x8b, + 0x37, 0x72, 0xe2, 0xe5, 0x1b, 0x39, 0xf1, 0x8b, 0x6c, 0xa7, 0x67, 0x10, 0x8b, 0xb6, 0xb3, 0xec, + 0xb9, 0xf4, 0xc6, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x7d, 0xe4, 0x26, 0xdf, 0xa9, 0x15, 0x00, + 0x00, } func (x CountMethod) String() string { @@ -2423,6 +2440,9 @@ func (this *LabelValuesRequest) Equal(that interface{}) bool { if !this.Matchers.Equal(that1.Matchers) { return false } + if this.Limit != that1.Limit { + return false + } return true } func (this *LabelValuesResponse) Equal(that interface{}) bool { @@ -2482,6 +2502,9 @@ func (this *LabelNamesRequest) Equal(that interface{}) bool { if !this.Matchers.Equal(that1.Matchers) { return false } + if this.Limit != that1.Limit { + return false + } return true } func (this *LabelNamesResponse) Equal(that interface{}) bool { @@ -3150,7 +3173,7 @@ func (this *LabelValuesRequest) GoString() string { if this == nil { return "nil" } - s := make([]string, 0, 8) + s := make([]string, 0, 9) s = append(s, "&client.LabelValuesRequest{") s = append(s, "LabelName: "+fmt.Sprintf("%#v", this.LabelName)+",\n") s = append(s, "StartTimestampMs: "+fmt.Sprintf("%#v", this.StartTimestampMs)+",\n") @@ -3158,6 +3181,7 @@ func (this *LabelValuesRequest) GoString() string { if this.Matchers != nil { s = append(s, "Matchers: "+fmt.Sprintf("%#v", this.Matchers)+",\n") } + s = append(s, "Limit: "+fmt.Sprintf("%#v", this.Limit)+",\n") s = append(s, "}") return strings.Join(s, "") } @@ -3175,13 +3199,14 @@ func (this *LabelNamesRequest) GoString() string { if this == nil { return "nil" } - s := make([]string, 0, 7) + s := make([]string, 0, 8) s = append(s, "&client.LabelNamesRequest{") s = append(s, "StartTimestampMs: "+fmt.Sprintf("%#v", this.StartTimestampMs)+",\n") s = append(s, "EndTimestampMs: "+fmt.Sprintf("%#v", this.EndTimestampMs)+",\n") if this.Matchers != nil { s = append(s, "Matchers: "+fmt.Sprintf("%#v", this.Matchers)+",\n") } + s = append(s, "Limit: "+fmt.Sprintf("%#v", this.Limit)+",\n") s = append(s, "}") return strings.Join(s, "") } @@ -4629,6 +4654,11 @@ func (m *LabelValuesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Limit != 0 { + i = encodeVarintIngester(dAtA, i, uint64(m.Limit)) + i-- + dAtA[i] = 0x28 + } if m.Matchers != nil { { size, err := m.Matchers.MarshalToSizedBuffer(dAtA[:i]) @@ -4713,6 +4743,11 @@ func (m *LabelNamesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Limit != 0 { + i = encodeVarintIngester(dAtA, i, uint64(m.Limit)) + i-- + dAtA[i] = 0x20 + } if m.Matchers != nil { { size, err := m.Matchers.MarshalToSizedBuffer(dAtA[:i]) @@ -5639,6 +5674,9 @@ func (m *LabelValuesRequest) Size() (n int) { l = m.Matchers.Size() n += 1 + l + sovIngester(uint64(l)) } + if m.Limit != 0 { + n += 1 + sovIngester(uint64(m.Limit)) + } return n } @@ -5673,6 +5711,9 @@ func (m *LabelNamesRequest) Size() (n int) { l = m.Matchers.Size() n += 1 + l + sovIngester(uint64(l)) } + if m.Limit != 0 { + n += 1 + sovIngester(uint64(m.Limit)) + } return n } @@ -6184,6 +6225,7 @@ func (this *LabelValuesRequest) String() string { `StartTimestampMs:` + fmt.Sprintf("%v", this.StartTimestampMs) + `,`, `EndTimestampMs:` + fmt.Sprintf("%v", this.EndTimestampMs) + `,`, `Matchers:` + strings.Replace(this.Matchers.String(), "LabelMatchers", "LabelMatchers", 1) + `,`, + `Limit:` + fmt.Sprintf("%v", this.Limit) + `,`, `}`, }, "") return s @@ -6206,6 +6248,7 @@ func (this *LabelNamesRequest) String() string { `StartTimestampMs:` + fmt.Sprintf("%v", this.StartTimestampMs) + `,`, `EndTimestampMs:` + fmt.Sprintf("%v", this.EndTimestampMs) + `,`, `Matchers:` + strings.Replace(this.Matchers.String(), "LabelMatchers", "LabelMatchers", 1) + `,`, + `Limit:` + fmt.Sprintf("%v", this.Limit) + `,`, `}`, }, "") return s @@ -8248,6 +8291,25 @@ func (m *LabelValuesRequest) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Limit", wireType) + } + m.Limit = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowIngester + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Limit |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipIngester(dAtA[iNdEx:]) @@ -8460,6 +8522,25 @@ func (m *LabelNamesRequest) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Limit", wireType) + } + m.Limit = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowIngester + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Limit |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipIngester(dAtA[iNdEx:]) diff --git a/pkg/ingester/client/ingester.proto b/pkg/ingester/client/ingester.proto index b2dd18b2a9..8f4ca944be 100644 --- a/pkg/ingester/client/ingester.proto +++ b/pkg/ingester/client/ingester.proto @@ -141,6 +141,7 @@ message LabelValuesRequest { int64 start_timestamp_ms = 2; int64 end_timestamp_ms = 3; LabelMatchers matchers = 4; + int64 limit = 5; } message LabelValuesResponse { @@ -151,6 +152,7 @@ message LabelNamesRequest { int64 start_timestamp_ms = 1; int64 end_timestamp_ms = 2; LabelMatchers matchers = 3; + int64 limit = 4; } message LabelNamesResponse { diff --git a/pkg/ingester/ingester.go b/pkg/ingester/ingester.go index 2407e64d3c..415531d9a8 100644 --- a/pkg/ingester/ingester.go +++ b/pkg/ingester/ingester.go @@ -1717,7 +1717,7 @@ func (i *Ingester) LabelValues(ctx context.Context, req *client.LabelValuesReque } defer func() { finishReadRequest(err) }() - labelName, startTimestampMs, endTimestampMs, matchers, err := client.FromLabelValuesRequest(req) + labelName, startTimestampMs, endTimestampMs, hints, matchers, err := client.FromLabelValuesRequest(req) if err != nil { return nil, err } @@ -1744,12 +1744,18 @@ func (i *Ingester) LabelValues(ctx context.Context, req *client.LabelValuesReque } defer q.Close() - hints := &storage.LabelHints{} vals, _, err := q.LabelValues(ctx, labelName, hints, matchers...) if err != nil { return nil, err } + // Besides we are passing the hints to q.LabelValues, we also limit the number of returned values here + // because LabelQuerier can resolve the labelValues using different instance and then joining the results, + // so we want to apply the limit at the end. + if hints != nil && hints.Limit > 0 && len(vals) > hints.Limit { + vals = vals[:hints.Limit] + } + // The label value strings are sometimes pointing to memory mapped file // regions that may become unmapped anytime after Querier.Close is called. // So we copy those strings. @@ -1789,7 +1795,7 @@ func (i *Ingester) LabelNames(ctx context.Context, req *client.LabelNamesRequest return &client.LabelNamesResponse{}, nil } - mint, maxt, matchers, err := client.FromLabelNamesRequest(req) + mint, maxt, hints, matchers, err := client.FromLabelNamesRequest(req) if err != nil { return nil, err } @@ -1803,12 +1809,18 @@ func (i *Ingester) LabelNames(ctx context.Context, req *client.LabelNamesRequest // Log the actual matchers passed down to TSDB. This can be useful for troubleshooting purposes. spanlog.DebugLog("num_matchers", len(matchers), "matchers", util.LabelMatchersToString(matchers)) - hints := &storage.LabelHints{} names, _, err := q.LabelNames(ctx, hints, matchers...) if err != nil { return nil, err } + // Besides we are passing the hints to q.LabelNames, we also limit the number of returned values here + // because LabelQuerier can resolve the labelNames using different instance and then joining the results, + // so we want to apply the limit at the end. + if hints != nil && hints.Limit > 0 && len(names) > hints.Limit { + names = names[:hints.Limit] + } + return &client.LabelNamesResponse{ LabelNames: names, }, nil diff --git a/pkg/ingester/ingester_test.go b/pkg/ingester/ingester_test.go index 4d47e7fabe..d7eec71766 100644 --- a/pkg/ingester/ingester_test.go +++ b/pkg/ingester/ingester_test.go @@ -4057,7 +4057,63 @@ func Test_Ingester_LabelNames(t *testing.T) { labels.MustNewMatcher(labels.MatchNotEqual, "route", "get_user"), } - req, err := client.ToLabelNamesRequest(0, model.Latest, matchers) + req, err := client.ToLabelNamesRequest(0, model.Latest, nil, matchers) + require.NoError(t, err) + + // Get label names + res, err := i.LabelNames(ctx, req) + require.NoError(t, err) + assert.ElementsMatch(t, expected, res.LabelNames) + }) + + t.Run("without matchers, with limit", func(t *testing.T) { + expected := []string{"__name__", "route"} + + hints := &storage.LabelHints{Limit: 2} + + req, err := client.ToLabelNamesRequest(0, model.Latest, hints, nil) + require.NoError(t, err) + + // Get label names + res, err := i.LabelNames(ctx, req) + require.NoError(t, err) + assert.ElementsMatch(t, expected, res.LabelNames) + }) + + t.Run("without matchers, with limit set to 0", func(t *testing.T) { + expected := []string{"__name__", "status", "route"} + + hints := &storage.LabelHints{Limit: 0} + + req, err := client.ToLabelNamesRequest(0, model.Latest, hints, nil) + require.NoError(t, err) + + // Get label names + res, err := i.LabelNames(ctx, req) + require.NoError(t, err) + assert.ElementsMatch(t, expected, res.LabelNames) + }) + + t.Run("without matchers, with limit set to same number of items returned", func(t *testing.T) { + expected := []string{"__name__", "status", "route"} + + hints := &storage.LabelHints{Limit: 3} + + req, err := client.ToLabelNamesRequest(0, model.Latest, hints, nil) + require.NoError(t, err) + + // Get label names + res, err := i.LabelNames(ctx, req) + require.NoError(t, err) + assert.ElementsMatch(t, expected, res.LabelNames) + }) + + t.Run("without matchers, with limit set to a higher number than the items returned", func(t *testing.T) { + expected := []string{"__name__", "status", "route"} + + hints := &storage.LabelHints{Limit: 10} + + req, err := client.ToLabelNamesRequest(0, model.Latest, hints, nil) require.NoError(t, err) // Get label names @@ -4130,6 +4186,26 @@ func Test_Ingester_LabelValues(t *testing.T) { assert.ElementsMatch(t, expectedValues, res.LabelValues) } + expectedLimit := map[int][]string{ + 0: {"test_1", "test_2"}, // no limit + 1: {"test_1"}, + 2: {"test_1", "test_2"}, // limit equals to the number of results + 4: {"test_1", "test_2"}, // limit greater than the number of results + } + t.Run("with limit", func(t *testing.T) { + for limit, expectedValues := range expectedLimit { + hints := &storage.LabelHints{Limit: limit} + + req, err := client.ToLabelValuesRequest("__name__", 0, model.Latest, hints, nil) + require.NoError(t, err) + + // Get label names + res, err := i.LabelValues(ctx, req) + require.NoError(t, err) + assert.ElementsMatch(t, expectedValues, res.LabelValues) + } + }) + t.Run("limited due to resource utilization", func(t *testing.T) { origLimiter := i.utilizationBasedLimiter t.Cleanup(func() { diff --git a/pkg/querier/blocks_store_queryable.go b/pkg/querier/blocks_store_queryable.go index f91ad99f87..d34e3e2d56 100644 --- a/pkg/querier/blocks_store_queryable.go +++ b/pkg/querier/blocks_store_queryable.go @@ -342,7 +342,7 @@ func (q *blocksStoreQuerier) Select(ctx context.Context, _ bool, sp *storage.Sel return q.selectSorted(ctx, sp, tenantID, matchers...) } -func (q *blocksStoreQuerier) LabelNames(ctx context.Context, _ *storage.LabelHints, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) { +func (q *blocksStoreQuerier) LabelNames(ctx context.Context, hints *storage.LabelHints, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) { spanLog, ctx := spanlogger.NewWithLogger(ctx, q.logger, "blocksStoreQuerier.LabelNames") defer spanLog.Span.Finish() @@ -369,7 +369,7 @@ func (q *blocksStoreQuerier) LabelNames(ctx context.Context, _ *storage.LabelHin ) queryF := func(clients map[BlocksStoreClient][]ulid.ULID, minT, maxT int64) ([]ulid.ULID, error) { - nameSets, warnings, queriedBlocks, err := q.fetchLabelNamesFromStore(ctx, clients, minT, maxT, tenantID, convertedMatchers) + nameSets, warnings, queriedBlocks, err := q.fetchLabelNamesFromStore(ctx, clients, minT, maxT, tenantID, hints, convertedMatchers) if err != nil { return nil, err } @@ -387,7 +387,7 @@ func (q *blocksStoreQuerier) LabelNames(ctx context.Context, _ *storage.LabelHin return util.MergeSlices(resNameSets...), resWarnings, nil } -func (q *blocksStoreQuerier) LabelValues(ctx context.Context, name string, _ *storage.LabelHints, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) { +func (q *blocksStoreQuerier) LabelValues(ctx context.Context, name string, hints *storage.LabelHints, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) { spanLog, ctx := spanlogger.NewWithLogger(ctx, q.logger, "blocksStoreQuerier.LabelValues") defer spanLog.Span.Finish() @@ -413,7 +413,7 @@ func (q *blocksStoreQuerier) LabelValues(ctx context.Context, name string, _ *st ) queryF := func(clients map[BlocksStoreClient][]ulid.ULID, minT, maxT int64) ([]ulid.ULID, error) { - valueSets, warnings, queriedBlocks, err := q.fetchLabelValuesFromStore(ctx, name, clients, minT, maxT, tenantID, matchers...) + valueSets, warnings, queriedBlocks, err := q.fetchLabelValuesFromStore(ctx, name, clients, minT, maxT, tenantID, hints, matchers...) if err != nil { return nil, err } @@ -1009,6 +1009,7 @@ func (q *blocksStoreQuerier) fetchLabelNamesFromStore( minT int64, maxT int64, tenantID string, + hints *storage.LabelHints, matchers []storepb.LabelMatcher, ) ([][]string, annotations.Annotations, []ulid.ULID, error) { var ( @@ -1024,7 +1025,7 @@ func (q *blocksStoreQuerier) fetchLabelNamesFromStore( // Concurrently fetch series from all clients. for c, blockIDs := range clients { g.Go(func() error { - req, err := createLabelNamesRequest(minT, maxT, blockIDs, matchers) + req, err := createLabelNamesRequest(minT, maxT, blockIDs, hints, matchers) if err != nil { return errors.Wrapf(err, "failed to create label names request") } @@ -1088,6 +1089,7 @@ func (q *blocksStoreQuerier) fetchLabelValuesFromStore( minT int64, maxT int64, tenantID string, + hints *storage.LabelHints, matchers ...*labels.Matcher, ) ([][]string, annotations.Annotations, []ulid.ULID, error) { var ( @@ -1103,7 +1105,7 @@ func (q *blocksStoreQuerier) fetchLabelValuesFromStore( // Concurrently fetch series from all clients. for c, blockIDs := range clients { g.Go(func() error { - req, err := createLabelValuesRequest(minT, maxT, name, blockIDs, matchers...) + req, err := createLabelValuesRequest(minT, maxT, name, blockIDs, hints, matchers...) if err != nil { return errors.Wrapf(err, "failed to create label values request") } @@ -1193,15 +1195,20 @@ func createSeriesRequest(minT, maxT int64, matchers []storepb.LabelMatcher, skip }, nil } -func createLabelNamesRequest(minT, maxT int64, blockIDs []ulid.ULID, matchers []storepb.LabelMatcher) (*storepb.LabelNamesRequest, error) { +func createLabelNamesRequest(minT, maxT int64, blockIDs []ulid.ULID, hints *storage.LabelHints, matchers []storepb.LabelMatcher) (*storepb.LabelNamesRequest, error) { + var limit int64 + if hints != nil && hints.Limit > 0 { + limit = int64(hints.Limit) + } req := &storepb.LabelNamesRequest{ Start: minT, End: maxT, Matchers: matchers, + Limit: limit, } // Selectively query only specific blocks. - hints := &hintspb.LabelNamesRequestHints{ + requestHints := &hintspb.LabelNamesRequestHints{ BlockMatchers: []storepb.LabelMatcher{ { Type: storepb.LabelMatcher_RE, @@ -1211,26 +1218,32 @@ func createLabelNamesRequest(minT, maxT int64, blockIDs []ulid.ULID, matchers [] }, } - anyHints, err := types.MarshalAny(hints) + anyRequestHints, err := types.MarshalAny(requestHints) if err != nil { return nil, errors.Wrapf(err, "failed to marshal label names request hints") } - req.Hints = anyHints + req.Hints = anyRequestHints return req, nil } -func createLabelValuesRequest(minT, maxT int64, label string, blockIDs []ulid.ULID, matchers ...*labels.Matcher) (*storepb.LabelValuesRequest, error) { +func createLabelValuesRequest(minT, maxT int64, label string, blockIDs []ulid.ULID, hints *storage.LabelHints, matchers ...*labels.Matcher) (*storepb.LabelValuesRequest, error) { + var limit int64 + if hints != nil && hints.Limit > 0 { + limit = int64(hints.Limit) + } + req := &storepb.LabelValuesRequest{ Start: minT, End: maxT, Label: label, Matchers: convertMatchersToLabelMatcher(matchers), + Limit: limit, } // Selectively query only specific blocks. - hints := &hintspb.LabelValuesRequestHints{ + requestHints := &hintspb.LabelValuesRequestHints{ BlockMatchers: []storepb.LabelMatcher{ { Type: storepb.LabelMatcher_RE, @@ -1240,12 +1253,12 @@ func createLabelValuesRequest(minT, maxT int64, label string, blockIDs []ulid.UL }, } - anyHints, err := types.MarshalAny(hints) + anyRequestHints, err := types.MarshalAny(requestHints) if err != nil { return nil, errors.Wrapf(err, "failed to marshal label values request hints") } - req.Hints = anyHints + req.Hints = anyRequestHints return req, nil } diff --git a/pkg/querier/distributor_queryable.go b/pkg/querier/distributor_queryable.go index 2fa028dd91..f442a541f3 100644 --- a/pkg/querier/distributor_queryable.go +++ b/pkg/querier/distributor_queryable.go @@ -35,8 +35,8 @@ import ( type Distributor interface { QueryStream(ctx context.Context, queryMetrics *stats.QueryMetrics, from, to model.Time, matchers ...*labels.Matcher) (client.CombinedQueryStreamResponse, error) QueryExemplars(ctx context.Context, from, to model.Time, matchers ...[]*labels.Matcher) (*client.ExemplarQueryResponse, error) - LabelValuesForLabelName(ctx context.Context, from, to model.Time, label model.LabelName, matchers ...*labels.Matcher) ([]string, error) - LabelNames(ctx context.Context, from model.Time, to model.Time, matchers ...*labels.Matcher) ([]string, error) + LabelValuesForLabelName(ctx context.Context, from, to model.Time, label model.LabelName, hints *storage.LabelHints, matchers ...*labels.Matcher) ([]string, error) + LabelNames(ctx context.Context, from model.Time, to model.Time, hints *storage.LabelHints, matchers ...*labels.Matcher) ([]string, error) MetricsForLabelMatchers(ctx context.Context, from, through model.Time, matchers ...*labels.Matcher) ([]labels.Labels, error) MetricsMetadata(ctx context.Context, req *client.MetricsMetadataRequest) ([]scrape.MetricMetadata, error) LabelNamesAndValues(ctx context.Context, matchers []*labels.Matcher, countMethod cardinality.CountMethod) (*client.LabelNamesAndValuesResponse, error) @@ -203,7 +203,7 @@ func (q *distributorQuerier) streamingSelect(ctx context.Context, minT, maxT int return storage.NewMergeSeriesSet(sets, 0, storage.ChainedSeriesMerge) } -func (q *distributorQuerier) LabelValues(ctx context.Context, name string, _ *storage.LabelHints, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) { +func (q *distributorQuerier) LabelValues(ctx context.Context, name string, hints *storage.LabelHints, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) { spanLog, ctx := spanlogger.NewWithLogger(ctx, q.logger, "distributorQuerier.LabelValues") defer spanLog.Span.Finish() @@ -221,12 +221,12 @@ func (q *distributorQuerier) LabelValues(ctx context.Context, name string, _ *st now := time.Now().UnixMilli() q.mint = clampMinTime(spanLog, q.mint, now, -queryIngestersWithin, "query ingesters within") - lvs, err := q.distributor.LabelValuesForLabelName(ctx, model.Time(q.mint), model.Time(q.maxt), model.LabelName(name), matchers...) + lvs, err := q.distributor.LabelValuesForLabelName(ctx, model.Time(q.mint), model.Time(q.maxt), model.LabelName(name), hints, matchers...) return lvs, nil, err } -func (q *distributorQuerier) LabelNames(ctx context.Context, _ *storage.LabelHints, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) { +func (q *distributorQuerier) LabelNames(ctx context.Context, hints *storage.LabelHints, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) { spanLog, ctx := spanlogger.NewWithLogger(ctx, q.logger, "distributorQuerier.LabelNames") defer spanLog.Span.Finish() @@ -244,7 +244,7 @@ func (q *distributorQuerier) LabelNames(ctx context.Context, _ *storage.LabelHin now := time.Now().UnixMilli() q.mint = clampMinTime(spanLog, q.mint, now, -queryIngestersWithin, "query ingesters within") - ln, err := q.distributor.LabelNames(ctx, model.Time(q.mint), model.Time(q.maxt), matchers...) + ln, err := q.distributor.LabelNames(ctx, model.Time(q.mint), model.Time(q.maxt), hints, matchers...) return ln, nil, err } diff --git a/pkg/querier/distributor_queryable_test.go b/pkg/querier/distributor_queryable_test.go index 28a7775190..d0a0eda562 100644 --- a/pkg/querier/distributor_queryable_test.go +++ b/pkg/querier/distributor_queryable_test.go @@ -644,20 +644,34 @@ func TestDistributorQuerier_LabelNames(t *testing.T) { labelNames := []string{"foo", "job"} t.Run("with matchers", func(t *testing.T) { - t.Run("queryLabelNamesWithMatchers=true", func(t *testing.T) { - d := &mockDistributor{} - d.On("LabelNames", mock.Anything, model.Time(mint), model.Time(maxt), someMatchers). - Return(labelNames, nil) - ctx := user.InjectOrgID(context.Background(), "0") - queryable := NewDistributorQueryable(d, newMockConfigProvider(0), nil, log.NewNopLogger()) - querier, err := queryable.Querier(mint, maxt) - require.NoError(t, err) + d := &mockDistributor{} + d.On("LabelNames", mock.Anything, model.Time(mint), model.Time(maxt), &storage.LabelHints{}, someMatchers). + Return(labelNames, nil) + ctx := user.InjectOrgID(context.Background(), "0") + queryable := NewDistributorQueryable(d, newMockConfigProvider(0), nil, log.NewNopLogger()) + querier, err := queryable.Querier(mint, maxt) + require.NoError(t, err) - names, warnings, err := querier.LabelNames(ctx, &storage.LabelHints{}, someMatchers...) - require.NoError(t, err) - assert.Empty(t, warnings) - assert.Equal(t, labelNames, names) - }) + names, warnings, err := querier.LabelNames(ctx, &storage.LabelHints{}, someMatchers...) + require.NoError(t, err) + assert.Empty(t, warnings) + assert.Equal(t, labelNames, names) + }) + + t.Run("with matchers and limit", func(t *testing.T) { + hints := &storage.LabelHints{Limit: 1} + d := &mockDistributor{} + d.On("LabelNames", mock.Anything, model.Time(mint), model.Time(maxt), hints, someMatchers). + Return(labelNames[:hints.Limit], nil) + ctx := user.InjectOrgID(context.Background(), "0") + queryable := NewDistributorQueryable(d, newMockConfigProvider(0), nil, log.NewNopLogger()) + querier, err := queryable.Querier(mint, maxt) + require.NoError(t, err) + + names, warnings, err := querier.LabelNames(ctx, hints, someMatchers...) + require.NoError(t, err) + assert.Empty(t, warnings) + assert.Equal(t, labelNames[:hints.Limit], names) }) } @@ -837,12 +851,12 @@ func (m *mockDistributor) QueryStream(ctx context.Context, queryMetrics *stats.Q args := m.Called(ctx, queryMetrics, from, to, matchers) return args.Get(0).(client.CombinedQueryStreamResponse), args.Error(1) } -func (m *mockDistributor) LabelValuesForLabelName(ctx context.Context, from, to model.Time, lbl model.LabelName, matchers ...*labels.Matcher) ([]string, error) { - args := m.Called(ctx, from, to, lbl, matchers) +func (m *mockDistributor) LabelValuesForLabelName(ctx context.Context, from, to model.Time, lbl model.LabelName, hints *storage.LabelHints, matchers ...*labels.Matcher) ([]string, error) { + args := m.Called(ctx, from, to, lbl, hints, matchers) return args.Get(0).([]string), args.Error(1) } -func (m *mockDistributor) LabelNames(ctx context.Context, from, to model.Time, matchers ...*labels.Matcher) ([]string, error) { - args := m.Called(ctx, from, to, matchers) +func (m *mockDistributor) LabelNames(ctx context.Context, from, to model.Time, hints *storage.LabelHints, matchers ...*labels.Matcher) ([]string, error) { + args := m.Called(ctx, from, to, hints, matchers) return args.Get(0).([]string), args.Error(1) } func (m *mockDistributor) MetricsForLabelMatchers(ctx context.Context, from, to model.Time, matchers ...*labels.Matcher) ([]labels.Labels, error) { diff --git a/pkg/querier/querier_test.go b/pkg/querier/querier_test.go index 5945b07985..9856b13746 100644 --- a/pkg/querier/querier_test.go +++ b/pkg/querier/querier_test.go @@ -966,8 +966,9 @@ func TestQuerier_ValidateQueryTimeRange_MaxQueryLookback(t *testing.T) { matchers := []*labels.Matcher{ labels.MustNewMatcher(labels.MatchNotEqual, "route", "get_user"), } + hints := &storage.LabelHints{Limit: 1} distributor := &mockDistributor{} - distributor.On("LabelNames", mock.Anything, mock.Anything, mock.Anything, matchers).Return([]string{}, nil) + distributor.On("LabelNames", mock.Anything, mock.Anything, mock.Anything, hints, matchers).Return([]string{}, nil) queryable, _, _, err := New(cfg, overrides, distributor, nil, nil, logger, nil) require.NoError(t, err) @@ -975,7 +976,7 @@ func TestQuerier_ValidateQueryTimeRange_MaxQueryLookback(t *testing.T) { q, err := queryable.Querier(util.TimeToMillis(testData.queryStartTime), util.TimeToMillis(testData.queryEndTime)) require.NoError(t, err) - _, _, err = q.LabelNames(ctx, &storage.LabelHints{}, matchers...) + _, _, err = q.LabelNames(ctx, hints, matchers...) require.NoError(t, err) if !testData.expectedSkipped { @@ -986,7 +987,8 @@ func TestQuerier_ValidateQueryTimeRange_MaxQueryLookback(t *testing.T) { args := distributor.Calls[0].Arguments assert.InDelta(t, util.TimeToMillis(testData.expectedMetadataStartTime), int64(args.Get(1).(model.Time)), delta) assert.InDelta(t, util.TimeToMillis(testData.expectedMetadataEndTime), int64(args.Get(2).(model.Time)), delta) - assert.Equal(t, matchers, args.Get(3).([]*labels.Matcher)) + assert.Equal(t, hints, args.Get(3).(*storage.LabelHints)) + assert.Equal(t, matchers, args.Get(4).([]*labels.Matcher)) } else { // Ensure no query has been executed (because skipped). assert.Len(t, distributor.Calls, 0) @@ -994,8 +996,9 @@ func TestQuerier_ValidateQueryTimeRange_MaxQueryLookback(t *testing.T) { }) t.Run("label values", func(t *testing.T) { + hints := &storage.LabelHints{Limit: 1} distributor := &mockDistributor{} - distributor.On("LabelValuesForLabelName", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]string{}, nil) + distributor.On("LabelValuesForLabelName", mock.Anything, mock.Anything, mock.Anything, mock.Anything, hints, mock.Anything).Return([]string{}, nil) queryable, _, _, err := New(cfg, overrides, distributor, nil, nil, logger, nil) require.NoError(t, err) @@ -1003,7 +1006,7 @@ func TestQuerier_ValidateQueryTimeRange_MaxQueryLookback(t *testing.T) { q, err := queryable.Querier(util.TimeToMillis(testData.queryStartTime), util.TimeToMillis(testData.queryEndTime)) require.NoError(t, err) - _, _, err = q.LabelValues(ctx, labels.MetricName, &storage.LabelHints{}) + _, _, err = q.LabelValues(ctx, labels.MetricName, hints) require.NoError(t, err) if !testData.expectedSkipped { @@ -1013,6 +1016,7 @@ func TestQuerier_ValidateQueryTimeRange_MaxQueryLookback(t *testing.T) { assert.Equal(t, "LabelValuesForLabelName", distributor.Calls[0].Method) assert.InDelta(t, util.TimeToMillis(testData.expectedMetadataStartTime), int64(distributor.Calls[0].Arguments.Get(1).(model.Time)), delta) assert.InDelta(t, util.TimeToMillis(testData.expectedMetadataEndTime), int64(distributor.Calls[0].Arguments.Get(2).(model.Time)), delta) + assert.Equal(t, hints, distributor.Calls[0].Arguments.Get(4).(*storage.LabelHints)) } else { // Ensure no query has been executed (because skipped). assert.Len(t, distributor.Calls, 0) @@ -1174,10 +1178,10 @@ func (m *errDistributor) QueryStream(context.Context, *stats.QueryMetrics, model func (m *errDistributor) QueryExemplars(context.Context, model.Time, model.Time, ...[]*labels.Matcher) (*client.ExemplarQueryResponse, error) { return nil, errDistributorError } -func (m *errDistributor) LabelValuesForLabelName(context.Context, model.Time, model.Time, model.LabelName, ...*labels.Matcher) ([]string, error) { +func (m *errDistributor) LabelValuesForLabelName(context.Context, model.Time, model.Time, model.LabelName, *storage.LabelHints, ...*labels.Matcher) ([]string, error) { return nil, errDistributorError } -func (m *errDistributor) LabelNames(context.Context, model.Time, model.Time, ...*labels.Matcher) ([]string, error) { +func (m *errDistributor) LabelNames(context.Context, model.Time, model.Time, *storage.LabelHints, ...*labels.Matcher) ([]string, error) { return nil, errDistributorError } func (m *errDistributor) MetricsForLabelMatchers(context.Context, model.Time, model.Time, ...*labels.Matcher) ([]labels.Labels, error) { @@ -1214,11 +1218,11 @@ func (d *emptyDistributor) QueryExemplars(context.Context, model.Time, model.Tim return nil, nil } -func (d *emptyDistributor) LabelValuesForLabelName(context.Context, model.Time, model.Time, model.LabelName, ...*labels.Matcher) ([]string, error) { +func (d *emptyDistributor) LabelValuesForLabelName(context.Context, model.Time, model.Time, model.LabelName, *storage.LabelHints, ...*labels.Matcher) ([]string, error) { return nil, nil } -func (d *emptyDistributor) LabelNames(context.Context, model.Time, model.Time, ...*labels.Matcher) ([]string, error) { +func (d *emptyDistributor) LabelNames(context.Context, model.Time, model.Time, *storage.LabelHints, ...*labels.Matcher) ([]string, error) { return nil, nil } diff --git a/pkg/querier/tenantfederation/merge_queryable_test.go b/pkg/querier/tenantfederation/merge_queryable_test.go index 9a6cf5cf9b..fbc98a0d06 100644 --- a/pkg/querier/tenantfederation/merge_queryable_test.go +++ b/pkg/querier/tenantfederation/merge_queryable_test.go @@ -169,7 +169,7 @@ func (m mockTenantQuerier) Select(ctx context.Context, _ bool, _ *storage.Select // LabelValues implements the storage.LabelQuerier interface. // The mockTenantQuerier returns all a sorted slice of all label values and does not support reducing the result set with matchers. -func (m mockTenantQuerier) LabelValues(ctx context.Context, name string, _ *storage.LabelHints, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) { +func (m mockTenantQuerier) LabelValues(ctx context.Context, name string, hints *storage.LabelHints, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) { tenantID, err := tenant.TenantID(ctx) if err != nil { return nil, nil, err @@ -198,6 +198,11 @@ func (m mockTenantQuerier) LabelValues(ctx context.Context, name string, _ *stor results = append(results, k) } slices.Sort(results) + + if hints != nil && hints.Limit > 0 && len(results) > hints.Limit { + results = results[:hints.Limit] + } + return results, warnings, nil } @@ -205,7 +210,7 @@ func (m mockTenantQuerier) LabelValues(ctx context.Context, name string, _ *stor // It returns a sorted slice of all label names in the querier. // If only one matcher is provided with label Name=seriesWithLabelNames then the resulting set will have the values of that matchers pipe-split appended. // I.e. querying for {seriesWithLabelNames="foo|bar|baz"} will have as result [bar, baz, foo, ] -func (m mockTenantQuerier) LabelNames(ctx context.Context, _ *storage.LabelHints, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) { +func (m mockTenantQuerier) LabelNames(ctx context.Context, hints *storage.LabelHints, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) { tenantID, err := tenant.TenantID(ctx) if err != nil { return nil, nil, err @@ -238,6 +243,11 @@ func (m mockTenantQuerier) LabelNames(ctx context.Context, _ *storage.LabelHints results = append(results, k) } slices.Sort(results) + + if hints != nil && hints.Limit > 0 && len(results) > hints.Limit { + results = results[:hints.Limit] + } + return results, warnings, nil } diff --git a/pkg/storegateway/bucket.go b/pkg/storegateway/bucket.go index 1fefa6a26d..57f6f067cc 100644 --- a/pkg/storegateway/bucket.go +++ b/pkg/storegateway/bucket.go @@ -1419,8 +1419,13 @@ func (s *BucketStore) LabelNames(ctx context.Context, req *storepb.LabelNamesReq return nil, status.Error(codes.Unknown, errors.Wrap(err, "marshal label names response hints").Error()) } + names := util.MergeSlices(sets...) + if req.Limit > 0 && len(names) > int(req.Limit) { + names = names[:req.Limit] + } + return &storepb.LabelNamesResponse{ - Names: util.MergeSlices(sets...), + Names: names, Hints: anyHints, }, nil } @@ -1595,8 +1600,13 @@ func (s *BucketStore) LabelValues(ctx context.Context, req *storepb.LabelValuesR return nil, status.Error(codes.Unknown, errors.Wrap(err, "marshal label values response hints").Error()) } + values := util.MergeSlices(sets...) + if req.Limit > 0 && len(values) > int(req.Limit) { + values = values[:req.Limit] + } + return &storepb.LabelValuesResponse{ - Values: util.MergeSlices(sets...), + Values: values, Hints: anyHints, }, nil } diff --git a/pkg/storegateway/bucket_e2e_test.go b/pkg/storegateway/bucket_e2e_test.go index bbd63c1c72..25234c9f0f 100644 --- a/pkg/storegateway/bucket_e2e_test.go +++ b/pkg/storegateway/bucket_e2e_test.go @@ -881,6 +881,14 @@ func TestBucketStore_LabelNames_e2e(t *testing.T) { }, expected: []string{"a", "b", "c"}, }, + "basic labelNames, limit = 1": { + req: &storepb.LabelNamesRequest{ + Start: timestamp.FromTime(minTime), + End: timestamp.FromTime(maxTime), + Limit: 1, + }, + expected: []string{"a"}, + }, "outside the time range": { req: &storepb.LabelNamesRequest{ Start: timestamp.FromTime(time.Now().Add(-24 * time.Hour)), @@ -1024,6 +1032,15 @@ func TestBucketStore_LabelValues_e2e(t *testing.T) { }, expected: []string{"2"}, }, + "label a, limit=1": { + req: &storepb.LabelValuesRequest{ + Label: "a", + Start: timestamp.FromTime(minTime), + End: timestamp.FromTime(maxTime), + Limit: 1, + }, + expected: []string{"1"}, + }, "label ext1": { req: &storepb.LabelValuesRequest{ Label: "ext1", diff --git a/pkg/storegateway/storepb/rpc.pb.go b/pkg/storegateway/storepb/rpc.pb.go index 763f925f01..39cbe60354 100644 --- a/pkg/storegateway/storepb/rpc.pb.go +++ b/pkg/storegateway/storepb/rpc.pb.go @@ -277,6 +277,7 @@ type LabelNamesRequest struct { // implementation of a specific store. Hints *types.Any `protobuf:"bytes,5,opt,name=hints,proto3" json:"hints,omitempty"` Matchers []LabelMatcher `protobuf:"bytes,6,rep,name=matchers,proto3" json:"matchers"` + Limit int64 `protobuf:"varint,7,opt,name=limit,proto3" json:"limit,omitempty"` } func (m *LabelNamesRequest) Reset() { *m = LabelNamesRequest{} } @@ -361,6 +362,7 @@ type LabelValuesRequest struct { // implementation of a specific store. Hints *types.Any `protobuf:"bytes,6,opt,name=hints,proto3" json:"hints,omitempty"` Matchers []LabelMatcher `protobuf:"bytes,7,rep,name=matchers,proto3" json:"matchers"` + Limit int64 `protobuf:"varint,8,opt,name=limit,proto3" json:"limit,omitempty"` } func (m *LabelValuesRequest) Reset() { *m = LabelValuesRequest{} } @@ -449,54 +451,54 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 740 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x93, 0xc1, 0x6e, 0x13, 0x3b, - 0x14, 0x86, 0xc7, 0x19, 0xcf, 0xc4, 0x71, 0x9a, 0xde, 0xe9, 0xb4, 0xba, 0x77, 0x9a, 0x7b, 0x35, - 0x8d, 0x22, 0x5d, 0x29, 0x42, 0x90, 0x4a, 0x45, 0x82, 0x15, 0x8b, 0x06, 0x21, 0xa5, 0x23, 0x60, - 0xe1, 0x22, 0x16, 0x48, 0x28, 0x9a, 0x24, 0x6e, 0x62, 0x35, 0xe3, 0x09, 0x63, 0x07, 0x9a, 0xae, - 0x78, 0x04, 0x1e, 0x03, 0xc1, 0x13, 0xb0, 0x65, 0xd5, 0x65, 0x97, 0x5d, 0x21, 0x92, 0x6e, 0x58, - 0xf6, 0x11, 0xd0, 0x78, 0x9c, 0xa4, 0x11, 0xad, 0x4a, 0x25, 0x76, 0x3e, 0xff, 0x7f, 0x7c, 0x7c, - 0xfc, 0xf9, 0x18, 0x17, 0x92, 0x61, 0xa7, 0x3e, 0x4c, 0x62, 0x19, 0xbb, 0xb6, 0xec, 0x87, 0x3c, - 0x16, 0xe5, 0xa2, 0x1c, 0x0f, 0xa9, 0xc8, 0xc4, 0xf2, 0xbd, 0x1e, 0x93, 0xfd, 0x51, 0xbb, 0xde, - 0x89, 0xa3, 0xed, 0x5e, 0xdc, 0x8b, 0xb7, 0x95, 0xdc, 0x1e, 0x1d, 0xa8, 0x48, 0x05, 0x6a, 0xa5, - 0xd3, 0x37, 0x7b, 0x71, 0xdc, 0x1b, 0xd0, 0x45, 0x56, 0xc8, 0xc7, 0x99, 0x55, 0xfd, 0x92, 0xc3, - 0xa5, 0x7d, 0x9a, 0x30, 0x2a, 0x08, 0x7d, 0x33, 0xa2, 0x42, 0xba, 0x9b, 0x18, 0x45, 0x8c, 0xb7, - 0x24, 0x8b, 0xa8, 0x07, 0x2a, 0xa0, 0x66, 0x92, 0x7c, 0xc4, 0xf8, 0x0b, 0x16, 0x51, 0x65, 0x85, - 0x47, 0x99, 0x95, 0xd3, 0x56, 0x78, 0xa4, 0xac, 0x07, 0xa9, 0x25, 0x3b, 0x7d, 0x9a, 0x08, 0xcf, - 0xac, 0x98, 0xb5, 0xe2, 0xce, 0x46, 0x3d, 0xeb, 0xbc, 0xfe, 0x34, 0x6c, 0xd3, 0xc1, 0xb3, 0xcc, - 0x6c, 0xc0, 0x93, 0x6f, 0x5b, 0x06, 0x99, 0xe7, 0xba, 0x5b, 0xb8, 0x28, 0x0e, 0xd9, 0xb0, 0xd5, - 0xe9, 0x8f, 0xf8, 0xa1, 0xf0, 0x50, 0x05, 0xd4, 0x10, 0xc1, 0xa9, 0xf4, 0x58, 0x29, 0xee, 0x1d, - 0x6c, 0xf5, 0x19, 0x97, 0xc2, 0x2b, 0x54, 0x80, 0xaa, 0x9a, 0xdd, 0xa5, 0x3e, 0xbb, 0x4b, 0x7d, - 0x97, 0x8f, 0x49, 0x96, 0xe2, 0x3e, 0xc2, 0xff, 0x0a, 0x99, 0xd0, 0x30, 0x62, 0xbc, 0xa7, 0x2b, - 0xb6, 0xda, 0xe9, 0x49, 0x2d, 0xc1, 0x8e, 0xa9, 0xd7, 0xad, 0x80, 0x1a, 0x24, 0xde, 0x3c, 0x25, - 0x3b, 0xa1, 0x91, 0x26, 0xec, 0xb3, 0x63, 0x1a, 0x40, 0x04, 0x1d, 0x2b, 0x80, 0xc8, 0x72, 0xec, - 0x00, 0x22, 0xdb, 0xc9, 0x07, 0x10, 0xe5, 0x1d, 0x14, 0x40, 0x84, 0x9d, 0x62, 0x00, 0x51, 0xd1, - 0x59, 0x09, 0x20, 0x5a, 0x71, 0x4a, 0x01, 0x44, 0x25, 0x67, 0xb5, 0xfa, 0x10, 0x5b, 0xfb, 0x32, - 0x94, 0xc2, 0xad, 0xe3, 0xf5, 0x03, 0x9a, 0x5e, 0xa8, 0xdb, 0x62, 0xbc, 0x4b, 0x8f, 0x5a, 0xed, - 0xb1, 0xa4, 0x42, 0xd1, 0x83, 0x64, 0x4d, 0x5b, 0x7b, 0xa9, 0xd3, 0x48, 0x8d, 0xea, 0x27, 0x13, - 0xaf, 0xce, 0xa0, 0x8b, 0x61, 0xcc, 0x05, 0x75, 0x6b, 0xd8, 0x16, 0x4a, 0x51, 0xbb, 0x8a, 0x3b, - 0xab, 0x33, 0x7a, 0x59, 0x5e, 0xd3, 0x20, 0xda, 0x77, 0xcb, 0x38, 0xff, 0x2e, 0x4c, 0x38, 0xe3, - 0x3d, 0xf5, 0x06, 0x85, 0xa6, 0x41, 0x66, 0x82, 0x7b, 0x77, 0x06, 0xcb, 0xbc, 0x1e, 0x56, 0xd3, - 0x98, 0xe1, 0xfa, 0x1f, 0x5b, 0x22, 0xed, 0xdf, 0x83, 0x2a, 0xbb, 0x34, 0x3f, 0x32, 0x15, 0xd3, - 0x34, 0xe5, 0xba, 0x7b, 0xd8, 0x59, 0x50, 0xd5, 0x4d, 0x5a, 0x6a, 0xc7, 0x7f, 0x8b, 0x1d, 0xda, - 0xcf, 0xba, 0x55, 0x48, 0x9b, 0x06, 0xf9, 0x4b, 0x2c, 0xeb, 0xcb, 0xa5, 0xf4, 0x93, 0xdb, 0xd7, - 0x94, 0xba, 0xf4, 0x3a, 0x4b, 0xa5, 0xf4, 0x5c, 0xbc, 0xc6, 0x9b, 0xbf, 0xbc, 0x35, 0x15, 0x92, - 0x45, 0xa1, 0xa4, 0x5e, 0x5e, 0xd5, 0xdc, 0xba, 0xa6, 0xe6, 0x13, 0x9d, 0xd6, 0x34, 0xc8, 0x3f, - 0xe2, 0x6a, 0xab, 0x81, 0xb0, 0x9d, 0x50, 0x31, 0x1a, 0xc8, 0xea, 0x67, 0x80, 0xd7, 0xd4, 0x08, - 0x3f, 0x0f, 0xa3, 0xc5, 0x2f, 0xd9, 0x50, 0xec, 0x12, 0xa9, 0x48, 0x9b, 0x24, 0x0b, 0x5c, 0x07, - 0x9b, 0x94, 0x77, 0x15, 0x4f, 0x93, 0xa4, 0xcb, 0xc5, 0xf8, 0x5a, 0x37, 0x8f, 0xef, 0xe5, 0x3f, - 0x64, 0xff, 0xfe, 0x1f, 0x0a, 0x20, 0x02, 0x4e, 0x2e, 0x80, 0x28, 0xe7, 0x98, 0xd5, 0x04, 0xbb, - 0x97, 0x9b, 0xd5, 0xd3, 0xb5, 0x81, 0x2d, 0x9e, 0x0a, 0x1e, 0xa8, 0x98, 0xb5, 0x02, 0xc9, 0x02, - 0xb7, 0x8c, 0x91, 0x1e, 0x1c, 0xe1, 0xe5, 0x94, 0x31, 0x8f, 0x17, 0x7d, 0x9b, 0x37, 0xf6, 0x5d, - 0xfd, 0x0a, 0xf4, 0xa1, 0x2f, 0xc3, 0xc1, 0x68, 0x09, 0xd1, 0x20, 0x55, 0xd5, 0x44, 0x17, 0x48, - 0x16, 0x2c, 0xc0, 0xc1, 0x2b, 0xc0, 0x59, 0x57, 0x80, 0xb3, 0x6f, 0x07, 0x2e, 0x7f, 0x2b, 0x70, - 0x39, 0xc7, 0x0c, 0x20, 0x32, 0x1d, 0x58, 0x1d, 0xe1, 0xf5, 0xa5, 0x3b, 0x68, 0x72, 0x7f, 0x63, - 0xfb, 0xad, 0x52, 0x34, 0x3a, 0x1d, 0xfd, 0x29, 0x76, 0x8d, 0xdd, 0x93, 0x89, 0x6f, 0x9c, 0x4e, - 0x7c, 0xe3, 0x6c, 0xe2, 0x1b, 0x17, 0x13, 0x1f, 0xbc, 0x9f, 0xfa, 0xe0, 0xe3, 0xd4, 0x07, 0x27, - 0x53, 0x1f, 0x9c, 0x4e, 0x7d, 0xf0, 0x7d, 0xea, 0x83, 0x1f, 0x53, 0xdf, 0xb8, 0x98, 0xfa, 0xe0, - 0xc3, 0xb9, 0x6f, 0x9c, 0x9e, 0xfb, 0xc6, 0xd9, 0xb9, 0x6f, 0xbc, 0xca, 0x0b, 0x19, 0x27, 0x74, - 0xd8, 0x6e, 0xdb, 0xaa, 0xee, 0xfd, 0x9f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xfa, 0xb6, 0x7d, 0x6f, - 0x35, 0x06, 0x00, 0x00, + // 749 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x93, 0x41, 0x6f, 0xd3, 0x30, + 0x14, 0xc7, 0xe3, 0xc6, 0x49, 0x5d, 0x77, 0x1d, 0x59, 0x56, 0x41, 0x56, 0x50, 0x56, 0x55, 0x42, + 0xaa, 0x10, 0x74, 0xd2, 0x90, 0xe0, 0xc4, 0x61, 0x45, 0x48, 0x5d, 0x04, 0x1c, 0x3c, 0xc4, 0x01, + 0x09, 0x55, 0x69, 0xeb, 0xb5, 0xd6, 0x9a, 0xa4, 0xc4, 0x2e, 0xac, 0x3b, 0xf1, 0x11, 0xf8, 0x18, + 0x88, 0x6f, 0xc0, 0x91, 0xdb, 0x8e, 0x3b, 0xee, 0x84, 0x68, 0x77, 0xe1, 0xb8, 0x8f, 0x80, 0xe2, + 0xb8, 0xcd, 0x2a, 0x36, 0x4d, 0x43, 0xdc, 0xfc, 0xfe, 0xff, 0xe7, 0x67, 0xbf, 0x9f, 0x9f, 0x71, + 0x21, 0x1e, 0x75, 0x1b, 0xa3, 0x38, 0x12, 0x91, 0x6d, 0x8a, 0x81, 0x1f, 0x46, 0xbc, 0x52, 0x14, + 0x93, 0x11, 0xe5, 0xa9, 0x58, 0x79, 0xd4, 0x67, 0x62, 0x30, 0xee, 0x34, 0xba, 0x51, 0xb0, 0xd5, + 0x8f, 0xfa, 0xd1, 0x96, 0x94, 0x3b, 0xe3, 0x7d, 0x19, 0xc9, 0x40, 0xae, 0x54, 0xfa, 0x46, 0x3f, + 0x8a, 0xfa, 0x43, 0x9a, 0x65, 0xf9, 0xe1, 0x24, 0xb5, 0x6a, 0xdf, 0x73, 0xb8, 0xb4, 0x47, 0x63, + 0x46, 0x39, 0xa1, 0x1f, 0xc6, 0x94, 0x0b, 0x7b, 0x03, 0xa3, 0x80, 0x85, 0x6d, 0xc1, 0x02, 0xea, + 0x80, 0x2a, 0xa8, 0xeb, 0x24, 0x1f, 0xb0, 0xf0, 0x0d, 0x0b, 0xa8, 0xb4, 0xfc, 0xc3, 0xd4, 0xca, + 0x29, 0xcb, 0x3f, 0x94, 0xd6, 0x93, 0xc4, 0x12, 0xdd, 0x01, 0x8d, 0xb9, 0xa3, 0x57, 0xf5, 0x7a, + 0x71, 0xbb, 0xdc, 0x48, 0x6f, 0xde, 0x78, 0xe9, 0x77, 0xe8, 0xf0, 0x55, 0x6a, 0x36, 0xe1, 0xf1, + 0xcf, 0x4d, 0x8d, 0x2c, 0x72, 0xed, 0x4d, 0x5c, 0xe4, 0x07, 0x6c, 0xd4, 0xee, 0x0e, 0xc6, 0xe1, + 0x01, 0x77, 0x50, 0x15, 0xd4, 0x11, 0xc1, 0x89, 0xf4, 0x5c, 0x2a, 0xf6, 0x03, 0x6c, 0x0c, 0x58, + 0x28, 0xb8, 0x53, 0xa8, 0x02, 0x59, 0x35, 0xed, 0xa5, 0x31, 0xef, 0xa5, 0xb1, 0x13, 0x4e, 0x48, + 0x9a, 0x62, 0x3f, 0xc3, 0x77, 0xb9, 0x88, 0xa9, 0x1f, 0xb0, 0xb0, 0xaf, 0x2a, 0xb6, 0x3b, 0xc9, + 0x49, 0x6d, 0xce, 0x8e, 0xa8, 0xd3, 0xab, 0x82, 0x3a, 0x24, 0xce, 0x22, 0x25, 0x3d, 0xa1, 0x99, + 0x24, 0xec, 0xb1, 0x23, 0xea, 0x41, 0x04, 0x2d, 0xc3, 0x83, 0xc8, 0xb0, 0x4c, 0x0f, 0x22, 0xd3, + 0xca, 0x7b, 0x10, 0xe5, 0x2d, 0xe4, 0x41, 0x84, 0xad, 0xa2, 0x07, 0x51, 0xd1, 0x5a, 0xf1, 0x20, + 0x5a, 0xb1, 0x4a, 0x1e, 0x44, 0x25, 0x6b, 0xb5, 0xf6, 0x14, 0x1b, 0x7b, 0xc2, 0x17, 0xdc, 0x6e, + 0xe0, 0xf5, 0x7d, 0x9a, 0x34, 0xd4, 0x6b, 0xb3, 0xb0, 0x47, 0x0f, 0xdb, 0x9d, 0x89, 0xa0, 0x5c, + 0xd2, 0x83, 0x64, 0x4d, 0x59, 0xbb, 0x89, 0xd3, 0x4c, 0x8c, 0xda, 0x37, 0x1d, 0xaf, 0xce, 0xa1, + 0xf3, 0x51, 0x14, 0x72, 0x6a, 0xd7, 0xb1, 0xc9, 0xa5, 0x22, 0x77, 0x15, 0xb7, 0x57, 0xe7, 0xf4, + 0xd2, 0xbc, 0x96, 0x46, 0x94, 0x6f, 0x57, 0x70, 0xfe, 0x93, 0x1f, 0x87, 0x2c, 0xec, 0xcb, 0x37, + 0x28, 0xb4, 0x34, 0x32, 0x17, 0xec, 0x87, 0x73, 0x58, 0xfa, 0xd5, 0xb0, 0x5a, 0xda, 0x1c, 0xd7, + 0x7d, 0x6c, 0xf0, 0xe4, 0xfe, 0x0e, 0x94, 0xd9, 0xa5, 0xc5, 0x91, 0x89, 0x98, 0xa4, 0x49, 0xd7, + 0xde, 0xc5, 0x56, 0x46, 0x55, 0x5d, 0xd2, 0x90, 0x3b, 0xee, 0x65, 0x3b, 0x94, 0x9f, 0xde, 0x56, + 0x22, 0x6d, 0x69, 0xe4, 0x16, 0x5f, 0xd6, 0x97, 0x4b, 0xa9, 0x27, 0x37, 0xaf, 0x28, 0x75, 0xe1, + 0x75, 0x96, 0x4a, 0xa9, 0xb9, 0x78, 0x8f, 0x37, 0xfe, 0x7a, 0x6b, 0xca, 0x05, 0x0b, 0x7c, 0x41, + 0x9d, 0xbc, 0xac, 0xb9, 0x79, 0x45, 0xcd, 0x17, 0x2a, 0xad, 0xa5, 0x91, 0x3b, 0xfc, 0x72, 0xab, + 0x89, 0xb0, 0x19, 0x53, 0x3e, 0x1e, 0x8a, 0xda, 0x0f, 0x80, 0xd7, 0xe4, 0x08, 0xbf, 0xf6, 0x83, + 0xec, 0x97, 0x94, 0x25, 0xbb, 0x58, 0x48, 0xd2, 0x3a, 0x49, 0x03, 0xdb, 0xc2, 0x3a, 0x0d, 0x7b, + 0x92, 0xa7, 0x4e, 0x92, 0x65, 0x36, 0xbe, 0xc6, 0xf5, 0xe3, 0x7b, 0xf1, 0x0f, 0x99, 0x37, 0xf8, + 0x43, 0x65, 0x6c, 0x0c, 0x59, 0xc0, 0x84, 0x6c, 0x5b, 0x27, 0x69, 0xe0, 0x41, 0x04, 0xac, 0x9c, + 0x07, 0x51, 0xce, 0xd2, 0x6b, 0x31, 0xb6, 0x2f, 0xb6, 0xa0, 0x66, 0xae, 0x8c, 0x8d, 0x30, 0x11, + 0x1c, 0x50, 0xd5, 0xeb, 0x05, 0x92, 0x06, 0x76, 0x05, 0x23, 0x35, 0x4e, 0xdc, 0xc9, 0x49, 0x63, + 0x11, 0x67, 0xdd, 0xe8, 0xd7, 0x76, 0x53, 0x3b, 0x05, 0xea, 0xd0, 0xb7, 0xfe, 0x70, 0xbc, 0x04, + 0x6e, 0x98, 0xa8, 0x72, 0xce, 0x0b, 0x24, 0x0d, 0x32, 0x9c, 0xf0, 0x12, 0x9c, 0xc6, 0x25, 0x38, + 0xcd, 0x9b, 0xe1, 0xcc, 0xff, 0x0b, 0x4e, 0xb4, 0x8c, 0x33, 0x67, 0xe9, 0x1e, 0x44, 0xba, 0x05, + 0x6b, 0x63, 0xbc, 0xbe, 0xd4, 0x99, 0xe2, 0x79, 0x1b, 0x9b, 0x1f, 0xa5, 0xa2, 0x80, 0xaa, 0xe8, + 0x7f, 0x11, 0x6d, 0xee, 0x1c, 0x4f, 0x5d, 0xed, 0x64, 0xea, 0x6a, 0xa7, 0x53, 0x57, 0x3b, 0x9f, + 0xba, 0xe0, 0xf3, 0xcc, 0x05, 0x5f, 0x67, 0x2e, 0x38, 0x9e, 0xb9, 0xe0, 0x64, 0xe6, 0x82, 0x5f, + 0x33, 0x17, 0xfc, 0x9e, 0xb9, 0xda, 0xf9, 0xcc, 0x05, 0x5f, 0xce, 0x5c, 0xed, 0xe4, 0xcc, 0xd5, + 0x4e, 0xcf, 0x5c, 0xed, 0x5d, 0x9e, 0x8b, 0x28, 0xa6, 0xa3, 0x4e, 0xc7, 0x94, 0x75, 0x1f, 0xff, + 0x09, 0x00, 0x00, 0xff, 0xff, 0x0e, 0xf1, 0x54, 0xb3, 0x61, 0x06, 0x00, 0x00, } func (this *SeriesRequest) Equal(that interface{}) bool { @@ -801,6 +803,9 @@ func (this *LabelNamesRequest) Equal(that interface{}) bool { return false } } + if this.Limit != that1.Limit { + return false + } return true } func (this *LabelNamesResponse) Equal(that interface{}) bool { @@ -882,6 +887,9 @@ func (this *LabelValuesRequest) Equal(that interface{}) bool { return false } } + if this.Limit != that1.Limit { + return false + } return true } func (this *LabelValuesResponse) Equal(that interface{}) bool { @@ -1029,7 +1037,7 @@ func (this *LabelNamesRequest) GoString() string { if this == nil { return "nil" } - s := make([]string, 0, 8) + s := make([]string, 0, 9) s = append(s, "&storepb.LabelNamesRequest{") s = append(s, "Start: "+fmt.Sprintf("%#v", this.Start)+",\n") s = append(s, "End: "+fmt.Sprintf("%#v", this.End)+",\n") @@ -1043,6 +1051,7 @@ func (this *LabelNamesRequest) GoString() string { } s = append(s, "Matchers: "+fmt.Sprintf("%#v", vs)+",\n") } + s = append(s, "Limit: "+fmt.Sprintf("%#v", this.Limit)+",\n") s = append(s, "}") return strings.Join(s, "") } @@ -1064,7 +1073,7 @@ func (this *LabelValuesRequest) GoString() string { if this == nil { return "nil" } - s := make([]string, 0, 9) + s := make([]string, 0, 10) s = append(s, "&storepb.LabelValuesRequest{") s = append(s, "Label: "+fmt.Sprintf("%#v", this.Label)+",\n") s = append(s, "Start: "+fmt.Sprintf("%#v", this.Start)+",\n") @@ -1079,6 +1088,7 @@ func (this *LabelValuesRequest) GoString() string { } s = append(s, "Matchers: "+fmt.Sprintf("%#v", vs)+",\n") } + s = append(s, "Limit: "+fmt.Sprintf("%#v", this.Limit)+",\n") s = append(s, "}") return strings.Join(s, "") } @@ -1393,6 +1403,11 @@ func (m *LabelNamesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Limit != 0 { + i = encodeVarintRpc(dAtA, i, uint64(m.Limit)) + i-- + dAtA[i] = 0x38 + } if len(m.Matchers) > 0 { for iNdEx := len(m.Matchers) - 1; iNdEx >= 0; iNdEx-- { { @@ -1505,6 +1520,11 @@ func (m *LabelValuesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if m.Limit != 0 { + i = encodeVarintRpc(dAtA, i, uint64(m.Limit)) + i-- + dAtA[i] = 0x40 + } if len(m.Matchers) > 0 { for iNdEx := len(m.Matchers) - 1; iNdEx >= 0; iNdEx-- { { @@ -1774,6 +1794,9 @@ func (m *LabelNamesRequest) Size() (n int) { n += 1 + l + sovRpc(uint64(l)) } } + if m.Limit != 0 { + n += 1 + sovRpc(uint64(m.Limit)) + } return n } @@ -1828,6 +1851,9 @@ func (m *LabelValuesRequest) Size() (n int) { n += 1 + l + sovRpc(uint64(l)) } } + if m.Limit != 0 { + n += 1 + sovRpc(uint64(m.Limit)) + } return n } @@ -1986,6 +2012,7 @@ func (this *LabelNamesRequest) String() string { `End:` + fmt.Sprintf("%v", this.End) + `,`, `Hints:` + strings.Replace(fmt.Sprintf("%v", this.Hints), "Any", "types.Any", 1) + `,`, `Matchers:` + repeatedStringForMatchers + `,`, + `Limit:` + fmt.Sprintf("%v", this.Limit) + `,`, `}`, }, "") return s @@ -2017,6 +2044,7 @@ func (this *LabelValuesRequest) String() string { `End:` + fmt.Sprintf("%v", this.End) + `,`, `Hints:` + strings.Replace(fmt.Sprintf("%v", this.Hints), "Any", "types.Any", 1) + `,`, `Matchers:` + repeatedStringForMatchers + `,`, + `Limit:` + fmt.Sprintf("%v", this.Limit) + `,`, `}`, }, "") return s @@ -2745,6 +2773,25 @@ func (m *LabelNamesRequest) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Limit", wireType) + } + m.Limit = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Limit |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipRpc(dAtA[iNdEx:]) @@ -3091,6 +3138,25 @@ func (m *LabelValuesRequest) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Limit", wireType) + } + m.Limit = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Limit |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipRpc(dAtA[iNdEx:]) diff --git a/pkg/storegateway/storepb/rpc.proto b/pkg/storegateway/storepb/rpc.proto index e8a4404fc7..cf4fc786fc 100644 --- a/pkg/storegateway/storepb/rpc.proto +++ b/pkg/storegateway/storepb/rpc.proto @@ -134,6 +134,8 @@ message LabelNamesRequest { google.protobuf.Any hints = 5; repeated LabelMatcher matchers = 6 [(gogoproto.nullable) = false]; + + int64 limit = 7; } message LabelNamesResponse { @@ -165,6 +167,8 @@ message LabelValuesRequest { google.protobuf.Any hints = 6; repeated LabelMatcher matchers = 7 [(gogoproto.nullable) = false]; + + int64 limit = 8; } message LabelValuesResponse {