diff --git a/pkg/distributor/distributor.go b/pkg/distributor/distributor.go index 664a221b10..d1d078c6c7 100644 --- a/pkg/distributor/distributor.go +++ b/pkg/distributor/distributor.go @@ -1021,7 +1021,7 @@ func (d *Distributor) ForReplicationSet(ctx context.Context, replicationSet ring }) } -func (d *Distributor) LabelValuesForLabelNameCommon(ctx context.Context, from, to model.Time, labelName model.LabelName, f func(ctx context.Context, rs ring.ReplicationSet, req *ingester_client.LabelValuesRequest) ([]interface{}, error), matchers ...*labels.Matcher) ([]string, error) { +func (d *Distributor) LabelValuesForLabelNameCommon(ctx context.Context, from, to model.Time, labelName model.LabelName, limit int, f func(ctx context.Context, rs ring.ReplicationSet, req *ingester_client.LabelValuesRequest) ([]interface{}, error), matchers ...*labels.Matcher) ([]string, error) { span, ctx := opentracing.StartSpanFromContext(ctx, "Distributor.LabelValues", opentracing.Tags{ "name": labelName, "start": from.Unix(), @@ -1033,7 +1033,7 @@ func (d *Distributor) LabelValuesForLabelNameCommon(ctx context.Context, from, t return nil, err } - req, err := ingester_client.ToLabelValuesRequest(labelName, from, to, matchers) + req, err := ingester_client.ToLabelValuesRequest(labelName, from, to, limit, matchers) if err != nil { return nil, err } @@ -1058,8 +1058,8 @@ func (d *Distributor) LabelValuesForLabelNameCommon(ctx context.Context, from, t } // LabelValuesForLabelName returns all the label values that are associated with a given label name. -func (d *Distributor) LabelValuesForLabelName(ctx context.Context, from, to model.Time, labelName model.LabelName, matchers ...*labels.Matcher) ([]string, error) { - return d.LabelValuesForLabelNameCommon(ctx, from, to, labelName, func(ctx context.Context, rs ring.ReplicationSet, req *ingester_client.LabelValuesRequest) ([]interface{}, error) { +func (d *Distributor) LabelValuesForLabelName(ctx context.Context, from, to model.Time, labelName model.LabelName, limit int, matchers ...*labels.Matcher) ([]string, error) { + return d.LabelValuesForLabelNameCommon(ctx, from, to, labelName, limit, func(ctx context.Context, rs ring.ReplicationSet, req *ingester_client.LabelValuesRequest) ([]interface{}, error) { return d.ForReplicationSet(ctx, rs, d.cfg.ZoneResultsQuorumMetadata, func(ctx context.Context, client ingester_client.IngesterClient) (interface{}, error) { resp, err := client.LabelValues(ctx, req) if err != nil { @@ -1071,8 +1071,8 @@ func (d *Distributor) LabelValuesForLabelName(ctx context.Context, from, to mode } // LabelValuesForLabelNameStream returns all the label values that are associated with a given label name. -func (d *Distributor) LabelValuesForLabelNameStream(ctx context.Context, from, to model.Time, labelName model.LabelName, matchers ...*labels.Matcher) ([]string, error) { - return d.LabelValuesForLabelNameCommon(ctx, from, to, labelName, func(ctx context.Context, rs ring.ReplicationSet, req *ingester_client.LabelValuesRequest) ([]interface{}, error) { +func (d *Distributor) LabelValuesForLabelNameStream(ctx context.Context, from, to model.Time, labelName model.LabelName, limit int, matchers ...*labels.Matcher) ([]string, error) { + return d.LabelValuesForLabelNameCommon(ctx, from, to, labelName, limit, func(ctx context.Context, rs ring.ReplicationSet, req *ingester_client.LabelValuesRequest) ([]interface{}, error) { return d.ForReplicationSet(ctx, rs, d.cfg.ZoneResultsQuorumMetadata, func(ctx context.Context, client ingester_client.IngesterClient) (interface{}, error) { stream, err := client.LabelValuesStream(ctx, req) if err != nil { @@ -1096,7 +1096,7 @@ func (d *Distributor) LabelValuesForLabelNameStream(ctx context.Context, from, t }, matchers...) } -func (d *Distributor) LabelNamesCommon(ctx context.Context, from, to model.Time, f func(ctx context.Context, rs ring.ReplicationSet, req *ingester_client.LabelNamesRequest) ([]interface{}, error)) ([]string, error) { +func (d *Distributor) LabelNamesCommon(ctx context.Context, from, to model.Time, limit int, f func(ctx context.Context, rs ring.ReplicationSet, req *ingester_client.LabelNamesRequest) ([]interface{}, error)) ([]string, error) { span, ctx := opentracing.StartSpanFromContext(ctx, "Distributor.LabelNames", opentracing.Tags{ "start": from.Unix(), "end": to.Unix(), @@ -1110,6 +1110,7 @@ func (d *Distributor) LabelNamesCommon(ctx context.Context, from, to model.Time, req := &ingester_client.LabelNamesRequest{ StartTimestampMs: int64(from), EndTimestampMs: int64(to), + Limit: int64(limit), } resps, err := f(ctx, replicationSet, req) if err != nil { @@ -1131,8 +1132,8 @@ func (d *Distributor) LabelNamesCommon(ctx context.Context, from, to model.Time, return r, nil } -func (d *Distributor) LabelNamesStream(ctx context.Context, from, to model.Time) ([]string, error) { - return d.LabelNamesCommon(ctx, from, to, func(ctx context.Context, rs ring.ReplicationSet, req *ingester_client.LabelNamesRequest) ([]interface{}, error) { +func (d *Distributor) LabelNamesStream(ctx context.Context, from, to model.Time, limit int) ([]string, error) { + return d.LabelNamesCommon(ctx, from, to, limit, func(ctx context.Context, rs ring.ReplicationSet, req *ingester_client.LabelNamesRequest) ([]interface{}, error) { return d.ForReplicationSet(ctx, rs, d.cfg.ZoneResultsQuorumMetadata, func(ctx context.Context, client ingester_client.IngesterClient) (interface{}, error) { stream, err := client.LabelNamesStream(ctx, req) if err != nil { @@ -1157,8 +1158,8 @@ func (d *Distributor) LabelNamesStream(ctx context.Context, from, to model.Time) } // LabelNames returns all the label names. -func (d *Distributor) LabelNames(ctx context.Context, from, to model.Time) ([]string, error) { - return d.LabelNamesCommon(ctx, from, to, func(ctx context.Context, rs ring.ReplicationSet, req *ingester_client.LabelNamesRequest) ([]interface{}, error) { +func (d *Distributor) LabelNames(ctx context.Context, from, to model.Time, limit int) ([]string, error) { + return d.LabelNamesCommon(ctx, from, to, limit, func(ctx context.Context, rs ring.ReplicationSet, req *ingester_client.LabelNamesRequest) ([]interface{}, error) { return d.ForReplicationSet(ctx, rs, d.cfg.ZoneResultsQuorumMetadata, func(ctx context.Context, client ingester_client.IngesterClient) (interface{}, error) { resp, err := client.LabelNames(ctx, req) if err != nil { @@ -1170,8 +1171,8 @@ func (d *Distributor) LabelNames(ctx context.Context, from, to model.Time) ([]st } // MetricsForLabelMatchers gets the metrics that match said matchers -func (d *Distributor) MetricsForLabelMatchers(ctx context.Context, from, through model.Time, matchers ...*labels.Matcher) ([]model.Metric, error) { - return d.metricsForLabelMatchersCommon(ctx, from, through, func(ctx context.Context, rs ring.ReplicationSet, req *ingester_client.MetricsForLabelMatchersRequest, metrics *map[model.Fingerprint]model.Metric, mutex *sync.Mutex, queryLimiter *limiter.QueryLimiter) error { +func (d *Distributor) MetricsForLabelMatchers(ctx context.Context, from, through model.Time, limit int, matchers ...*labels.Matcher) ([]model.Metric, error) { + return d.metricsForLabelMatchersCommon(ctx, from, through, limit, func(ctx context.Context, rs ring.ReplicationSet, req *ingester_client.MetricsForLabelMatchersRequest, metrics *map[model.Fingerprint]model.Metric, mutex *sync.Mutex, queryLimiter *limiter.QueryLimiter) error { _, err := d.ForReplicationSet(ctx, rs, false, func(ctx context.Context, client ingester_client.IngesterClient) (interface{}, error) { resp, err := client.MetricsForLabelMatchers(ctx, req) if err != nil { @@ -1199,8 +1200,8 @@ func (d *Distributor) MetricsForLabelMatchers(ctx context.Context, from, through }, matchers...) } -func (d *Distributor) MetricsForLabelMatchersStream(ctx context.Context, from, through model.Time, matchers ...*labels.Matcher) ([]model.Metric, error) { - return d.metricsForLabelMatchersCommon(ctx, from, through, func(ctx context.Context, rs ring.ReplicationSet, req *ingester_client.MetricsForLabelMatchersRequest, metrics *map[model.Fingerprint]model.Metric, mutex *sync.Mutex, queryLimiter *limiter.QueryLimiter) error { +func (d *Distributor) MetricsForLabelMatchersStream(ctx context.Context, from, through model.Time, limit int, matchers ...*labels.Matcher) ([]model.Metric, error) { + return d.metricsForLabelMatchersCommon(ctx, from, through, limit, func(ctx context.Context, rs ring.ReplicationSet, req *ingester_client.MetricsForLabelMatchersRequest, metrics *map[model.Fingerprint]model.Metric, mutex *sync.Mutex, queryLimiter *limiter.QueryLimiter) error { _, err := d.ForReplicationSet(ctx, rs, false, func(ctx context.Context, client ingester_client.IngesterClient) (interface{}, error) { stream, err := client.MetricsForLabelMatchersStream(ctx, req) if err != nil { @@ -1239,14 +1240,14 @@ func (d *Distributor) MetricsForLabelMatchersStream(ctx context.Context, from, t }, matchers...) } -func (d *Distributor) metricsForLabelMatchersCommon(ctx context.Context, from, through model.Time, f func(context.Context, ring.ReplicationSet, *ingester_client.MetricsForLabelMatchersRequest, *map[model.Fingerprint]model.Metric, *sync.Mutex, *limiter.QueryLimiter) error, matchers ...*labels.Matcher) ([]model.Metric, error) { +func (d *Distributor) metricsForLabelMatchersCommon(ctx context.Context, from, through model.Time, limit int, f func(context.Context, ring.ReplicationSet, *ingester_client.MetricsForLabelMatchersRequest, *map[model.Fingerprint]model.Metric, *sync.Mutex, *limiter.QueryLimiter) error, matchers ...*labels.Matcher) ([]model.Metric, error) { replicationSet, err := d.GetIngestersForMetadata(ctx) queryLimiter := limiter.QueryLimiterFromContextWithFallback(ctx) if err != nil { return nil, err } - req, err := ingester_client.ToMetricsForLabelMatchersRequest(from, through, matchers) + req, err := ingester_client.ToMetricsForLabelMatchersRequest(from, through, limit, matchers) if err != nil { return nil, err } diff --git a/pkg/ingester/client/compat.go b/pkg/ingester/client/compat.go index cbac06a46f..6e4a81d634 100644 --- a/pkg/ingester/client/compat.go +++ b/pkg/ingester/client/compat.go @@ -114,7 +114,7 @@ func ToQueryResponse(matrix model.Matrix) *QueryResponse { } // ToMetricsForLabelMatchersRequest builds a MetricsForLabelMatchersRequest proto -func ToMetricsForLabelMatchersRequest(from, to model.Time, matchers []*labels.Matcher) (*MetricsForLabelMatchersRequest, error) { +func ToMetricsForLabelMatchersRequest(from, to model.Time, limit int, matchers []*labels.Matcher) (*MetricsForLabelMatchersRequest, error) { ms, err := toLabelMatchers(matchers) if err != nil { return nil, err @@ -124,6 +124,7 @@ func ToMetricsForLabelMatchersRequest(from, to model.Time, matchers []*labels.Ma StartTimestampMs: int64(from), EndTimestampMs: int64(to), MatchersSet: []*LabelMatchers{{Matchers: ms}}, + Limit: int64(limit), }, nil } @@ -174,22 +175,22 @@ func SeriesSetToQueryResponse(s storage.SeriesSet) (*QueryResponse, error) { } // FromMetricsForLabelMatchersRequest unpacks a MetricsForLabelMatchersRequest proto -func FromMetricsForLabelMatchersRequest(req *MetricsForLabelMatchersRequest) (model.Time, model.Time, [][]*labels.Matcher, error) { +func FromMetricsForLabelMatchersRequest(req *MetricsForLabelMatchersRequest) (model.Time, model.Time, int, [][]*labels.Matcher, error) { matchersSet := make([][]*labels.Matcher, 0, len(req.MatchersSet)) for _, matchers := range req.MatchersSet { matchers, err := FromLabelMatchers(matchers.Matchers) if err != nil { - return 0, 0, nil, err + return 0, 0, 0, nil, err } matchersSet = append(matchersSet, matchers) } from := model.Time(req.StartTimestampMs) to := model.Time(req.EndTimestampMs) - return from, to, matchersSet, nil + return from, to, int(req.Limit), matchersSet, nil } // 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, limit int, matchers []*labels.Matcher) (*LabelValuesRequest, error) { ms, err := toLabelMatchers(matchers) if err != nil { return nil, err @@ -200,22 +201,23 @@ func ToLabelValuesRequest(labelName model.LabelName, from, to model.Time, matche StartTimestampMs: int64(from), EndTimestampMs: int64(to), Matchers: &LabelMatchers{Matchers: ms}, + Limit: int64(limit), }, nil } // FromLabelValuesRequest unpacks a LabelValuesRequest proto -func FromLabelValuesRequest(req *LabelValuesRequest) (string, int64, int64, []*labels.Matcher, error) { +func FromLabelValuesRequest(req *LabelValuesRequest) (string, int64, int64, int, []*labels.Matcher, error) { var err error 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, 0, nil, err } } - return req.LabelName, req.StartTimestampMs, req.EndTimestampMs, matchers, nil + return req.LabelName, req.StartTimestampMs, req.EndTimestampMs, int(req.Limit), matchers, nil } func toLabelMatchers(matchers []*labels.Matcher) ([]*LabelMatcher, error) { diff --git a/pkg/ingester/client/ingester.pb.go b/pkg/ingester/client/ingester.pb.go index 643c9c6c2e..594292429f 100644 --- a/pkg/ingester/client/ingester.pb.go +++ b/pkg/ingester/client/ingester.pb.go @@ -402,6 +402,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{} } @@ -464,6 +465,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"` } @@ -553,6 +561,7 @@ func (m *LabelValuesStreamResponse) GetLabelValues() []string { 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"` + Limit int64 `protobuf:"varint,3,opt,name=limit,proto3" json:"limit,omitempty"` } func (m *LabelNamesRequest) Reset() { *m = LabelNamesRequest{} } @@ -601,6 +610,13 @@ func (m *LabelNamesRequest) GetEndTimestampMs() int64 { return 0 } +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"` } @@ -895,6 +911,7 @@ type MetricsForLabelMatchersRequest 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"` MatchersSet []*LabelMatchers `protobuf:"bytes,3,rep,name=matchers_set,json=matchersSet,proto3" json:"matchers_set,omitempty"` + Limit int64 `protobuf:"varint,4,opt,name=limit,proto3" json:"limit,omitempty"` } func (m *MetricsForLabelMatchersRequest) Reset() { *m = MetricsForLabelMatchersRequest{} } @@ -950,6 +967,13 @@ func (m *MetricsForLabelMatchersRequest) GetMatchersSet() []*LabelMatchers { return nil } +func (m *MetricsForLabelMatchersRequest) GetLimit() int64 { + if m != nil { + return m.Limit + } + return 0 +} + type MetricsForLabelMatchersResponse struct { Metric []*cortexpb.Metric `protobuf:"bytes,1,rep,name=metric,proto3" json:"metric,omitempty"` } @@ -1444,88 +1468,89 @@ func init() { func init() { proto.RegisterFile("ingester.proto", fileDescriptor_60f6df4f3586b478) } var fileDescriptor_60f6df4f3586b478 = []byte{ - // 1292 bytes of a gzipped FileDescriptorProto + // 1309 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0x4b, 0x6f, 0xd4, 0xd6, - 0x17, 0xb7, 0x33, 0x93, 0x49, 0xe6, 0xcc, 0x64, 0x98, 0xdc, 0x04, 0x32, 0x98, 0x3f, 0x0e, 0xf8, - 0x2f, 0xda, 0xa8, 0x2d, 0x09, 0xa4, 0xad, 0x04, 0x7d, 0xa1, 0x04, 0x02, 0x04, 0x08, 0x01, 0x67, - 0xa0, 0x55, 0xd5, 0xca, 0x72, 0x66, 0x2e, 0x13, 0x17, 0xbf, 0xb0, 0xaf, 0x11, 0x74, 0x55, 0xa9, - 0x1f, 0xa0, 0x5d, 0x76, 0xdb, 0x5d, 0xd7, 0xfd, 0x00, 0x5d, 0xb3, 0x64, 0x89, 0xaa, 0x0a, 0x95, - 0x41, 0xaa, 0xba, 0xa4, 0xdf, 0xa0, 0xf2, 0x7d, 0x78, 0x6c, 0xc7, 0x93, 0x0c, 0x12, 0xe9, 0x6e, - 0x7c, 0xce, 0xef, 0x9c, 0xfb, 0x3b, 0x8f, 0x7b, 0xcf, 0x19, 0x68, 0x58, 0x6e, 0x0f, 0x87, 0x04, - 0x07, 0x8b, 0x7e, 0xe0, 0x11, 0x0f, 0x55, 0x3a, 0x5e, 0x40, 0xf0, 0x23, 0x65, 0xb6, 0xe7, 0xf5, - 0x3c, 0x2a, 0x5a, 0x8a, 0x7f, 0x31, 0xad, 0x72, 0xbe, 0x67, 0x91, 0x9d, 0x68, 0x7b, 0xb1, 0xe3, - 0x39, 0x4b, 0x0c, 0xe8, 0x07, 0xde, 0x37, 0xb8, 0x43, 0xf8, 0xd7, 0x92, 0x7f, 0xbf, 0x27, 0x14, - 0xdb, 0xfc, 0x07, 0x33, 0xd5, 0x3e, 0x85, 0x9a, 0x8e, 0xcd, 0xae, 0x8e, 0x1f, 0x44, 0x38, 0x24, - 0x68, 0x11, 0x26, 0x1e, 0x44, 0x38, 0xb0, 0x70, 0xd8, 0x92, 0x4f, 0x94, 0x16, 0x6a, 0xcb, 0xb3, - 0x8b, 0x1c, 0x7e, 0x3b, 0xc2, 0xc1, 0x63, 0x0e, 0xd3, 0x05, 0x48, 0xbb, 0x00, 0x75, 0x66, 0x1e, - 0xfa, 0x9e, 0x1b, 0x62, 0xb4, 0x04, 0x13, 0x01, 0x0e, 0x23, 0x9b, 0x08, 0xfb, 0xc3, 0x39, 0x7b, - 0x86, 0xd3, 0x05, 0x4a, 0xbb, 0x0e, 0x53, 0x19, 0x0d, 0xfa, 0x08, 0x80, 0x58, 0x0e, 0x0e, 0x8b, - 0x48, 0xf8, 0xdb, 0x8b, 0x6d, 0xcb, 0xc1, 0x5b, 0x54, 0xb7, 0x5a, 0x7e, 0xf2, 0x7c, 0x5e, 0xd2, - 0x53, 0x68, 0xed, 0x27, 0x19, 0xea, 0x69, 0x9e, 0xe8, 0x3d, 0x40, 0x21, 0x31, 0x03, 0x62, 0x50, - 0x10, 0x31, 0x1d, 0xdf, 0x70, 0x62, 0xa7, 0xf2, 0x42, 0x49, 0x6f, 0x52, 0x4d, 0x5b, 0x28, 0x36, - 0x42, 0xb4, 0x00, 0x4d, 0xec, 0x76, 0xb3, 0xd8, 0x31, 0x8a, 0x6d, 0x60, 0xb7, 0x9b, 0x46, 0x9e, - 0x81, 0x49, 0xc7, 0x24, 0x9d, 0x1d, 0x1c, 0x84, 0xad, 0x52, 0x36, 0x4f, 0x37, 0xcc, 0x6d, 0x6c, - 0x6f, 0x30, 0xa5, 0x9e, 0xa0, 0xb4, 0x9f, 0x65, 0x98, 0x5d, 0x7b, 0x84, 0x1d, 0xdf, 0x36, 0x83, - 0xff, 0x84, 0xe2, 0xd9, 0x5d, 0x14, 0x0f, 0x17, 0x51, 0x0c, 0x53, 0x1c, 0xbf, 0x82, 0x19, 0x4a, - 0x6d, 0x8b, 0x04, 0xd8, 0x74, 0x92, 0x8a, 0x5c, 0x80, 0x5a, 0x67, 0x27, 0x72, 0xef, 0x67, 0x4a, - 0x32, 0x27, 0x9c, 0x0d, 0x0a, 0x72, 0x31, 0x06, 0xf1, 0xaa, 0xa4, 0x2d, 0xae, 0x95, 0x27, 0xc7, - 0x9a, 0x25, 0x6d, 0x0b, 0x0e, 0xe7, 0x12, 0xf0, 0x06, 0x2a, 0xfe, 0x9b, 0x0c, 0x88, 0x86, 0x73, - 0xd7, 0xb4, 0x23, 0x1c, 0x8a, 0xa4, 0x1e, 0x07, 0xb0, 0x63, 0xa9, 0xe1, 0x9a, 0x0e, 0xa6, 0xc9, - 0xac, 0xea, 0x55, 0x2a, 0xb9, 0x69, 0x3a, 0x78, 0x48, 0xce, 0xc7, 0x5e, 0x23, 0xe7, 0xa5, 0x7d, - 0x73, 0x5e, 0x3e, 0x21, 0x8f, 0x92, 0xf3, 0x73, 0x30, 0x93, 0xe1, 0xcf, 0x73, 0x72, 0x12, 0xea, - 0x2c, 0x80, 0x87, 0x54, 0x4e, 0xb3, 0x52, 0xd5, 0x6b, 0xf6, 0x00, 0xaa, 0x7d, 0x06, 0x47, 0x53, - 0x96, 0xb9, 0x9a, 0x8d, 0x60, 0x7f, 0x1f, 0xa6, 0x6f, 0x88, 0x8c, 0x84, 0x07, 0xdc, 0x8d, 0xda, - 0x87, 0xbc, 0x4c, 0xfc, 0x30, 0xce, 0x72, 0x1e, 0x6a, 0x83, 0x32, 0x09, 0x92, 0x90, 0xd4, 0x29, - 0xd4, 0x3e, 0x86, 0xd6, 0xc0, 0x2c, 0x17, 0xe2, 0xbe, 0xc6, 0x08, 0x9a, 0x77, 0x42, 0x1c, 0x6c, - 0x11, 0x93, 0x88, 0xf8, 0xb4, 0x3f, 0x64, 0x98, 0x4e, 0x09, 0xb9, 0xab, 0x53, 0xe2, 0xbd, 0xb5, - 0x3c, 0xd7, 0x08, 0x4c, 0xc2, 0x5a, 0x46, 0xd6, 0xa7, 0x12, 0xa9, 0x6e, 0x12, 0x1c, 0x77, 0x95, - 0x1b, 0x39, 0x06, 0x6f, 0xd4, 0x38, 0xd0, 0xb2, 0x5e, 0x75, 0x23, 0x87, 0x75, 0x67, 0x9c, 0x3b, - 0xd3, 0xb7, 0x8c, 0x9c, 0xa7, 0x12, 0xf5, 0xd4, 0x34, 0x7d, 0x6b, 0x3d, 0xe3, 0x6c, 0x11, 0x66, - 0x82, 0xc8, 0xc6, 0x79, 0x78, 0x99, 0xc2, 0xa7, 0x63, 0x55, 0x16, 0xff, 0x7f, 0x98, 0x32, 0x3b, - 0xc4, 0x7a, 0x88, 0xc5, 0xf9, 0xe3, 0xf4, 0xfc, 0x3a, 0x13, 0x32, 0x0a, 0xda, 0xd7, 0x30, 0x13, - 0x47, 0xb7, 0x7e, 0x29, 0x1b, 0xdf, 0x1c, 0x4c, 0x44, 0x21, 0x0e, 0x0c, 0xab, 0xcb, 0xef, 0x42, - 0x25, 0xfe, 0x5c, 0xef, 0xa2, 0xd3, 0x50, 0xee, 0x9a, 0xc4, 0xa4, 0xb1, 0xd4, 0x96, 0x8f, 0x8a, - 0x66, 0xdd, 0x95, 0x21, 0x9d, 0xc2, 0xb4, 0x2b, 0x80, 0x62, 0x55, 0x98, 0xf5, 0x7e, 0x16, 0xc6, - 0xc3, 0x58, 0xc0, 0xaf, 0xee, 0xb1, 0xb4, 0x97, 0x1c, 0x13, 0x9d, 0x21, 0xb5, 0x5f, 0x65, 0x50, - 0x37, 0x30, 0x09, 0xac, 0x4e, 0x78, 0xd9, 0x0b, 0xb2, 0x77, 0xe3, 0x80, 0xdf, 0xc5, 0x73, 0x50, - 0x17, 0x97, 0xcf, 0x08, 0x31, 0xd9, 0xfb, 0x6d, 0xac, 0x09, 0xe8, 0x16, 0x26, 0xda, 0x75, 0x98, - 0x1f, 0xca, 0x99, 0xa7, 0x62, 0x01, 0x2a, 0x0e, 0x85, 0xf0, 0x5c, 0x34, 0x07, 0xcf, 0x18, 0x33, - 0xd5, 0xb9, 0x5e, 0xbb, 0x0d, 0xa7, 0x86, 0x38, 0xcb, 0xb5, 0xf9, 0xe8, 0x2e, 0x5b, 0x70, 0x84, - 0xbb, 0xdc, 0xc0, 0xc4, 0x8c, 0x0b, 0x26, 0xba, 0x7e, 0x13, 0xe6, 0x76, 0x69, 0xb8, 0xfb, 0x0f, - 0x60, 0xd2, 0xe1, 0x32, 0x7e, 0x40, 0x2b, 0x7f, 0x40, 0x62, 0x93, 0x20, 0xb5, 0x7f, 0x64, 0x38, - 0x94, 0x7b, 0xf8, 0xe3, 0x12, 0xdc, 0x0b, 0x3c, 0xc7, 0x10, 0x9b, 0xcb, 0xa0, 0xdb, 0x1a, 0xb1, - 0x7c, 0x9d, 0x8b, 0xd7, 0xbb, 0xe9, 0x76, 0x1c, 0xcb, 0xb4, 0xa3, 0x0b, 0x15, 0x7a, 0x7f, 0xc5, - 0xc4, 0x9a, 0x19, 0x50, 0xa1, 0x29, 0xba, 0x65, 0x5a, 0xc1, 0xea, 0x4a, 0x3c, 0x04, 0x7e, 0x7f, - 0x3e, 0xff, 0x5a, 0x4b, 0x0f, 0xb3, 0x5f, 0xe9, 0x9a, 0x3e, 0xc1, 0x81, 0xce, 0x4f, 0x41, 0xef, - 0x42, 0x85, 0xcd, 0xa9, 0x56, 0x99, 0x9e, 0x37, 0x25, 0xba, 0x20, 0x3d, 0xca, 0x38, 0x44, 0xfb, - 0x41, 0x86, 0x71, 0x16, 0xe9, 0x41, 0xb5, 0xa6, 0x02, 0x93, 0xd8, 0xed, 0x78, 0x5d, 0xcb, 0xed, - 0xd1, 0x67, 0x63, 0x5c, 0x4f, 0xbe, 0x11, 0xe2, 0x37, 0x35, 0x7e, 0x1f, 0xea, 0xfc, 0x3a, 0xae, - 0xc0, 0x54, 0xa6, 0x73, 0x32, 0x6b, 0x89, 0x3c, 0xd2, 0x5a, 0x62, 0x40, 0x3d, 0xad, 0x41, 0xa7, - 0xa0, 0x4c, 0x1e, 0xfb, 0xec, 0xfd, 0x6b, 0x2c, 0x4f, 0x0b, 0x6b, 0xaa, 0x6e, 0x3f, 0xf6, 0xb1, - 0x4e, 0xd5, 0x31, 0x1b, 0x3a, 0x59, 0x59, 0xf9, 0xe8, 0x6f, 0x34, 0x0b, 0xe3, 0x74, 0xd8, 0x50, - 0xea, 0x55, 0x9d, 0x7d, 0x68, 0xdf, 0xcb, 0xd0, 0x18, 0x74, 0xca, 0x65, 0xcb, 0xc6, 0x6f, 0xa2, - 0x51, 0x14, 0x98, 0xbc, 0x67, 0xd9, 0x98, 0x72, 0x60, 0xc7, 0x25, 0xdf, 0x45, 0x99, 0x7a, 0xe7, - 0x1a, 0x54, 0x93, 0x10, 0x50, 0x15, 0xc6, 0xd7, 0x6e, 0xdf, 0x59, 0xb9, 0xd1, 0x94, 0xd0, 0x14, - 0x54, 0x6f, 0x6e, 0xb6, 0x0d, 0xf6, 0x29, 0xa3, 0x43, 0x50, 0xd3, 0xd7, 0xae, 0xac, 0x7d, 0x61, - 0x6c, 0xac, 0xb4, 0x2f, 0x5e, 0x6d, 0x8e, 0x21, 0x04, 0x0d, 0x26, 0xb8, 0xb9, 0xc9, 0x65, 0xa5, - 0xe5, 0xbf, 0x26, 0x60, 0x52, 0x70, 0x44, 0xe7, 0xa1, 0x7c, 0x2b, 0x0a, 0x77, 0xd0, 0x91, 0x41, - 0xa7, 0x7e, 0x1e, 0x58, 0x04, 0xf3, 0x9b, 0xa7, 0xcc, 0xed, 0x92, 0xb3, 0x7b, 0xa7, 0x49, 0xe8, - 0x12, 0xd4, 0x52, 0xdb, 0x16, 0x2a, 0x5c, 0xb4, 0x95, 0x63, 0x19, 0x69, 0xf6, 0x69, 0xd0, 0xa4, - 0x33, 0x32, 0xda, 0x84, 0x06, 0x55, 0x89, 0xd5, 0x2a, 0x44, 0xff, 0x13, 0x26, 0x45, 0xeb, 0xa6, - 0x72, 0x7c, 0x88, 0x36, 0xa1, 0x75, 0x15, 0x6a, 0xa9, 0xb5, 0x02, 0x29, 0x99, 0x06, 0xca, 0x6c, - 0x59, 0x03, 0x72, 0x05, 0x1b, 0x8c, 0x26, 0xa1, 0xbb, 0x7c, 0xc1, 0x48, 0x2f, 0x28, 0x7b, 0xfa, - 0x3b, 0x59, 0xa0, 0x2b, 0x08, 0x79, 0x0d, 0x60, 0xb0, 0x14, 0xa0, 0xa3, 0x19, 0xa3, 0xf4, 0x32, - 0xa3, 0x28, 0x45, 0xaa, 0x84, 0xde, 0x16, 0x34, 0xf3, 0xbb, 0xc5, 0x5e, 0xce, 0x4e, 0xec, 0x56, - 0x15, 0x70, 0x5b, 0x85, 0x6a, 0x32, 0x3c, 0x51, 0xab, 0x60, 0x9e, 0x32, 0x67, 0xc3, 0x27, 0xad, - 0x26, 0xa1, 0xcb, 0x50, 0x5f, 0xb1, 0xed, 0x51, 0xdc, 0x28, 0x69, 0x4d, 0x98, 0xf7, 0x63, 0x27, - 0xaf, 0x7e, 0x7e, 0xc4, 0xa0, 0xb7, 0x92, 0x8b, 0xbd, 0xe7, 0x10, 0x56, 0xde, 0xde, 0x17, 0x97, - 0x9c, 0xf6, 0x2d, 0x1c, 0xdf, 0x73, 0xa0, 0x8d, 0x7c, 0xe6, 0xe9, 0x7d, 0x70, 0x05, 0x59, 0x6f, - 0xc3, 0xa1, 0xdc, 0x7c, 0x43, 0x6a, 0xce, 0x4b, 0x6e, 0x24, 0x2a, 0xf3, 0x43, 0xf5, 0xc2, 0xef, - 0xea, 0x27, 0x4f, 0x5f, 0xa8, 0xd2, 0xb3, 0x17, 0xaa, 0xf4, 0xea, 0x85, 0x2a, 0x7f, 0xd7, 0x57, - 0xe5, 0x5f, 0xfa, 0xaa, 0xfc, 0xa4, 0xaf, 0xca, 0x4f, 0xfb, 0xaa, 0xfc, 0x67, 0x5f, 0x95, 0xff, - 0xee, 0xab, 0xd2, 0xab, 0xbe, 0x2a, 0xff, 0xf8, 0x52, 0x95, 0x9e, 0xbe, 0x54, 0xa5, 0x67, 0x2f, - 0x55, 0xe9, 0xcb, 0x4a, 0xc7, 0xb6, 0xb0, 0x4b, 0xb6, 0x2b, 0xf4, 0xff, 0xf5, 0xfb, 0xff, 0x06, - 0x00, 0x00, 0xff, 0xff, 0xa7, 0xb7, 0xb7, 0x0a, 0xca, 0x0f, 0x00, 0x00, + 0x17, 0xb7, 0x33, 0x8f, 0x64, 0xce, 0x4c, 0x86, 0xc9, 0x4d, 0x20, 0x83, 0xf9, 0xe3, 0x80, 0xff, + 0xa2, 0x8d, 0xda, 0x92, 0x40, 0xda, 0x4a, 0xd0, 0x17, 0x4a, 0x20, 0x40, 0x80, 0x10, 0x70, 0x02, + 0xad, 0xaa, 0x56, 0x96, 0x33, 0x73, 0x49, 0x5c, 0xfc, 0xc2, 0xbe, 0x46, 0xd0, 0x55, 0xab, 0x7e, + 0x80, 0x76, 0xd9, 0x6d, 0x77, 0xfd, 0x28, 0x2c, 0x59, 0x74, 0x81, 0xaa, 0x0a, 0x95, 0x41, 0xaa, + 0xba, 0xa4, 0xdf, 0xa0, 0xf2, 0x7d, 0xf8, 0x15, 0x27, 0x19, 0x24, 0xd2, 0x9d, 0xef, 0x39, 0xbf, + 0x73, 0xee, 0x79, 0xde, 0x73, 0x0c, 0x6d, 0xcb, 0xdd, 0xc2, 0x21, 0xc1, 0xc1, 0x9c, 0x1f, 0x78, + 0xc4, 0x43, 0xf5, 0x9e, 0x17, 0x10, 0xfc, 0x48, 0x99, 0xda, 0xf2, 0xb6, 0x3c, 0x4a, 0x9a, 0x8f, + 0xbf, 0x18, 0x57, 0x39, 0xbf, 0x65, 0x91, 0xed, 0x68, 0x73, 0xae, 0xe7, 0x39, 0xf3, 0x0c, 0xe8, + 0x07, 0xde, 0x37, 0xb8, 0x47, 0xf8, 0x69, 0xde, 0xbf, 0xbf, 0x25, 0x18, 0x9b, 0xfc, 0x83, 0x89, + 0x6a, 0x9f, 0x42, 0x53, 0xc7, 0x66, 0x5f, 0xc7, 0x0f, 0x22, 0x1c, 0x12, 0x34, 0x07, 0xa3, 0x0f, + 0x22, 0x1c, 0x58, 0x38, 0xec, 0xca, 0x27, 0x2a, 0xb3, 0xcd, 0x85, 0xa9, 0x39, 0x0e, 0xbf, 0x1d, + 0xe1, 0xe0, 0x31, 0x87, 0xe9, 0x02, 0xa4, 0x5d, 0x80, 0x16, 0x13, 0x0f, 0x7d, 0xcf, 0x0d, 0x31, + 0x9a, 0x87, 0xd1, 0x00, 0x87, 0x91, 0x4d, 0x84, 0xfc, 0xe1, 0x82, 0x3c, 0xc3, 0xe9, 0x02, 0xa5, + 0x5d, 0x87, 0xf1, 0x1c, 0x07, 0x7d, 0x04, 0x40, 0x2c, 0x07, 0x87, 0x65, 0x46, 0xf8, 0x9b, 0x73, + 0x1b, 0x96, 0x83, 0xd7, 0x29, 0x6f, 0xa9, 0xfa, 0xe4, 0xf9, 0x8c, 0xa4, 0x67, 0xd0, 0xda, 0xcf, + 0x32, 0xb4, 0xb2, 0x76, 0xa2, 0xf7, 0x00, 0x85, 0xc4, 0x0c, 0x88, 0x41, 0x41, 0xc4, 0x74, 0x7c, + 0xc3, 0x89, 0x95, 0xca, 0xb3, 0x15, 0xbd, 0x43, 0x39, 0x1b, 0x82, 0xb1, 0x1a, 0xa2, 0x59, 0xe8, + 0x60, 0xb7, 0x9f, 0xc7, 0x8e, 0x50, 0x6c, 0x1b, 0xbb, 0xfd, 0x2c, 0xf2, 0x0c, 0x8c, 0x39, 0x26, + 0xe9, 0x6d, 0xe3, 0x20, 0xec, 0x56, 0xf2, 0x71, 0xba, 0x61, 0x6e, 0x62, 0x7b, 0x95, 0x31, 0xf5, + 0x04, 0xa5, 0xfd, 0x22, 0xc3, 0xd4, 0xf2, 0x23, 0xec, 0xf8, 0xb6, 0x19, 0xfc, 0x27, 0x26, 0x9e, + 0xdd, 0x61, 0xe2, 0xe1, 0x32, 0x13, 0xc3, 0x8c, 0x8d, 0x5f, 0xc1, 0x24, 0x35, 0x6d, 0x9d, 0x04, + 0xd8, 0x74, 0x92, 0x8c, 0x5c, 0x80, 0x66, 0x6f, 0x3b, 0x72, 0xef, 0xe7, 0x52, 0x32, 0x2d, 0x94, + 0xa5, 0x09, 0xb9, 0x18, 0x83, 0x78, 0x56, 0xb2, 0x12, 0xd7, 0xaa, 0x63, 0x23, 0x9d, 0x8a, 0xb6, + 0x0e, 0x87, 0x0b, 0x01, 0x78, 0x03, 0x19, 0xff, 0x4d, 0x06, 0x44, 0xdd, 0xb9, 0x6b, 0xda, 0x11, + 0x0e, 0x45, 0x50, 0x8f, 0x03, 0xd8, 0x31, 0xd5, 0x70, 0x4d, 0x07, 0xd3, 0x60, 0x36, 0xf4, 0x06, + 0xa5, 0xdc, 0x34, 0x1d, 0xbc, 0x4b, 0xcc, 0x47, 0x5e, 0x23, 0xe6, 0x95, 0x7d, 0x63, 0x5e, 0x3d, + 0x21, 0x0f, 0x11, 0x73, 0x34, 0x05, 0x35, 0xdb, 0x72, 0x2c, 0xd2, 0xad, 0x51, 0x8d, 0xec, 0xa0, + 0x9d, 0x83, 0xc9, 0x9c, 0x57, 0x3c, 0x52, 0x27, 0xa1, 0xc5, 0xdc, 0x7a, 0x48, 0xe9, 0x34, 0x56, + 0x0d, 0xbd, 0x69, 0xa7, 0x50, 0xed, 0x33, 0x38, 0x9a, 0x91, 0x2c, 0x64, 0x72, 0x08, 0xf9, 0xef, + 0x65, 0x98, 0xb8, 0x21, 0x02, 0x15, 0x1e, 0x74, 0x91, 0x26, 0xde, 0x57, 0xb2, 0xde, 0x7f, 0xc8, + 0x73, 0xca, 0x4d, 0xe0, 0xc6, 0xcf, 0x40, 0x33, 0xcd, 0xa9, 0xb0, 0x1d, 0x92, 0xa4, 0x86, 0xda, + 0xc7, 0xd0, 0x4d, 0xc5, 0x0a, 0x9e, 0xef, 0x2b, 0x8c, 0xa0, 0x73, 0x27, 0xc4, 0xc1, 0x3a, 0x31, + 0x89, 0xf0, 0x5a, 0xfb, 0x43, 0x86, 0x89, 0x0c, 0x91, 0xab, 0x3a, 0x25, 0x1e, 0x67, 0xcb, 0x73, + 0x8d, 0xc0, 0x24, 0xac, 0xbe, 0x64, 0x7d, 0x3c, 0xa1, 0xea, 0x26, 0xc1, 0x71, 0x09, 0xba, 0x91, + 0x63, 0xf0, 0xaa, 0x8e, 0xdd, 0xaf, 0xea, 0x0d, 0x37, 0x72, 0x58, 0x29, 0xc7, 0x11, 0x35, 0x7d, + 0xcb, 0x28, 0x68, 0xaa, 0x50, 0x4d, 0x1d, 0xd3, 0xb7, 0x56, 0x72, 0xca, 0xe6, 0x60, 0x32, 0x88, + 0x6c, 0x5c, 0x84, 0x57, 0x29, 0x7c, 0x22, 0x66, 0xe5, 0xf1, 0xff, 0x87, 0x71, 0xb3, 0x47, 0xac, + 0x87, 0x58, 0xdc, 0x5f, 0xa3, 0xf7, 0xb7, 0x18, 0x91, 0x99, 0xa0, 0x7d, 0x0d, 0x93, 0xb1, 0x77, + 0x2b, 0x97, 0xf2, 0xfe, 0x4d, 0xc3, 0x68, 0x14, 0xe2, 0xc0, 0xb0, 0xfa, 0xbc, 0x71, 0xea, 0xf1, + 0x71, 0xa5, 0x8f, 0x4e, 0x43, 0xb5, 0x6f, 0x12, 0x93, 0xfa, 0xd2, 0x5c, 0x38, 0x2a, 0x2a, 0x7b, + 0x47, 0x84, 0x74, 0x0a, 0xd3, 0xae, 0x00, 0x8a, 0x59, 0x61, 0x5e, 0xfb, 0x59, 0xa8, 0x85, 0x31, + 0x81, 0xf7, 0xf9, 0xb1, 0xac, 0x96, 0x82, 0x25, 0x3a, 0x43, 0x6a, 0x4f, 0x64, 0x50, 0x57, 0x31, + 0x09, 0xac, 0x5e, 0x78, 0xd9, 0x0b, 0xf2, 0x8d, 0x74, 0xc0, 0xf5, 0x79, 0x0e, 0x5a, 0xa2, 0x53, + 0x8d, 0x10, 0x93, 0xbd, 0x1f, 0xd2, 0xa6, 0x80, 0xae, 0x63, 0x92, 0x56, 0x76, 0x35, 0x5b, 0xd9, + 0xd7, 0x61, 0x66, 0x57, 0x4f, 0x78, 0x80, 0x66, 0xa1, 0xee, 0x50, 0x08, 0x8f, 0x50, 0x27, 0x7d, + 0x09, 0x99, 0xa8, 0xce, 0xf9, 0xda, 0x6d, 0x38, 0xb5, 0x8b, 0xb2, 0x42, 0xf1, 0x0f, 0xaf, 0xb2, + 0x0b, 0x47, 0xb8, 0xca, 0x55, 0x4c, 0xcc, 0x38, 0x8d, 0xa2, 0x17, 0xd6, 0x60, 0x7a, 0x07, 0x87, + 0xab, 0xff, 0x00, 0xc6, 0x1c, 0x4e, 0xe3, 0x17, 0x74, 0x8b, 0x17, 0x24, 0x32, 0x09, 0x52, 0xfb, + 0x47, 0x86, 0x43, 0x85, 0xd9, 0x11, 0x27, 0xe6, 0x5e, 0xe0, 0x39, 0x86, 0x58, 0x7e, 0xd2, 0x1a, + 0x6c, 0xc7, 0xf4, 0x15, 0x4e, 0x5e, 0xe9, 0x67, 0x8b, 0x74, 0x24, 0x57, 0xa4, 0x2e, 0xd4, 0x69, + 0x57, 0x8b, 0xa1, 0x37, 0x99, 0x9a, 0x42, 0x43, 0x74, 0xcb, 0xb4, 0x82, 0xa5, 0xc5, 0x78, 0x8e, + 0xfc, 0xfe, 0x7c, 0xe6, 0xb5, 0xf6, 0x26, 0x26, 0xbf, 0xd8, 0x37, 0x7d, 0x82, 0x03, 0x9d, 0xdf, + 0x82, 0xde, 0x85, 0x3a, 0x1b, 0x75, 0xdd, 0x2a, 0xbd, 0x6f, 0x5c, 0xd4, 0x46, 0x76, 0x1a, 0x72, + 0x88, 0xf6, 0xa3, 0x0c, 0x35, 0xe6, 0xe9, 0x41, 0x15, 0xac, 0x02, 0x63, 0xd8, 0xed, 0x79, 0x7d, + 0xcb, 0xdd, 0xa2, 0x8f, 0x49, 0x4d, 0x4f, 0xce, 0x08, 0xf1, 0xfe, 0x8d, 0x2b, 0xb2, 0xc5, 0x9b, + 0x74, 0x11, 0xc6, 0x73, 0x95, 0x93, 0xdb, 0x6c, 0xe4, 0xa1, 0x36, 0x1b, 0x03, 0x5a, 0x59, 0x0e, + 0x3a, 0x05, 0x55, 0xf2, 0xd8, 0x67, 0xaf, 0x62, 0x7b, 0x61, 0x42, 0x48, 0x53, 0xf6, 0xc6, 0x63, + 0x1f, 0xeb, 0x94, 0x1d, 0x5b, 0x43, 0x87, 0x33, 0x4b, 0x1f, 0xfd, 0x8e, 0x9b, 0x86, 0x4e, 0x26, + 0x6a, 0x7a, 0x43, 0x67, 0x07, 0xed, 0x07, 0x19, 0xda, 0x69, 0xa5, 0x5c, 0xb6, 0x6c, 0xfc, 0x26, + 0x0a, 0x45, 0x81, 0xb1, 0x7b, 0x96, 0x8d, 0xa9, 0x0d, 0xec, 0xba, 0xe4, 0x5c, 0x16, 0xa9, 0x77, + 0xae, 0x41, 0x23, 0x71, 0x01, 0x35, 0xa0, 0xb6, 0x7c, 0xfb, 0xce, 0xe2, 0x8d, 0x8e, 0x84, 0xc6, + 0xa1, 0x71, 0x73, 0x6d, 0xc3, 0x60, 0x47, 0x19, 0x1d, 0x82, 0xa6, 0xbe, 0x7c, 0x65, 0xf9, 0x0b, + 0x63, 0x75, 0x71, 0xe3, 0xe2, 0xd5, 0xce, 0x08, 0x42, 0xd0, 0x66, 0x84, 0x9b, 0x6b, 0x9c, 0x56, + 0x59, 0xf8, 0x6b, 0x14, 0xc6, 0x84, 0x8d, 0xe8, 0x3c, 0x54, 0x6f, 0x45, 0xe1, 0x36, 0x3a, 0x92, + 0x56, 0xea, 0xe7, 0x81, 0x45, 0x30, 0xef, 0x3c, 0x65, 0x7a, 0x07, 0x9d, 0xf5, 0x9d, 0x26, 0xa1, + 0x4b, 0xd0, 0xcc, 0x2c, 0x6c, 0xa8, 0x74, 0x57, 0x57, 0x8e, 0xe5, 0xa8, 0xf9, 0xa7, 0x41, 0x93, + 0xce, 0xc8, 0x68, 0x0d, 0xda, 0x94, 0x25, 0xb6, 0xb3, 0x10, 0xfd, 0x4f, 0x88, 0x94, 0x6d, 0xac, + 0xca, 0xf1, 0x5d, 0xb8, 0x89, 0x59, 0x57, 0xa1, 0x99, 0xd9, 0x41, 0x90, 0x92, 0x2b, 0xa0, 0xdc, + 0xa2, 0x96, 0x1a, 0x57, 0xb2, 0xee, 0x68, 0x12, 0xba, 0xcb, 0x97, 0x91, 0xec, 0x36, 0xb3, 0xa7, + 0xbe, 0x93, 0x25, 0xbc, 0x12, 0x97, 0x97, 0x01, 0xd2, 0x55, 0x01, 0x1d, 0xcd, 0x09, 0x65, 0x17, + 0x1f, 0x45, 0x29, 0x63, 0x25, 0xe6, 0xad, 0x43, 0xa7, 0xb8, 0x71, 0xec, 0xa5, 0xec, 0xc4, 0x4e, + 0x56, 0x89, 0x6d, 0x4b, 0xd0, 0x48, 0x46, 0x2a, 0xea, 0x96, 0x4c, 0x59, 0xa6, 0x6c, 0xf7, 0xf9, + 0xab, 0x49, 0xe8, 0x32, 0xb4, 0x16, 0x6d, 0x7b, 0x18, 0x35, 0x4a, 0x96, 0x13, 0x16, 0xf5, 0xd8, + 0xc9, 0xab, 0x5f, 0x1c, 0x31, 0xe8, 0xad, 0xa4, 0xb1, 0xf7, 0x1c, 0xcd, 0xca, 0xdb, 0xfb, 0xe2, + 0x92, 0xdb, 0xbe, 0x85, 0xe3, 0x7b, 0x0e, 0xb4, 0xa1, 0xef, 0x3c, 0xbd, 0x0f, 0xae, 0x24, 0xea, + 0x1b, 0x70, 0xa8, 0x30, 0xdf, 0x90, 0x5a, 0xd0, 0x52, 0x18, 0x89, 0xca, 0xcc, 0xae, 0x7c, 0xa1, + 0x77, 0xe9, 0x93, 0xa7, 0x2f, 0x54, 0xe9, 0xd9, 0x0b, 0x55, 0x7a, 0xf5, 0x42, 0x95, 0xbf, 0x1b, + 0xa8, 0xf2, 0xaf, 0x03, 0x55, 0x7e, 0x32, 0x50, 0xe5, 0xa7, 0x03, 0x55, 0xfe, 0x73, 0xa0, 0xca, + 0x7f, 0x0f, 0x54, 0xe9, 0xd5, 0x40, 0x95, 0x7f, 0x7a, 0xa9, 0x4a, 0x4f, 0x5f, 0xaa, 0xd2, 0xb3, + 0x97, 0xaa, 0xf4, 0x65, 0xbd, 0x67, 0x5b, 0xd8, 0x25, 0x9b, 0x75, 0xfa, 0x8b, 0xfe, 0xfe, 0xbf, + 0x01, 0x00, 0x00, 0xff, 0xff, 0xdd, 0xd4, 0xb0, 0x94, 0x0d, 0x10, 0x00, 0x00, } func (x MatchType) String() string { @@ -1781,6 +1806,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 { @@ -1866,6 +1894,9 @@ func (this *LabelNamesRequest) Equal(that interface{}) bool { if this.EndTimestampMs != that1.EndTimestampMs { return false } + if this.Limit != that1.Limit { + return false + } return true } func (this *LabelNamesResponse) Equal(that interface{}) bool { @@ -2072,6 +2103,9 @@ func (this *MetricsForLabelMatchersRequest) Equal(that interface{}) bool { return false } } + if this.Limit != that1.Limit { + return false + } return true } func (this *MetricsForLabelMatchersResponse) Equal(that interface{}) bool { @@ -2454,7 +2488,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") @@ -2462,6 +2496,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, "") } @@ -2489,10 +2524,11 @@ func (this *LabelNamesRequest) GoString() string { if this == nil { return "nil" } - s := make([]string, 0, 6) + s := make([]string, 0, 7) 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") + s = append(s, "Limit: "+fmt.Sprintf("%#v", this.Limit)+",\n") s = append(s, "}") return strings.Join(s, "") } @@ -2568,13 +2604,14 @@ func (this *MetricsForLabelMatchersRequest) GoString() string { if this == nil { return "nil" } - s := make([]string, 0, 7) + s := make([]string, 0, 8) s = append(s, "&client.MetricsForLabelMatchersRequest{") s = append(s, "StartTimestampMs: "+fmt.Sprintf("%#v", this.StartTimestampMs)+",\n") s = append(s, "EndTimestampMs: "+fmt.Sprintf("%#v", this.EndTimestampMs)+",\n") if this.MatchersSet != nil { s = append(s, "MatchersSet: "+fmt.Sprintf("%#v", this.MatchersSet)+",\n") } + s = append(s, "Limit: "+fmt.Sprintf("%#v", this.Limit)+",\n") s = append(s, "}") return strings.Join(s, "") } @@ -3585,6 +3622,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]) @@ -3701,6 +3743,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] = 0x18 + } if m.EndTimestampMs != 0 { i = encodeVarintIngester(dAtA, i, uint64(m.EndTimestampMs)) i-- @@ -3951,6 +3998,11 @@ func (m *MetricsForLabelMatchersRequest) MarshalToSizedBuffer(dAtA []byte) (int, _ = i var l int _ = l + if m.Limit != 0 { + i = encodeVarintIngester(dAtA, i, uint64(m.Limit)) + i-- + dAtA[i] = 0x20 + } if len(m.MatchersSet) > 0 { for iNdEx := len(m.MatchersSet) - 1; iNdEx >= 0; iNdEx-- { { @@ -4500,6 +4552,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 } @@ -4545,6 +4600,9 @@ func (m *LabelNamesRequest) Size() (n int) { if m.EndTimestampMs != 0 { n += 1 + sovIngester(uint64(m.EndTimestampMs)) } + if m.Limit != 0 { + n += 1 + sovIngester(uint64(m.Limit)) + } return n } @@ -4661,6 +4719,9 @@ func (m *MetricsForLabelMatchersRequest) Size() (n int) { n += 1 + l + sovIngester(uint64(l)) } } + if m.Limit != 0 { + n += 1 + sovIngester(uint64(m.Limit)) + } return n } @@ -4953,6 +5014,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 @@ -4984,6 +5046,7 @@ func (this *LabelNamesRequest) String() string { s := strings.Join([]string{`&LabelNamesRequest{`, `StartTimestampMs:` + fmt.Sprintf("%v", this.StartTimestampMs) + `,`, `EndTimestampMs:` + fmt.Sprintf("%v", this.EndTimestampMs) + `,`, + `Limit:` + fmt.Sprintf("%v", this.Limit) + `,`, `}`, }, "") return s @@ -5070,6 +5133,7 @@ func (this *MetricsForLabelMatchersRequest) String() string { `StartTimestampMs:` + fmt.Sprintf("%v", this.StartTimestampMs) + `,`, `EndTimestampMs:` + fmt.Sprintf("%v", this.EndTimestampMs) + `,`, `MatchersSet:` + repeatedStringForMatchersSet + `,`, + `Limit:` + fmt.Sprintf("%v", this.Limit) + `,`, `}`, }, "") return s @@ -6027,6 +6091,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:]) @@ -6288,6 +6371,25 @@ func (m *LabelNamesRequest) Unmarshal(dAtA []byte) error { break } } + case 3: + 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:]) @@ -6968,6 +7070,25 @@ func (m *MetricsForLabelMatchersRequest) 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 3965808d6a..e9db9685c1 100644 --- a/pkg/ingester/client/ingester.proto +++ b/pkg/ingester/client/ingester.proto @@ -67,6 +67,7 @@ message LabelValuesRequest { int64 start_timestamp_ms = 2; int64 end_timestamp_ms = 3; LabelMatchers matchers = 4; + int64 limit = 5; } message LabelValuesResponse { @@ -80,6 +81,7 @@ message LabelValuesStreamResponse { message LabelNamesRequest { int64 start_timestamp_ms = 1; int64 end_timestamp_ms = 2; + int64 limit = 3; } message LabelNamesResponse { @@ -113,6 +115,7 @@ message MetricsForLabelMatchersRequest { int64 start_timestamp_ms = 1; int64 end_timestamp_ms = 2; repeated LabelMatchers matchers_set = 3; + int64 limit = 4; } message MetricsForLabelMatchersResponse { diff --git a/pkg/ingester/ingester.go b/pkg/ingester/ingester.go index e6cf5d9701..9441b947ed 100644 --- a/pkg/ingester/ingester.go +++ b/pkg/ingester/ingester.go @@ -1500,7 +1500,7 @@ func (i *Ingester) labelsValuesCommon(ctx context.Context, req *client.LabelValu return nil, cleanup, err } - labelName, startTimestampMs, endTimestampMs, matchers, err := client.FromLabelValuesRequest(req) + labelName, startTimestampMs, endTimestampMs, limit, matchers, err := client.FromLabelValuesRequest(req) if err != nil { return nil, cleanup, err } @@ -1534,11 +1534,15 @@ func (i *Ingester) labelsValuesCommon(ctx context.Context, req *client.LabelValu return nil, cleanup, err } defer c() - vals, _, err := q.LabelValues(ctx, labelName, nil, matchers...) + vals, _, err := q.LabelValues(ctx, labelName, &storage.LabelHints{Limit: limit}, matchers...) if err != nil { return nil, cleanup, err } + if limit > 0 && len(vals) > limit { + vals = vals[:limit] + } + return &client.LabelValuesResponse{ LabelValues: vals, }, cleanup, nil @@ -1601,6 +1605,8 @@ func (i *Ingester) labelNamesCommon(ctx context.Context, req *client.LabelNamesR return nil, cleanup, err } + limit := int(req.Limit) + q, err := db.Querier(mint, maxt) if err != nil { return nil, cleanup, err @@ -1615,11 +1621,15 @@ func (i *Ingester) labelNamesCommon(ctx context.Context, req *client.LabelNamesR return nil, cleanup, err } defer c() - names, _, err := q.LabelNames(ctx, nil) + names, _, err := q.LabelNames(ctx, &storage.LabelHints{Limit: limit}) if err != nil { return nil, cleanup, err } + if limit > 0 && len(names) > limit { + names = names[:limit] + } + return &client.LabelNamesResponse{ LabelNames: names, }, cleanup, nil @@ -1676,7 +1686,7 @@ func (i *Ingester) metricsForLabelMatchersCommon(ctx context.Context, req *clien } // Parse the request - _, _, matchersSet, err := client.FromMetricsForLabelMatchersRequest(req) + _, _, limit, matchersSet, err := client.FromMetricsForLabelMatchersRequest(req) if err != nil { return nil, cleanup, err } @@ -1705,6 +1715,7 @@ func (i *Ingester) metricsForLabelMatchersCommon(ctx context.Context, req *clien Start: mint, End: maxt, Func: "series", // There is no series function, this token is used for lookups that don't need samples. + Limit: limit, } if len(matchersSet) > 1 { for _, matchers := range matchersSet { @@ -1735,6 +1746,9 @@ func (i *Ingester) metricsForLabelMatchersCommon(ctx context.Context, req *clien result.Metric = append(result.Metric, &cortexpb.Metric{ Labels: cortexpb.FromLabelsToLabelAdapters(mergedSet.At().Labels()), }) + if len(result.Metric) >= limit { + break + } } return result, cleanup, nil diff --git a/pkg/querier/distributor_queryable.go b/pkg/querier/distributor_queryable.go index 5bd933c209..b4d7d7ec40 100644 --- a/pkg/querier/distributor_queryable.go +++ b/pkg/querier/distributor_queryable.go @@ -27,12 +27,12 @@ import ( type Distributor interface { QueryStream(ctx context.Context, from, to model.Time, matchers ...*labels.Matcher) (*client.QueryStreamResponse, 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) - LabelValuesForLabelNameStream(ctx context.Context, from, to model.Time, label model.LabelName, matchers ...*labels.Matcher) ([]string, error) - LabelNames(context.Context, model.Time, model.Time) ([]string, error) - LabelNamesStream(context.Context, model.Time, model.Time) ([]string, error) - MetricsForLabelMatchers(ctx context.Context, from, through model.Time, matchers ...*labels.Matcher) ([]model.Metric, error) - MetricsForLabelMatchersStream(ctx context.Context, from, through model.Time, matchers ...*labels.Matcher) ([]model.Metric, error) + LabelValuesForLabelName(ctx context.Context, from, to model.Time, label model.LabelName, limit int, matchers ...*labels.Matcher) ([]string, error) + LabelValuesForLabelNameStream(ctx context.Context, from, to model.Time, label model.LabelName, limit int, matchers ...*labels.Matcher) ([]string, error) + LabelNames(context.Context, model.Time, model.Time, int) ([]string, error) + LabelNamesStream(context.Context, model.Time, model.Time, int) ([]string, error) + MetricsForLabelMatchers(ctx context.Context, from, through model.Time, limit int, matchers ...*labels.Matcher) ([]model.Metric, error) + MetricsForLabelMatchersStream(ctx context.Context, from, through model.Time, limit int, matchers ...*labels.Matcher) ([]model.Metric, error) MetricsMetadata(ctx context.Context) ([]scrape.MetricMetadata, error) } @@ -113,11 +113,12 @@ func (q *distributorQuerier) Select(ctx context.Context, sortSeries bool, sp *st ms []model.Metric err error ) + limit := getLimitFromSelectHints(sp) if q.streamingMetadata { - ms, err = q.distributor.MetricsForLabelMatchersStream(ctx, model.Time(minT), model.Time(maxT), matchers...) + ms, err = q.distributor.MetricsForLabelMatchersStream(ctx, model.Time(minT), model.Time(maxT), limit, matchers...) } else { - ms, err = q.distributor.MetricsForLabelMatchers(ctx, model.Time(minT), model.Time(maxT), matchers...) + ms, err = q.distributor.MetricsForLabelMatchers(ctx, model.Time(minT), model.Time(maxT), limit, matchers...) } if err != nil { @@ -170,10 +171,12 @@ func (q *distributorQuerier) LabelValues(ctx context.Context, name string, hints err error ) + limit := getLimitFromLabelHints(hints) + if q.streamingMetadata { - lvs, err = q.distributor.LabelValuesForLabelNameStream(ctx, model.Time(q.mint), model.Time(q.maxt), model.LabelName(name), matchers...) + lvs, err = q.distributor.LabelValuesForLabelNameStream(ctx, model.Time(q.mint), model.Time(q.maxt), model.LabelName(name), limit, matchers...) } else { - 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), limit, matchers...) } return lvs, nil, err @@ -181,7 +184,7 @@ func (q *distributorQuerier) LabelValues(ctx context.Context, name string, hints func (q *distributorQuerier) LabelNames(ctx context.Context, hints *storage.LabelHints, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) { if len(matchers) > 0 { - return q.labelNamesWithMatchers(ctx, matchers...) + return q.labelNamesWithMatchers(ctx, hints, matchers...) } log, ctx := spanlogger.New(ctx, "distributorQuerier.LabelNames") @@ -192,17 +195,19 @@ func (q *distributorQuerier) LabelNames(ctx context.Context, hints *storage.Labe err error ) + limit := getLimitFromLabelHints(hints) + if q.streamingMetadata { - ln, err = q.distributor.LabelNamesStream(ctx, model.Time(q.mint), model.Time(q.maxt)) + ln, err = q.distributor.LabelNamesStream(ctx, model.Time(q.mint), model.Time(q.maxt), limit) } else { - ln, err = q.distributor.LabelNames(ctx, model.Time(q.mint), model.Time(q.maxt)) + ln, err = q.distributor.LabelNames(ctx, model.Time(q.mint), model.Time(q.maxt), limit) } return ln, nil, err } // labelNamesWithMatchers performs the LabelNames call by calling ingester's MetricsForLabelMatchers method -func (q *distributorQuerier) labelNamesWithMatchers(ctx context.Context, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) { +func (q *distributorQuerier) labelNamesWithMatchers(ctx context.Context, hints *storage.LabelHints, matchers ...*labels.Matcher) ([]string, annotations.Annotations, error) { log, ctx := spanlogger.New(ctx, "distributorQuerier.labelNamesWithMatchers") defer log.Span.Finish() @@ -211,10 +216,12 @@ func (q *distributorQuerier) labelNamesWithMatchers(ctx context.Context, matcher err error ) + limit := getLimitFromLabelHints(hints) + if q.streamingMetadata { - ms, err = q.distributor.MetricsForLabelMatchersStream(ctx, model.Time(q.mint), model.Time(q.maxt), matchers...) + ms, err = q.distributor.MetricsForLabelMatchersStream(ctx, model.Time(q.mint), model.Time(q.maxt), limit, matchers...) } else { - ms, err = q.distributor.MetricsForLabelMatchers(ctx, model.Time(q.mint), model.Time(q.maxt), matchers...) + ms, err = q.distributor.MetricsForLabelMatchers(ctx, model.Time(q.mint), model.Time(q.maxt), limit, matchers...) } if err != nil { @@ -280,3 +287,17 @@ func (q *distributorExemplarQuerier) Select(start, end int64, matchers ...[]*lab } return ret, nil } + +func getLimitFromLabelHints(hints *storage.LabelHints) int { + if hints != nil { + return hints.Limit + } + return 0 +} + +func getLimitFromSelectHints(hints *storage.SelectHints) int { + if hints != nil { + return hints.Limit + } + return 0 +}