From a532ccd421e32bf54b234f3e4651a4ae15150066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Giedrius=20Statkevi=C4=8Dius?= Date: Mon, 26 Feb 2024 15:42:23 +0200 Subject: [PATCH] queryfrontend: fix analysis after API changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the analysis functionality with query-frontend after the recent changes. Added tests for this. Signed-off-by: Giedrius Statkevičius --- go.mod | 1 + go.sum | 2 + .../cortex/querier/queryrange/query_range.go | 161 ++++-- .../querier/queryrange/query_range_test.go | 63 ++- .../querier/queryrange/queryrange.pb.go | 518 ++++++++++++++---- .../querier/queryrange/queryrange.proto | 10 +- .../querier/queryrange/results_cache.go | 22 +- .../querier/queryrange/results_cache_test.go | 25 +- pkg/queryfrontend/queryinstant_codec.go | 35 +- pkg/queryfrontend/queryinstant_codec_test.go | 110 +++- pkg/queryfrontend/queryrange_codec.go | 9 +- pkg/queryfrontend/request.go | 4 +- test/e2e/query_frontend_test.go | 5 +- 13 files changed, 744 insertions(+), 221 deletions(-) diff --git a/go.mod b/go.mod index d5809c9a1e..2e350c3586 100644 --- a/go.mod +++ b/go.mod @@ -116,6 +116,7 @@ require ( ) require ( + dario.cat/mergo v1.0.0 github.com/mitchellh/go-ps v1.0.0 github.com/onsi/gomega v1.27.10 github.com/prometheus-community/prom-label-proxy v0.8.1-0.20240127162815-c1195f9aabc0 diff --git a/go.sum b/go.sum index d6225b7eb0..74afed96eb 100644 --- a/go.sum +++ b/go.sum @@ -603,6 +603,8 @@ cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoIS cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw= +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= diff --git a/internal/cortex/querier/queryrange/query_range.go b/internal/cortex/querier/queryrange/query_range.go index 5304f9c63d..97375f3670 100644 --- a/internal/cortex/querier/queryrange/query_range.go +++ b/internal/cortex/querier/queryrange/query_range.go @@ -12,13 +12,16 @@ import ( "math" "net/http" "net/url" + "reflect" "sort" "strconv" "strings" "time" "unsafe" + "dario.cat/mergo" "github.com/gogo/protobuf/proto" + github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" "github.com/gogo/status" jsoniter "github.com/json-iterator/go" "github.com/opentracing/opentracing-go" @@ -208,6 +211,24 @@ func NewEmptyPrometheusInstantQueryResponse() *PrometheusInstantQueryResponse { } } +type TimeDurationTransformer struct{} + +func (t TimeDurationTransformer) Transformer(typ reflect.Type) func(dst, src reflect.Value) error { + if typ == reflect.TypeOf(Duration(0)) { + return func(dst, src reflect.Value) error { + if dst.CanSet() { + d := dst.Interface().(Duration) + s := src.Interface().(Duration) + + merged := d + s + dst.Set(reflect.ValueOf(merged)) + } + return nil + } + } + return nil +} + func (prometheusCodec) MergeResponse(_ Request, responses ...Response) (Response, error) { if len(responses) == 0 { return NewEmptyPrometheusResponse(), nil @@ -225,21 +246,27 @@ func (prometheusCodec) MergeResponse(_ Request, responses ...Response) (Response // Merge the responses. sort.Sort(byFirstTime(promResponses)) - var explanation *Explanation + var analysis Analysis for i := range promResponses { - if promResponses[i].Data.GetExplanation() != nil { - explanation = promResponses[i].Data.GetExplanation() - break + if promResponses[i].Data.GetAnalysis() == nil { + continue + } + + if err := mergo.Merge(&analysis, + promResponses[i].Data.GetAnalysis(), + mergo.WithTransformers(TimeDurationTransformer{}), + ); err != nil { + return nil, err } } response := PrometheusResponse{ Status: StatusSuccess, Data: PrometheusData{ - ResultType: model.ValMatrix.String(), - Result: matrixMerge(promResponses), - Stats: StatsMerge(responses), - Explanation: explanation, + ResultType: model.ValMatrix.String(), + Result: matrixMerge(promResponses), + Stats: StatsMerge(responses), + Analysis: &analysis, }, } @@ -533,10 +560,10 @@ func (s *StringSample) UnmarshalJSON(b []byte) error { // UnmarshalJSON implements json.Unmarshaler. func (s *PrometheusInstantQueryData) UnmarshalJSON(data []byte) error { var queryData struct { - ResultType string `json:"resultType"` - Result jsoniter.RawMessage `json:"result"` - Stats *PrometheusResponseStats `json:"stats,omitempty"` - Explanation *Explanation `json:"explanation,omitempty"` + ResultType string `json:"resultType"` + Result jsoniter.RawMessage `json:"result"` + Stats *PrometheusResponseStats `json:"stats,omitempty"` + Analysis *Analysis `json:"analysis,omitempty"` } if err := json.Unmarshal(data, &queryData); err != nil { @@ -545,7 +572,7 @@ func (s *PrometheusInstantQueryData) UnmarshalJSON(data []byte) error { s.ResultType = queryData.ResultType s.Stats = queryData.Stats - s.Explanation = queryData.Explanation + s.Analysis = queryData.Analysis switch s.ResultType { case model.ValVector.String(): var result struct { @@ -605,54 +632,54 @@ func (s *PrometheusInstantQueryData) MarshalJSON() ([]byte, error) { switch s.ResultType { case model.ValVector.String(): res := struct { - ResultType string `json:"resultType"` - Data []*Sample `json:"result"` - Stats *PrometheusResponseStats `json:"stats,omitempty"` - Explanation *Explanation `json:"explanation,omitempty"` + ResultType string `json:"resultType"` + Data []*Sample `json:"result"` + Stats *PrometheusResponseStats `json:"stats,omitempty"` + Analysis *Analysis `json:"analysis,omitempty"` }{ - ResultType: s.ResultType, - Data: s.Result.GetVector().Samples, - Stats: s.Stats, - Explanation: s.Explanation, + ResultType: s.ResultType, + Data: s.Result.GetVector().Samples, + Stats: s.Stats, + Analysis: s.Analysis, } return json.Marshal(res) case model.ValMatrix.String(): res := struct { - ResultType string `json:"resultType"` - Data []*SampleStream `json:"result"` - Stats *PrometheusResponseStats `json:"stats,omitempty"` - Explanation *Explanation `json:"explanation,omitempty"` + ResultType string `json:"resultType"` + Data []*SampleStream `json:"result"` + Stats *PrometheusResponseStats `json:"stats,omitempty"` + Analysis *Analysis `json:"analysis,omitempty"` }{ - ResultType: s.ResultType, - Data: s.Result.GetMatrix().SampleStreams, - Stats: s.Stats, - Explanation: s.Explanation, + ResultType: s.ResultType, + Data: s.Result.GetMatrix().SampleStreams, + Stats: s.Stats, + Analysis: s.Analysis, } return json.Marshal(res) case model.ValScalar.String(): res := struct { - ResultType string `json:"resultType"` - Data *cortexpb.Sample `json:"result"` - Stats *PrometheusResponseStats `json:"stats,omitempty"` - Explanation *Explanation `json:"explanation,omitempty"` + ResultType string `json:"resultType"` + Data *cortexpb.Sample `json:"result"` + Stats *PrometheusResponseStats `json:"stats,omitempty"` + Analysis *Analysis `json:"analysis,omitempty"` }{ - ResultType: s.ResultType, - Data: s.Result.GetScalar(), - Stats: s.Stats, - Explanation: s.Explanation, + ResultType: s.ResultType, + Data: s.Result.GetScalar(), + Stats: s.Stats, + Analysis: s.Analysis, } return json.Marshal(res) case model.ValString.String(): res := struct { - ResultType string `json:"resultType"` - Data *StringSample `json:"result"` - Stats *PrometheusResponseStats `json:"stats,omitempty"` - Explanation *Explanation `json:"explanation,omitempty"` + ResultType string `json:"resultType"` + Data *StringSample `json:"result"` + Stats *PrometheusResponseStats `json:"stats,omitempty"` + Analysis *Analysis `json:"analysis,omitempty"` }{ - ResultType: s.ResultType, - Data: s.Result.GetStringSample(), - Stats: s.Stats, - Explanation: s.Explanation, + ResultType: s.ResultType, + Data: s.Result.GetStringSample(), + Stats: s.Stats, + Analysis: s.Analysis, } return json.Marshal(res) default: @@ -865,3 +892,47 @@ func init() { jsoniter.RegisterTypeEncoderFunc("queryrange.PrometheusResponseQueryableSamplesStatsPerStep", PrometheusResponseQueryableSamplesStatsPerStepJsoniterEncode, func(unsafe.Pointer) bool { return false }) jsoniter.RegisterTypeDecoderFunc("queryrange.PrometheusResponseQueryableSamplesStatsPerStep", PrometheusResponseQueryableSamplesStatsPerStepJsoniterDecode) } + +type Duration time.Duration + +func (d Duration) MarshalJSON() ([]byte, error) { + return json.Marshal(time.Duration(d).String()) +} + +func (d *Duration) UnmarshalJSON(b []byte) error { + var v interface{} + if err := json.Unmarshal(b, &v); err != nil { + return err + } + switch value := v.(type) { + case float64: + *d = Duration(time.Duration(value)) + return nil + case string: + tmp, err := time.ParseDuration(value) + if err != nil { + return err + } + *d = Duration(tmp) + return nil + default: + return errors.New("invalid duration") + } +} + +func (d *Duration) Size() int { + return github_com_gogo_protobuf_types.SizeOfStdDuration(time.Duration(*d)) +} + +func (d *Duration) Unmarshal(b []byte) error { + var td time.Duration + if err := github_com_gogo_protobuf_types.StdDurationUnmarshal(&td, b); err != nil { + return err + } + *d = Duration(td) + return nil +} + +func (d *Duration) MarshalTo(b []byte) (int, error) { + return github_com_gogo_protobuf_types.StdDurationMarshalTo(time.Duration(*d), b) +} diff --git a/internal/cortex/querier/queryrange/query_range_test.go b/internal/cortex/querier/queryrange/query_range_test.go index 3cf0f2fc84..978672e0db 100644 --- a/internal/cortex/querier/queryrange/query_range_test.go +++ b/internal/cortex/querier/queryrange/query_range_test.go @@ -10,6 +10,7 @@ import ( "net/http" "strconv" "testing" + "time" jsoniter "github.com/json-iterator/go" "github.com/prometheus/common/model" @@ -128,7 +129,7 @@ func TestResponseWithStats(t *testing.T) { expected *PrometheusResponse }{ { - body: `{"status":"success","data":{"resultType":"matrix","result":[{"metric":{"foo":"bar"},"values":[[1536673680,"137"],[1536673780,"137"]]}],"stats":{"samples":{"totalQueryableSamples":10,"totalQueryableSamplesPerStep":[[1536673680,5],[1536673780,5]]}},"explanation":null}}`, + body: `{"status":"success","data":{"resultType":"matrix","result":[{"metric":{"foo":"bar"},"values":[[1536673680,"137"],[1536673780,"137"]]}],"stats":{"samples":{"totalQueryableSamples":10,"totalQueryableSamplesPerStep":[[1536673680,5],[1536673780,5]]}},"analysis":null}}`, expected: &PrometheusResponse{ Status: "success", Data: PrometheusData{ @@ -156,6 +157,39 @@ func TestResponseWithStats(t *testing.T) { }, }, }, + { + body: `{"status":"success","data":{"resultType":"matrix","result":[{"metric":{"foo":"bar"},"values":[[1536673680,"137"],[1536673780,"137"]]}],"stats":{"samples":{"totalQueryableSamples":10,"totalQueryableSamplesPerStep":[[1536673680,5],[1536673780,5]]}},"analysis":{"name":"[noArgFunction]","executionTime":"1s","children":null}}}`, + expected: &PrometheusResponse{ + Status: "success", + Data: PrometheusData{ + Analysis: &Analysis{ + Name: "[noArgFunction]", + ExecutionTime: Duration(1 * time.Second), + }, + ResultType: model.ValMatrix.String(), + Result: []SampleStream{ + { + Labels: []cortexpb.LabelAdapter{ + {Name: "foo", Value: "bar"}, + }, + Samples: []cortexpb.Sample{ + {Value: 137, TimestampMs: 1536673680000}, + {Value: 137, TimestampMs: 1536673780000}, + }, + }, + }, + Stats: &PrometheusResponseStats{ + Samples: &PrometheusResponseSamplesStats{ + TotalQueryableSamples: 10, + TotalQueryableSamplesPerStep: []*PrometheusResponseQueryableSamplesStatsPerStep{ + {Value: 5, TimestampMs: 1536673680000}, + {Value: 5, TimestampMs: 1536673780000}, + }, + }, + }, + }, + }, + }, } { t.Run(strconv.Itoa(i), func(t *testing.T) { tc.expected.Headers = respHeaders @@ -195,6 +229,7 @@ func TestMergeAPIResponses(t *testing.T) { Status: StatusSuccess, Data: PrometheusData{ ResultType: matrix, + Analysis: (*Analysis)(nil), Result: []SampleStream{}, }, }, @@ -214,6 +249,7 @@ func TestMergeAPIResponses(t *testing.T) { Status: StatusSuccess, Data: PrometheusData{ ResultType: matrix, + Analysis: &Analysis{}, Result: []SampleStream{}, }, }, @@ -239,6 +275,7 @@ func TestMergeAPIResponses(t *testing.T) { Status: StatusSuccess, Data: PrometheusData{ ResultType: matrix, + Analysis: &Analysis{}, Result: []SampleStream{}, }, }, @@ -250,6 +287,10 @@ func TestMergeAPIResponses(t *testing.T) { &PrometheusResponse{ Data: PrometheusData{ ResultType: matrix, + Analysis: &Analysis{ + Name: "foo", + ExecutionTime: Duration(1 * time.Second), + }, Result: []SampleStream{ { Labels: []cortexpb.LabelAdapter{}, @@ -264,6 +305,10 @@ func TestMergeAPIResponses(t *testing.T) { &PrometheusResponse{ Data: PrometheusData{ ResultType: matrix, + Analysis: &Analysis{ + Name: "foo", + ExecutionTime: Duration(1 * time.Second), + }, Result: []SampleStream{ { Labels: []cortexpb.LabelAdapter{}, @@ -280,6 +325,10 @@ func TestMergeAPIResponses(t *testing.T) { Status: StatusSuccess, Data: PrometheusData{ ResultType: matrix, + Analysis: &Analysis{ + Name: "foo", + ExecutionTime: Duration(2 * time.Second), + }, Result: []SampleStream{ { Labels: []cortexpb.LabelAdapter{}, @@ -305,6 +354,7 @@ func TestMergeAPIResponses(t *testing.T) { Status: StatusSuccess, Data: PrometheusData{ ResultType: matrix, + Analysis: &Analysis{}, Result: []SampleStream{ { Labels: []cortexpb.LabelAdapter{{Name: "a", Value: "b"}, {Name: "c", Value: "d"}}, @@ -330,6 +380,7 @@ func TestMergeAPIResponses(t *testing.T) { Status: StatusSuccess, Data: PrometheusData{ ResultType: matrix, + Analysis: &Analysis{}, Result: []SampleStream{ { Labels: []cortexpb.LabelAdapter{{Name: "a", Value: "b"}, {Name: "c", Value: "d"}}, @@ -352,6 +403,7 @@ func TestMergeAPIResponses(t *testing.T) { expected: &PrometheusResponse{ Status: StatusSuccess, Data: PrometheusData{ + Analysis: &Analysis{}, ResultType: matrix, Result: []SampleStream{ { @@ -378,6 +430,7 @@ func TestMergeAPIResponses(t *testing.T) { Status: StatusSuccess, Data: PrometheusData{ ResultType: matrix, + Analysis: &Analysis{}, Result: []SampleStream{ { Labels: []cortexpb.LabelAdapter{{Name: "a", Value: "b"}, {Name: "c", Value: "d"}}, @@ -407,6 +460,7 @@ func TestMergeAPIResponses(t *testing.T) { Status: StatusSuccess, Data: PrometheusData{ ResultType: matrix, + Analysis: &Analysis{}, Result: []SampleStream{}, Stats: &PrometheusResponseStats{Samples: &PrometheusResponseSamplesStats{}}, }, @@ -434,6 +488,7 @@ func TestMergeAPIResponses(t *testing.T) { expected: &PrometheusResponse{ Status: StatusSuccess, Data: PrometheusData{ + Analysis: &Analysis{}, ResultType: matrix, Result: []SampleStream{}, Stats: &PrometheusResponseStats{Samples: &PrometheusResponseSamplesStats{}}, @@ -467,6 +522,7 @@ func TestMergeAPIResponses(t *testing.T) { }, &PrometheusResponse{ Data: PrometheusData{ + Analysis: &Analysis{}, ResultType: matrix, Result: []SampleStream{ { @@ -490,6 +546,7 @@ func TestMergeAPIResponses(t *testing.T) { expected: &PrometheusResponse{ Status: StatusSuccess, Data: PrometheusData{ + Analysis: &Analysis{}, ResultType: matrix, Result: []SampleStream{ { @@ -524,6 +581,7 @@ func TestMergeAPIResponses(t *testing.T) { Status: StatusSuccess, Data: PrometheusData{ ResultType: matrix, + Analysis: &Analysis{}, Result: []SampleStream{ { Labels: []cortexpb.LabelAdapter{{Name: "a", Value: "b"}, {Name: "c", Value: "d"}}, @@ -556,6 +614,7 @@ func TestMergeAPIResponses(t *testing.T) { Status: StatusSuccess, Data: PrometheusData{ ResultType: matrix, + Analysis: &Analysis{}, Result: []SampleStream{ { Labels: []cortexpb.LabelAdapter{{Name: "a", Value: "b"}, {Name: "c", Value: "d"}}, @@ -595,6 +654,7 @@ func TestMergeAPIResponses(t *testing.T) { Status: StatusSuccess, Data: PrometheusData{ ResultType: matrix, + Analysis: &Analysis{}, Result: []SampleStream{ { Labels: []cortexpb.LabelAdapter{{Name: "a", Value: "b"}, {Name: "c", Value: "d"}}, @@ -630,6 +690,7 @@ func TestMergeAPIResponses(t *testing.T) { Status: StatusSuccess, Data: PrometheusData{ ResultType: matrix, + Analysis: &Analysis{}, Result: []SampleStream{ { Labels: []cortexpb.LabelAdapter{{Name: "a", Value: "b"}, {Name: "c", Value: "d"}}, diff --git a/internal/cortex/querier/queryrange/queryrange.pb.go b/internal/cortex/querier/queryrange/queryrange.pb.go index 0b97731181..db9699fd28 100644 --- a/internal/cortex/querier/queryrange/queryrange.pb.go +++ b/internal/cortex/querier/queryrange/queryrange.pb.go @@ -336,7 +336,7 @@ type PrometheusData struct { ResultType string `protobuf:"bytes,1,opt,name=ResultType,proto3" json:"resultType"` Result []SampleStream `protobuf:"bytes,2,rep,name=Result,proto3" json:"result"` Stats *PrometheusResponseStats `protobuf:"bytes,3,opt,name=stats,proto3" json:"stats,omitempty"` - Explanation *Explanation `protobuf:"bytes,4,opt,name=Explanation,proto3" json:"explanation"` + Analysis *Analysis `protobuf:"bytes,4,opt,name=analysis,proto3" json:"analysis"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -396,9 +396,9 @@ func (m *PrometheusData) GetStats() *PrometheusResponseStats { return nil } -func (m *PrometheusData) GetExplanation() *Explanation { +func (m *PrometheusData) GetAnalysis() *Analysis { if m != nil { - return m.Explanation + return m.Analysis } return nil } @@ -486,7 +486,7 @@ type PrometheusInstantQueryData struct { ResultType string `protobuf:"bytes,1,opt,name=ResultType,proto3" json:"resultType"` Result PrometheusInstantQueryResult `protobuf:"bytes,2,opt,name=Result,proto3" json:"result"` Stats *PrometheusResponseStats `protobuf:"bytes,3,opt,name=stats,proto3" json:"stats,omitempty"` - Explanation *Explanation `protobuf:"bytes,4,opt,name=Explanation,proto3" json:"explanation"` + Analysis *Analysis `protobuf:"bytes,4,opt,name=analysis,proto3" json:"analysis"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -546,9 +546,9 @@ func (m *PrometheusInstantQueryData) GetStats() *PrometheusResponseStats { return nil } -func (m *PrometheusInstantQueryData) GetExplanation() *Explanation { +func (m *PrometheusInstantQueryData) GetAnalysis() *Analysis { if m != nil { - return m.Explanation + return m.Analysis } return nil } @@ -1516,6 +1516,62 @@ func (m *Explanation) GetChildren() []*Explanation { return nil } +type Analysis struct { + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name"` + ExecutionTime Duration `protobuf:"bytes,2,opt,name=executionTime,proto3,customtype=Duration" json:"executionTime"` + Children []*Analysis `protobuf:"bytes,3,rep,name=children,proto3" json:"children"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *Analysis) Reset() { *m = Analysis{} } +func (m *Analysis) String() string { return proto.CompactTextString(m) } +func (*Analysis) ProtoMessage() {} +func (*Analysis) Descriptor() ([]byte, []int) { + return fileDescriptor_9af7607b46ac39b7, []int{23} +} +func (m *Analysis) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Analysis) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Analysis.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Analysis) XXX_Merge(src proto.Message) { + xxx_messageInfo_Analysis.Merge(m, src) +} +func (m *Analysis) XXX_Size() int { + return m.Size() +} +func (m *Analysis) XXX_DiscardUnknown() { + xxx_messageInfo_Analysis.DiscardUnknown(m) +} + +var xxx_messageInfo_Analysis proto.InternalMessageInfo + +func (m *Analysis) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *Analysis) GetChildren() []*Analysis { + if m != nil { + return m.Children + } + return nil +} + func init() { proto.RegisterType((*PrometheusRequestHeader)(nil), "queryrange.PrometheusRequestHeader") proto.RegisterType((*PrometheusRequest)(nil), "queryrange.PrometheusRequest") @@ -1540,6 +1596,7 @@ func init() { proto.RegisterType((*Extent)(nil), "queryrange.Extent") proto.RegisterType((*CachingOptions)(nil), "queryrange.CachingOptions") proto.RegisterType((*Explanation)(nil), "queryrange.Explanation") + proto.RegisterType((*Analysis)(nil), "queryrange.Analysis") } func init() { @@ -1547,97 +1604,100 @@ func init() { } var fileDescriptor_9af7607b46ac39b7 = []byte{ - // 1427 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x58, 0xcd, 0x73, 0x1b, 0xc5, - 0x12, 0xcf, 0x4a, 0xf2, 0x5a, 0x6a, 0xf9, 0xd9, 0xc9, 0x38, 0xef, 0x45, 0xf6, 0xf3, 0xf3, 0xea, - 0x6d, 0x28, 0xca, 0x84, 0x44, 0xaa, 0x32, 0x15, 0x0e, 0xa9, 0x22, 0xe0, 0x25, 0x01, 0x27, 0x95, - 0x0f, 0x67, 0x9c, 0xca, 0x81, 0x4b, 0x6a, 0x24, 0x0d, 0xd2, 0x92, 0xd5, 0xee, 0x66, 0x76, 0x36, - 0xd8, 0x37, 0xfe, 0x08, 0x0e, 0x9c, 0x28, 0xa8, 0xe2, 0x42, 0x15, 0x7f, 0x01, 0x37, 0x6e, 0x39, - 0x72, 0xe6, 0xb0, 0x50, 0x39, 0xee, 0x89, 0x3f, 0x81, 0x9a, 0x8f, 0xd5, 0xce, 0xca, 0x1f, 0x29, - 0x17, 0x17, 0xe0, 0x62, 0xcd, 0xf4, 0xd7, 0x74, 0xff, 0xba, 0xa7, 0xb7, 0xc7, 0x70, 0x65, 0x18, - 0x31, 0x4e, 0x0f, 0xfa, 0xcf, 0x53, 0xca, 0x7c, 0xca, 0xe4, 0xef, 0x21, 0x23, 0xe1, 0x98, 0x1a, - 0xcb, 0x5e, 0xcc, 0x22, 0x1e, 0x21, 0x28, 0x29, 0xeb, 0x17, 0xc7, 0xd1, 0x38, 0x92, 0xe4, 0xbe, - 0x58, 0x29, 0x89, 0xf5, 0xcd, 0x71, 0x14, 0x8d, 0x03, 0xda, 0x97, 0xbb, 0x41, 0xfa, 0x69, 0x7f, - 0x94, 0x32, 0xc2, 0xfd, 0x28, 0xd4, 0xfc, 0x0d, 0x7d, 0x9a, 0xfa, 0x89, 0x07, 0x7a, 0xa1, 0xb9, - 0x6b, 0xf3, 0xda, 0x24, 0x3c, 0x54, 0x2c, 0x77, 0x1f, 0x2e, 0xed, 0xb1, 0x68, 0x4a, 0xf9, 0x84, - 0xa6, 0x09, 0xa6, 0xcf, 0x53, 0x9a, 0xf0, 0x5d, 0x4a, 0x46, 0x94, 0xa1, 0x35, 0x68, 0x3c, 0x20, - 0x53, 0xda, 0xb1, 0xba, 0xd6, 0x56, 0xcb, 0x5b, 0xc8, 0x33, 0xc7, 0xba, 0x86, 0x25, 0x09, 0xfd, - 0x0f, 0xec, 0x27, 0x24, 0x48, 0x69, 0xd2, 0xa9, 0x75, 0xeb, 0x25, 0x53, 0x13, 0xdd, 0xac, 0x06, - 0x17, 0x8e, 0x58, 0x45, 0x08, 0x1a, 0x31, 0xe1, 0x13, 0x65, 0x0f, 0xcb, 0x35, 0xba, 0x08, 0x0b, - 0x09, 0x27, 0x8c, 0x77, 0x6a, 0x5d, 0x6b, 0xab, 0x8e, 0xd5, 0x06, 0x9d, 0x87, 0x3a, 0x0d, 0x47, - 0x9d, 0xba, 0xa4, 0x89, 0xa5, 0xd0, 0x4d, 0x38, 0x8d, 0x3b, 0x0d, 0x49, 0x92, 0x6b, 0xf4, 0x1e, - 0x2c, 0x72, 0x7f, 0x4a, 0xa3, 0x94, 0x77, 0x16, 0xba, 0xd6, 0x56, 0x7b, 0x7b, 0xad, 0xa7, 0xe2, - 0xec, 0x15, 0x71, 0xf6, 0x6e, 0x69, 0x94, 0xbc, 0xe6, 0xcb, 0xcc, 0x39, 0xf7, 0xd5, 0xaf, 0x8e, - 0x85, 0x0b, 0x1d, 0x71, 0xb4, 0x84, 0xbd, 0x63, 0x4b, 0x7f, 0xd4, 0x06, 0xed, 0xc2, 0xf2, 0x90, - 0x0c, 0x27, 0x7e, 0x38, 0x7e, 0x18, 0x0b, 0xcd, 0xa4, 0xb3, 0x28, 0x6d, 0xaf, 0xf7, 0x8c, 0xac, - 0x7d, 0x58, 0x91, 0xf0, 0x1a, 0xc2, 0x38, 0x9e, 0xd3, 0x43, 0xb7, 0x60, 0x51, 0x01, 0x99, 0x74, - 0x9a, 0xdd, 0xfa, 0x56, 0x7b, 0xfb, 0xb2, 0x69, 0xe2, 0x04, 0xd0, 0x0b, 0x24, 0x0b, 0x55, 0x0d, - 0x10, 0x4f, 0x3a, 0x2d, 0xe5, 0xa5, 0xdc, 0xb8, 0x8f, 0xa1, 0x63, 0x1a, 0x48, 0xe2, 0x28, 0x4c, - 0xe8, 0x9f, 0x4e, 0xdb, 0xf7, 0x35, 0x40, 0x47, 0xcd, 0x22, 0x17, 0xec, 0x7d, 0x4e, 0x78, 0x9a, - 0x68, 0x93, 0x90, 0x67, 0x8e, 0x9d, 0x48, 0x0a, 0xd6, 0x1c, 0xf4, 0x11, 0x34, 0x6e, 0x11, 0x4e, - 0x64, 0x1a, 0xe7, 0xc0, 0x2a, 0x2d, 0x0a, 0x09, 0xef, 0x3f, 0x02, 0xac, 0x3c, 0x73, 0x96, 0x47, - 0x84, 0x93, 0xab, 0xd1, 0xd4, 0xe7, 0x74, 0x1a, 0xf3, 0x43, 0x2c, 0xf5, 0xd1, 0x75, 0x68, 0xdd, - 0x66, 0x2c, 0x62, 0x8f, 0x0f, 0x63, 0x2a, 0xf3, 0xdf, 0xf2, 0x2e, 0xe5, 0x99, 0xb3, 0x4a, 0x0b, - 0xa2, 0xa1, 0x51, 0x4a, 0xa2, 0xb7, 0x60, 0x41, 0x6e, 0x64, 0x7d, 0xb4, 0xbc, 0xd5, 0x3c, 0x73, - 0x56, 0xa4, 0x8a, 0x21, 0xae, 0x24, 0xd0, 0xed, 0x32, 0x2d, 0x0b, 0x32, 0x2d, 0x6f, 0x9c, 0x94, - 0x16, 0x13, 0xd5, 0xf9, 0xbc, 0xb8, 0x5f, 0xd7, 0x60, 0xb9, 0x1a, 0x19, 0xea, 0x01, 0x60, 0x9a, - 0xa4, 0x01, 0x97, 0xce, 0x2b, 0xac, 0x96, 0xf3, 0xcc, 0x01, 0x36, 0xa3, 0x62, 0x43, 0x02, 0x7d, - 0x00, 0xb6, 0xda, 0xc9, 0x6c, 0xb4, 0xb7, 0x3b, 0xa6, 0x23, 0xfb, 0x64, 0x1a, 0x07, 0x74, 0x9f, - 0x33, 0x4a, 0xa6, 0xde, 0xb2, 0xc6, 0xcc, 0x56, 0x96, 0xb0, 0xd6, 0x43, 0x0f, 0x8a, 0xe2, 0xa8, - 0x4b, 0xd8, 0x2f, 0x9f, 0x1e, 0x89, 0x48, 0x55, 0xa2, 0xb0, 0x91, 0x5a, 0x26, 0x36, 0x92, 0x80, - 0xee, 0x42, 0xfb, 0xf6, 0x41, 0x1c, 0x90, 0x50, 0x5e, 0x1a, 0x09, 0x66, 0x7b, 0xfb, 0x92, 0x69, - 0xd5, 0x60, 0x7b, 0x2b, 0x79, 0xe6, 0xb4, 0x69, 0x49, 0xc0, 0xa6, 0xb2, 0xfb, 0x53, 0x0d, 0x36, - 0x4b, 0x1f, 0xee, 0x84, 0x09, 0x27, 0x21, 0x7f, 0x24, 0x2c, 0x9d, 0xa9, 0xb0, 0x70, 0xa5, 0xb0, - 0xde, 0x3c, 0x3e, 0x42, 0xd3, 0xfa, 0x3f, 0xa9, 0xc8, 0x7e, 0xac, 0xc1, 0xfa, 0xc9, 0x51, 0x9e, - 0xb9, 0xe0, 0xf6, 0x8c, 0x82, 0x13, 0x68, 0x6e, 0xbd, 0x1e, 0x4d, 0x25, 0xff, 0xb7, 0x2c, 0xc0, - 0xdf, 0x2d, 0xd8, 0x38, 0x2d, 0x28, 0x74, 0x05, 0xec, 0x64, 0x48, 0x02, 0xc2, 0x24, 0x74, 0xed, - 0xed, 0xf3, 0xbd, 0xe2, 0xeb, 0xa9, 0x6f, 0xdf, 0xee, 0x39, 0xac, 0x25, 0xd0, 0x4d, 0x58, 0x4a, - 0x38, 0xf3, 0xc3, 0xb1, 0xe2, 0x68, 0x00, 0xab, 0x37, 0xd6, 0xe0, 0xef, 0x9e, 0xc3, 0x15, 0x79, - 0x74, 0x15, 0xec, 0x17, 0x74, 0xc8, 0x23, 0xa6, 0x91, 0x42, 0xa6, 0xe6, 0x13, 0xc9, 0x11, 0xa7, - 0x29, 0x19, 0x21, 0x3d, 0x25, 0x9c, 0xf9, 0x07, 0x1a, 0x81, 0x8a, 0xf4, 0x7d, 0xc9, 0x11, 0xd2, - 0x4a, 0xc6, 0x6b, 0x82, 0x4e, 0x8b, 0xfb, 0x2e, 0xd8, 0x4f, 0x0a, 0x0b, 0x8b, 0x89, 0x3c, 0x59, - 0xdc, 0xad, 0xfa, 0xbc, 0x09, 0xe5, 0x14, 0x2e, 0x44, 0xdc, 0x5d, 0xb0, 0x95, 0x55, 0x74, 0x13, - 0xfe, 0x95, 0x18, 0x9d, 0xa7, 0xd0, 0x3e, 0xb1, 0x35, 0xe1, 0xaa, 0xb8, 0x1b, 0x54, 0xc7, 0x09, - 0x23, 0xef, 0xe8, 0x91, 0xe9, 0x92, 0x88, 0xea, 0xca, 0x6b, 0xaa, 0x45, 0x09, 0xab, 0xa2, 0x69, - 0xe7, 0x99, 0x53, 0xa8, 0x97, 0x7e, 0x7f, 0x59, 0xe9, 0x31, 0xc7, 0x29, 0xa2, 0x87, 0xf0, 0x6f, - 0x1e, 0x71, 0x12, 0xc8, 0xc4, 0x93, 0x41, 0x50, 0x70, 0xa5, 0x0f, 0x75, 0x6f, 0x2d, 0xcf, 0x9c, - 0xe3, 0x05, 0xf0, 0xf1, 0x64, 0xf4, 0x8d, 0x05, 0x1b, 0xc7, 0x72, 0xf6, 0x28, 0xdb, 0x17, 0x23, - 0x8a, 0x6a, 0xe6, 0x37, 0x4e, 0x0f, 0x6e, 0x5e, 0x59, 0x3a, 0xab, 0x2d, 0x78, 0xdd, 0x3c, 0x73, - 0x4e, 0x3d, 0x03, 0x9f, 0xca, 0x75, 0x7d, 0x38, 0xe3, 0x89, 0x62, 0xca, 0x78, 0x21, 0x66, 0x00, - 0x85, 0x0a, 0x56, 0x1b, 0xf4, 0x7f, 0x58, 0x12, 0xc3, 0x52, 0xc2, 0xc9, 0x34, 0x7e, 0x3a, 0x4d, - 0xf4, 0x8c, 0xd6, 0x9e, 0xd1, 0xee, 0x27, 0xee, 0xb7, 0x35, 0x58, 0x32, 0xeb, 0x01, 0x7d, 0x61, - 0x81, 0x1d, 0x90, 0x01, 0x0d, 0x8a, 0xd2, 0x59, 0x2d, 0x6f, 0xd5, 0x3d, 0x41, 0xdf, 0x23, 0x3e, - 0xf3, 0xf6, 0x45, 0x3f, 0xf9, 0x25, 0x73, 0x76, 0xc6, 0x3e, 0x9f, 0xa4, 0x83, 0xde, 0x30, 0x9a, - 0xf6, 0xf9, 0x84, 0x84, 0x51, 0x72, 0xcd, 0x8f, 0xf4, 0xaa, 0xef, 0x87, 0x9c, 0xb2, 0x90, 0x04, - 0xfd, 0xb9, 0xd9, 0x56, 0xd9, 0xd9, 0x19, 0x91, 0x98, 0x53, 0x26, 0x9a, 0xd2, 0x94, 0x72, 0xe6, - 0x0f, 0xb1, 0x3e, 0x17, 0xdd, 0x28, 0x0b, 0x4d, 0xe5, 0xe2, 0xc8, 0xc5, 0x2e, 0xfb, 0x99, 0x0c, - 0xb4, 0xac, 0x28, 0x84, 0x01, 0x26, 0x7e, 0xc2, 0xa3, 0x31, 0x13, 0xc5, 0x5f, 0x97, 0xea, 0xce, - 0xd1, 0xe2, 0xdf, 0x2d, 0x64, 0x64, 0x34, 0x17, 0xb4, 0xb5, 0xd6, 0x4c, 0x15, 0x1b, 0x56, 0xdc, - 0xef, 0x6a, 0x60, 0xeb, 0x36, 0xf0, 0x17, 0x40, 0xe7, 0x6d, 0x68, 0xab, 0x60, 0xe5, 0xd0, 0x27, - 0x73, 0x6a, 0x79, 0xad, 0x3c, 0x73, 0x54, 0xd2, 0xb1, 0xc9, 0x45, 0x1b, 0xd0, 0x9a, 0x65, 0x5b, - 0x8f, 0xe3, 0x25, 0x01, 0xdd, 0x83, 0x32, 0x62, 0xdd, 0xa9, 0xfe, 0x7b, 0x0a, 0x56, 0x12, 0x27, - 0xab, 0x8a, 0x53, 0xb9, 0x74, 0x3f, 0x86, 0x25, 0xb3, 0x85, 0x56, 0x6b, 0xb2, 0x75, 0x86, 0x9a, - 0xe4, 0xb0, 0x7a, 0x4c, 0x96, 0xaa, 0xb1, 0x58, 0xf3, 0xb1, 0xbc, 0x6f, 0xc6, 0x52, 0x7b, 0x7d, - 0x2c, 0x6a, 0xe6, 0x37, 0xdc, 0x8f, 0x61, 0x65, 0x4e, 0x46, 0x44, 0x30, 0x8c, 0xd2, 0x90, 0xcb, - 0xd3, 0x2c, 0xac, 0x36, 0xe2, 0x71, 0x93, 0xa4, 0xea, 0x0c, 0x0b, 0x8b, 0x25, 0xba, 0x0e, 0x8b, - 0x83, 0x74, 0xf8, 0x8c, 0xf2, 0xa2, 0xe2, 0x2a, 0x27, 0x97, 0x67, 0x4a, 0x19, 0x5c, 0xc8, 0xba, - 0x09, 0xac, 0xcc, 0xf1, 0xd0, 0x26, 0xc0, 0x20, 0x4a, 0xc3, 0x11, 0x61, 0xbe, 0x6e, 0x71, 0x0b, - 0xd8, 0xa0, 0x08, 0x8f, 0x82, 0xe8, 0x73, 0xca, 0xf4, 0xe9, 0x6a, 0x23, 0xa8, 0x69, 0x1c, 0x53, - 0xf5, 0x6d, 0xb2, 0xb0, 0xda, 0x94, 0xde, 0x37, 0x0c, 0xef, 0xdd, 0xcf, 0x60, 0x59, 0xbc, 0x7e, - 0xe8, 0x68, 0x36, 0xc5, 0xad, 0x41, 0xfd, 0x19, 0x3d, 0xd4, 0xe3, 0xc7, 0x62, 0x9e, 0x39, 0x62, - 0x8b, 0xc5, 0x1f, 0xf1, 0x42, 0xa3, 0x07, 0x9c, 0x86, 0xbc, 0xb8, 0x89, 0xa8, 0xfa, 0x29, 0x17, - 0x2c, 0x6f, 0x45, 0xdf, 0x9e, 0x42, 0x14, 0x17, 0x0b, 0xf7, 0x07, 0x0b, 0x6c, 0x25, 0x84, 0x9c, - 0xe2, 0x9d, 0xa8, 0xda, 0xb6, 0xac, 0x57, 0x49, 0x28, 0x9e, 0x8c, 0x6b, 0xea, 0xc9, 0x28, 0xcb, - 0x41, 0x79, 0x41, 0xc3, 0x91, 0x7a, 0x3b, 0x76, 0xa1, 0xc9, 0x19, 0x19, 0xd2, 0xa7, 0xfe, 0x48, - 0x8f, 0x6e, 0xc5, 0x9c, 0x25, 0xc9, 0x77, 0x46, 0xe8, 0x26, 0x34, 0x99, 0x0e, 0x47, 0x3f, 0x25, - 0x2f, 0x1e, 0x79, 0x4a, 0xee, 0x84, 0x87, 0xde, 0x52, 0x9e, 0x39, 0x33, 0x49, 0x3c, 0x5b, 0xdd, - 0x6d, 0x34, 0xeb, 0xe7, 0x1b, 0xee, 0x55, 0x05, 0x8d, 0xf1, 0x04, 0x5c, 0x87, 0xe6, 0xc8, 0x4f, - 0x44, 0xd3, 0x1d, 0x49, 0xc7, 0x9b, 0x78, 0xb6, 0x77, 0xc3, 0xca, 0xa8, 0x83, 0x36, 0xa0, 0x11, - 0x96, 0xaf, 0xb6, 0x66, 0x9e, 0x39, 0x72, 0x8f, 0xe5, 0x5f, 0xb4, 0x03, 0xcd, 0xe1, 0xc4, 0x0f, - 0x46, 0x8c, 0x86, 0x1a, 0xc9, 0x13, 0x87, 0x22, 0xe9, 0x63, 0x21, 0x8c, 0x67, 0x2b, 0xaf, 0xf3, - 0xf2, 0xd5, 0xa6, 0xf5, 0xf3, 0xab, 0x4d, 0xeb, 0xb7, 0x57, 0x9b, 0xd6, 0x27, 0xc6, 0x7f, 0x1c, - 0x06, 0xb6, 0x8c, 0xf1, 0x9d, 0x3f, 0x02, 0x00, 0x00, 0xff, 0xff, 0x6b, 0x8e, 0x21, 0xfd, 0xb2, - 0x10, 0x00, 0x00, + // 1482 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x58, 0x4f, 0x6f, 0x1c, 0xc5, + 0x12, 0xcf, 0xec, 0xae, 0xd7, 0xbb, 0xb5, 0x8e, 0x9d, 0xb4, 0xfd, 0x5e, 0xd6, 0x7e, 0x7e, 0x1e, + 0x67, 0xf2, 0xf4, 0x64, 0x42, 0xb2, 0x96, 0x8c, 0xc2, 0x21, 0x12, 0x01, 0x0f, 0x31, 0x38, 0x28, + 0x7f, 0x9c, 0x76, 0x94, 0x03, 0x97, 0xa8, 0x77, 0xb7, 0x59, 0x0f, 0x99, 0x9d, 0x99, 0x74, 0xf7, + 0x04, 0xfb, 0xc6, 0x67, 0x40, 0x1c, 0x38, 0x82, 0xc4, 0x05, 0x09, 0xf1, 0x1d, 0xb8, 0xe5, 0xc0, + 0x81, 0x33, 0x87, 0x01, 0xe5, 0xb8, 0x27, 0x3e, 0x02, 0xea, 0x3f, 0xb3, 0xd3, 0xb3, 0xb6, 0xd7, + 0xb2, 0xb8, 0x00, 0x17, 0x6f, 0x77, 0xfd, 0xeb, 0xaa, 0x5f, 0x55, 0xd7, 0x54, 0x1b, 0xae, 0xf7, + 0x62, 0x26, 0xe8, 0xe1, 0xe6, 0x8b, 0x94, 0xb2, 0x80, 0x32, 0xf5, 0x7b, 0xc4, 0x48, 0x34, 0xa0, + 0xd6, 0xb2, 0x93, 0xb0, 0x58, 0xc4, 0x08, 0x0a, 0xca, 0xca, 0xd2, 0x20, 0x1e, 0xc4, 0x8a, 0xbc, + 0x29, 0x57, 0x5a, 0x62, 0x65, 0x6d, 0x10, 0xc7, 0x83, 0x90, 0x6e, 0xaa, 0x5d, 0x37, 0xfd, 0x64, + 0xb3, 0x9f, 0x32, 0x22, 0x82, 0x38, 0x32, 0xfc, 0x55, 0x73, 0x9a, 0xfe, 0x49, 0xba, 0x66, 0x61, + 0xb8, 0xcb, 0x93, 0xda, 0x24, 0x3a, 0xd2, 0x2c, 0x6f, 0x1f, 0xae, 0xec, 0xb1, 0x78, 0x48, 0xc5, + 0x01, 0x4d, 0x39, 0xa6, 0x2f, 0x52, 0xca, 0xc5, 0x2e, 0x25, 0x7d, 0xca, 0xd0, 0x32, 0xd4, 0x1e, + 0x92, 0x21, 0x6d, 0x3b, 0xeb, 0xce, 0x46, 0xd3, 0x9f, 0x19, 0x65, 0xae, 0x73, 0x13, 0x2b, 0x12, + 0xfa, 0x2f, 0xd4, 0x9f, 0x92, 0x30, 0xa5, 0xbc, 0x5d, 0x59, 0xaf, 0x16, 0x4c, 0x43, 0xf4, 0xb2, + 0x0a, 0x5c, 0x3e, 0x66, 0x15, 0x21, 0xa8, 0x25, 0x44, 0x1c, 0x68, 0x7b, 0x58, 0xad, 0xd1, 0x12, + 0xcc, 0x70, 0x41, 0x98, 0x68, 0x57, 0xd6, 0x9d, 0x8d, 0x2a, 0xd6, 0x1b, 0x74, 0x09, 0xaa, 0x34, + 0xea, 0xb7, 0xab, 0x8a, 0x26, 0x97, 0x52, 0x97, 0x0b, 0x9a, 0xb4, 0x6b, 0x8a, 0xa4, 0xd6, 0xe8, + 0x1d, 0x98, 0x15, 0xc1, 0x90, 0xc6, 0xa9, 0x68, 0xcf, 0xac, 0x3b, 0x1b, 0xad, 0xad, 0xe5, 0x8e, + 0x8e, 0xb3, 0x93, 0xc7, 0xd9, 0xb9, 0x6b, 0x50, 0xf2, 0x1b, 0xaf, 0x32, 0xf7, 0xc2, 0x57, 0xbf, + 0xba, 0x0e, 0xce, 0x75, 0xe4, 0xd1, 0x0a, 0xf6, 0x76, 0x5d, 0xf9, 0xa3, 0x37, 0x68, 0x17, 0xe6, + 0x7b, 0xa4, 0x77, 0x10, 0x44, 0x83, 0x47, 0x89, 0xd4, 0xe4, 0xed, 0x59, 0x65, 0x7b, 0xa5, 0x63, + 0x65, 0xed, 0xfd, 0x92, 0x84, 0x5f, 0x93, 0xc6, 0xf1, 0x84, 0x1e, 0xba, 0x0b, 0xb3, 0x1a, 0x48, + 0xde, 0x6e, 0xac, 0x57, 0x37, 0x5a, 0x5b, 0xd7, 0x6c, 0x13, 0xa7, 0x80, 0x9e, 0x23, 0x99, 0xab, + 0x1a, 0x80, 0x04, 0x6f, 0x37, 0xb5, 0x97, 0x6a, 0xe3, 0x3d, 0x81, 0xb6, 0x6d, 0x80, 0x27, 0x71, + 0xc4, 0xe9, 0x9f, 0x4e, 0xdb, 0x77, 0x15, 0x40, 0xc7, 0xcd, 0x22, 0x0f, 0xea, 0xfb, 0x82, 0x88, + 0x94, 0x1b, 0x93, 0x30, 0xca, 0xdc, 0x3a, 0x57, 0x14, 0x6c, 0x38, 0xe8, 0x03, 0xa8, 0xdd, 0x25, + 0x82, 0xa8, 0x34, 0x4e, 0x80, 0x55, 0x58, 0x94, 0x12, 0xfe, 0xbf, 0x25, 0x58, 0xa3, 0xcc, 0x9d, + 0xef, 0x13, 0x41, 0x6e, 0xc4, 0xc3, 0x40, 0xd0, 0x61, 0x22, 0x8e, 0xb0, 0xd2, 0x47, 0xb7, 0xa0, + 0xb9, 0xc3, 0x58, 0xcc, 0x9e, 0x1c, 0x25, 0x54, 0xe5, 0xbf, 0xe9, 0x5f, 0x19, 0x65, 0xee, 0x22, + 0xcd, 0x89, 0x96, 0x46, 0x21, 0x89, 0xde, 0x80, 0x19, 0xb5, 0x51, 0xf5, 0xd1, 0xf4, 0x17, 0x47, + 0x99, 0xbb, 0xa0, 0x54, 0x2c, 0x71, 0x2d, 0x81, 0x76, 0x8a, 0xb4, 0xcc, 0xa8, 0xb4, 0xfc, 0xef, + 0xb4, 0xb4, 0xd8, 0xa8, 0x4e, 0xe6, 0xc5, 0xfb, 0xa2, 0x02, 0xf3, 0xe5, 0xc8, 0x50, 0x07, 0x00, + 0x53, 0x9e, 0x86, 0x42, 0x39, 0xaf, 0xb1, 0x9a, 0x1f, 0x65, 0x2e, 0xb0, 0x31, 0x15, 0x5b, 0x12, + 0xe8, 0x3d, 0xa8, 0xeb, 0x9d, 0xca, 0x46, 0x6b, 0xab, 0x6d, 0x3b, 0xb2, 0x4f, 0x86, 0x49, 0x48, + 0xf7, 0x05, 0xa3, 0x64, 0xe8, 0xcf, 0x1b, 0xcc, 0xea, 0xda, 0x12, 0x36, 0x7a, 0xe8, 0x61, 0x5e, + 0x1c, 0x55, 0x05, 0xfb, 0xb5, 0xe9, 0x91, 0xc8, 0x54, 0x71, 0x8d, 0x8d, 0xd2, 0xb2, 0xb1, 0x51, + 0x04, 0x74, 0x07, 0x1a, 0x24, 0x22, 0xe1, 0x11, 0x0f, 0xb8, 0x42, 0xb2, 0xb5, 0xb5, 0x64, 0x9b, + 0xdc, 0x36, 0x3c, 0x7f, 0x6e, 0x94, 0xb9, 0x63, 0x49, 0x3c, 0x5e, 0x79, 0x3f, 0x56, 0x60, 0xad, + 0x38, 0xf7, 0x5e, 0xc4, 0x05, 0x89, 0xc4, 0x63, 0x69, 0xe0, 0x5c, 0xc5, 0x84, 0x4b, 0xc5, 0xf4, + 0xff, 0x93, 0xa3, 0xb2, 0xad, 0xff, 0x93, 0x0a, 0xeb, 0x87, 0x0a, 0xac, 0x9c, 0x1e, 0xe5, 0xb9, + 0x8b, 0x6c, 0xcf, 0x2a, 0x32, 0x89, 0xe6, 0xc6, 0xd9, 0x68, 0x6a, 0xf9, 0xbf, 0x4d, 0xd1, 0xfd, + 0xee, 0xc0, 0xea, 0xb4, 0x40, 0xd0, 0x75, 0xa8, 0xf3, 0x1e, 0x09, 0x09, 0x53, 0x70, 0xb5, 0xb6, + 0x2e, 0x75, 0xf2, 0xaf, 0xa4, 0xb9, 0x65, 0xbb, 0x17, 0xb0, 0x91, 0x40, 0x77, 0x60, 0x8e, 0x0b, + 0x16, 0x44, 0x03, 0xcd, 0x31, 0xa0, 0x95, 0x6f, 0xa6, 0xc5, 0xdf, 0xbd, 0x80, 0x4b, 0xf2, 0xe8, + 0x06, 0xd4, 0x5f, 0xd2, 0x9e, 0x88, 0x99, 0x41, 0x07, 0xd9, 0x9a, 0x4f, 0x15, 0x47, 0x9e, 0xa6, + 0x65, 0xa4, 0xf4, 0x90, 0x08, 0x16, 0x1c, 0x9a, 0xc0, 0x4b, 0xd2, 0x0f, 0x14, 0x47, 0x4a, 0x6b, + 0x19, 0xbf, 0x01, 0x26, 0x15, 0xde, 0xdb, 0x50, 0x7f, 0x9a, 0x5b, 0x98, 0xe5, 0xea, 0x64, 0x79, + 0x9f, 0xaa, 0x93, 0x26, 0xb4, 0x53, 0x38, 0x17, 0xf1, 0x76, 0xa1, 0xae, 0xad, 0xa2, 0x3b, 0x70, + 0x91, 0x5b, 0x1d, 0x26, 0xd7, 0x3e, 0xb5, 0x05, 0xe1, 0xb2, 0xb8, 0x17, 0x96, 0xc7, 0x06, 0x2b, + 0xd7, 0xe8, 0xb1, 0xed, 0x92, 0x8c, 0xea, 0xfa, 0x19, 0x15, 0xa2, 0x85, 0x75, 0xa1, 0xb4, 0x46, + 0x99, 0x9b, 0xab, 0x17, 0x7e, 0x7f, 0x59, 0xea, 0x2b, 0x27, 0x29, 0xa2, 0x47, 0xf0, 0x2f, 0x11, + 0x0b, 0x12, 0xaa, 0xc4, 0x93, 0x6e, 0x98, 0x73, 0x95, 0x0f, 0x55, 0x7f, 0x79, 0x94, 0xb9, 0x27, + 0x0b, 0xe0, 0x93, 0xc9, 0xe8, 0x6b, 0x07, 0x56, 0x4f, 0xe4, 0xec, 0x51, 0xb6, 0x2f, 0x47, 0x11, + 0xdd, 0xb4, 0x6f, 0x4f, 0x0f, 0x6e, 0x52, 0x59, 0x39, 0x6b, 0x2c, 0xf8, 0xeb, 0xa3, 0xcc, 0x9d, + 0x7a, 0x06, 0x9e, 0xca, 0xf5, 0x02, 0x38, 0xe7, 0x89, 0x72, 0x9a, 0x78, 0x29, 0xbf, 0xf5, 0x1a, + 0x15, 0xac, 0x37, 0xe8, 0x2a, 0xcc, 0xc9, 0xa1, 0x88, 0x0b, 0x32, 0x4c, 0x9e, 0x0d, 0xb9, 0x99, + 0xc5, 0x5a, 0x63, 0xda, 0x03, 0xee, 0x7d, 0x53, 0x81, 0x39, 0xbb, 0x1e, 0xd0, 0xe7, 0x0e, 0xd4, + 0x43, 0xd2, 0xa5, 0x61, 0x5e, 0x3a, 0x8b, 0xc5, 0xad, 0xba, 0x2f, 0xe9, 0x7b, 0x24, 0x60, 0xfe, + 0xbe, 0xec, 0x21, 0xbf, 0x64, 0xee, 0xf6, 0x20, 0x10, 0x07, 0x69, 0xb7, 0xd3, 0x8b, 0x87, 0x9b, + 0xe2, 0x80, 0x44, 0x31, 0xbf, 0x19, 0xc4, 0x66, 0xb5, 0x19, 0x44, 0x82, 0xb2, 0x88, 0x84, 0x9b, + 0x13, 0x33, 0xac, 0xb6, 0xb3, 0xdd, 0x27, 0x89, 0xa0, 0x4c, 0x36, 0xa2, 0x21, 0x15, 0x2c, 0xe8, + 0x61, 0x73, 0x2e, 0xba, 0x5d, 0x14, 0x9a, 0xce, 0xc5, 0xb1, 0x8b, 0x5d, 0xf4, 0x30, 0x15, 0x68, + 0x51, 0x51, 0x08, 0x03, 0x1c, 0x04, 0x5c, 0xc4, 0x03, 0x26, 0x8b, 0xbf, 0xaa, 0xd4, 0xdd, 0xe3, + 0xc5, 0xbf, 0x9b, 0xcb, 0xa8, 0x68, 0x2e, 0x1b, 0x6b, 0xcd, 0xb1, 0x2a, 0xb6, 0xac, 0x78, 0xdf, + 0x56, 0xa0, 0x6e, 0xda, 0xc0, 0x5f, 0x00, 0x9d, 0x37, 0xa1, 0xa5, 0x83, 0x55, 0xc3, 0x9d, 0xca, + 0xa9, 0xe3, 0x37, 0x47, 0x99, 0xab, 0x93, 0x8e, 0x6d, 0x2e, 0x5a, 0x85, 0xe6, 0x38, 0xdb, 0x66, + 0xec, 0x2e, 0x08, 0xe8, 0x3e, 0x14, 0x11, 0x9b, 0x4e, 0xf5, 0x9f, 0x29, 0x58, 0x29, 0x9c, 0x9c, + 0x32, 0x4e, 0xc5, 0xd2, 0xfb, 0x10, 0xe6, 0xec, 0x16, 0x5a, 0xae, 0xc9, 0xe6, 0x39, 0x6a, 0x52, + 0xc0, 0xe2, 0x09, 0x59, 0x2a, 0xc7, 0xe2, 0x4c, 0xc6, 0xf2, 0xae, 0x1d, 0x4b, 0xe5, 0xec, 0x58, + 0xf4, 0x6c, 0x6f, 0xb9, 0x9f, 0xc0, 0xc2, 0x84, 0x8c, 0x8c, 0xa0, 0x17, 0xa7, 0x91, 0x50, 0xa7, + 0x39, 0x58, 0x6f, 0xe4, 0x23, 0x86, 0xa7, 0xfa, 0x0c, 0x07, 0xcb, 0x25, 0xba, 0x05, 0xb3, 0xdd, + 0xb4, 0xf7, 0x9c, 0x8a, 0xbc, 0xe2, 0x4a, 0x27, 0x17, 0x67, 0x2a, 0x19, 0x9c, 0xcb, 0x7a, 0x1c, + 0x16, 0x26, 0x78, 0x68, 0x0d, 0xa0, 0x1b, 0xa7, 0x51, 0x9f, 0xb0, 0xc0, 0xb4, 0xb8, 0x19, 0x6c, + 0x51, 0xa4, 0x47, 0x61, 0xfc, 0x19, 0x65, 0xe6, 0x74, 0xbd, 0x91, 0xd4, 0x34, 0x49, 0xa8, 0xfe, + 0x36, 0x39, 0x58, 0x6f, 0x0a, 0xef, 0x6b, 0x96, 0xf7, 0xde, 0xa7, 0x30, 0x2f, 0x5f, 0x39, 0xb4, + 0x3f, 0x9e, 0xdc, 0x96, 0xa1, 0xfa, 0x9c, 0x1e, 0x99, 0x91, 0x63, 0x76, 0x94, 0xb9, 0x72, 0x8b, + 0xe5, 0x1f, 0xf9, 0x12, 0xa3, 0x87, 0x82, 0x46, 0x22, 0xbf, 0x89, 0xa5, 0xaf, 0xd0, 0x8e, 0x62, + 0xf9, 0x0b, 0xe6, 0xf6, 0xe4, 0xa2, 0x38, 0x5f, 0x78, 0xdf, 0x3b, 0x50, 0xd7, 0x42, 0xc8, 0xcd, + 0xdf, 0x83, 0xba, 0x6d, 0xab, 0x7a, 0x55, 0x84, 0xfc, 0x69, 0xb8, 0xac, 0x9f, 0x86, 0xaa, 0x1c, + 0xb4, 0x17, 0x34, 0xea, 0xeb, 0x37, 0xe2, 0x3a, 0x34, 0x04, 0x23, 0x3d, 0xfa, 0x2c, 0xe8, 0x9b, + 0x71, 0x2d, 0x9f, 0xad, 0x14, 0xf9, 0x5e, 0x5f, 0x8e, 0x1a, 0xcc, 0x84, 0x63, 0x9e, 0x8c, 0x4b, + 0xc7, 0x9e, 0x8c, 0xdb, 0xd1, 0x91, 0x1e, 0x35, 0x72, 0x49, 0x3c, 0x5e, 0x7d, 0x54, 0x6b, 0x54, + 0x2f, 0xd5, 0xbc, 0x1b, 0x1a, 0x1a, 0xeb, 0xa9, 0xb7, 0x02, 0x8d, 0x7e, 0xc0, 0x65, 0xd3, 0xed, + 0x2b, 0xc7, 0x1b, 0x78, 0xbc, 0xf7, 0x22, 0x68, 0xed, 0x1c, 0x26, 0x21, 0x89, 0xd4, 0x43, 0x14, + 0xad, 0x42, 0x2d, 0x2a, 0x5e, 0x67, 0x8d, 0x51, 0xe6, 0xaa, 0x3d, 0x56, 0x7f, 0xd1, 0x36, 0x34, + 0x7a, 0x07, 0x41, 0xd8, 0x67, 0x34, 0x32, 0x48, 0x5e, 0x29, 0x23, 0x39, 0x36, 0xa4, 0x7d, 0xcc, + 0x85, 0xf1, 0x78, 0xe5, 0xfd, 0xe4, 0x40, 0x23, 0x9f, 0x99, 0xce, 0x38, 0xad, 0x0b, 0x17, 0xe9, + 0x21, 0xed, 0xa5, 0xd2, 0xde, 0x93, 0x60, 0x98, 0x4f, 0x3b, 0x53, 0x9e, 0xd1, 0x57, 0x4d, 0xc7, + 0x6a, 0xe4, 0x94, 0x51, 0xe6, 0x96, 0x6d, 0xe0, 0xf2, 0x56, 0x42, 0x3e, 0x8e, 0x48, 0x17, 0xfd, + 0x94, 0xe9, 0xee, 0x78, 0x38, 0x7e, 0xfb, 0xd5, 0xeb, 0x35, 0xe7, 0xe7, 0xd7, 0x6b, 0xce, 0x6f, + 0xaf, 0xd7, 0x9c, 0x8f, 0xad, 0x7f, 0x94, 0x74, 0xeb, 0xca, 0xbd, 0xb7, 0xfe, 0x08, 0x00, 0x00, + 0xff, 0xff, 0x64, 0x18, 0x91, 0x98, 0x69, 0x11, 0x00, 0x00, } func (m *PrometheusRequestHeader) Marshal() (dAtA []byte, err error) { @@ -1917,9 +1977,9 @@ func (m *PrometheusData) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } - if m.Explanation != nil { + if m.Analysis != nil { { - size, err := m.Explanation.MarshalToSizedBuffer(dAtA[:i]) + size, err := m.Analysis.MarshalToSizedBuffer(dAtA[:i]) if err != nil { return 0, err } @@ -2061,9 +2121,9 @@ func (m *PrometheusInstantQueryData) MarshalToSizedBuffer(dAtA []byte) (int, err i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } - if m.Explanation != nil { + if m.Analysis != nil { { - size, err := m.Explanation.MarshalToSizedBuffer(dAtA[:i]) + size, err := m.Analysis.MarshalToSizedBuffer(dAtA[:i]) if err != nil { return 0, err } @@ -2935,6 +2995,64 @@ func (m *Explanation) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *Analysis) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Analysis) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Analysis) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) + } + if len(m.Children) > 0 { + for iNdEx := len(m.Children) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Children[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQueryrange(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + { + size := m.ExecutionTime.Size() + i -= size + if _, err := m.ExecutionTime.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQueryrange(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Name) > 0 { + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarintQueryrange(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarintQueryrange(dAtA []byte, offset int, v uint64) int { offset -= sovQueryrange(v) base := offset @@ -3085,8 +3203,8 @@ func (m *PrometheusData) Size() (n int) { l = m.Stats.Size() n += 1 + l + sovQueryrange(uint64(l)) } - if m.Explanation != nil { - l = m.Explanation.Size() + if m.Analysis != nil { + l = m.Analysis.Size() n += 1 + l + sovQueryrange(uint64(l)) } if m.XXX_unrecognized != nil { @@ -3143,8 +3261,8 @@ func (m *PrometheusInstantQueryData) Size() (n int) { l = m.Stats.Size() n += 1 + l + sovQueryrange(uint64(l)) } - if m.Explanation != nil { - l = m.Explanation.Size() + if m.Analysis != nil { + l = m.Analysis.Size() n += 1 + l + sovQueryrange(uint64(l)) } if m.XXX_unrecognized != nil { @@ -3534,6 +3652,30 @@ func (m *Explanation) Size() (n int) { return n } +func (m *Analysis) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Name) + if l > 0 { + n += 1 + l + sovQueryrange(uint64(l)) + } + l = m.ExecutionTime.Size() + n += 1 + l + sovQueryrange(uint64(l)) + if len(m.Children) > 0 { + for _, e := range m.Children { + l = e.Size() + n += 1 + l + sovQueryrange(uint64(l)) + } + } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + func sovQueryrange(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -4421,7 +4563,7 @@ func (m *PrometheusData) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 4: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Explanation", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Analysis", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -4448,10 +4590,10 @@ func (m *PrometheusData) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Explanation == nil { - m.Explanation = &Explanation{} + if m.Analysis == nil { + m.Analysis = &Analysis{} } - if err := m.Explanation.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.Analysis.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -4823,7 +4965,7 @@ func (m *PrometheusInstantQueryData) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 4: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Explanation", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Analysis", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -4850,10 +4992,10 @@ func (m *PrometheusInstantQueryData) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Explanation == nil { - m.Explanation = &Explanation{} + if m.Analysis == nil { + m.Analysis = &Analysis{} } - if err := m.Explanation.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.Analysis.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -6701,6 +6843,156 @@ func (m *Explanation) Unmarshal(dAtA []byte) error { } return nil } +func (m *Analysis) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQueryrange + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Analysis: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Analysis: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQueryrange + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQueryrange + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQueryrange + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ExecutionTime", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQueryrange + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQueryrange + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQueryrange + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ExecutionTime.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Children", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQueryrange + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQueryrange + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQueryrange + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Children = append(m.Children, &Analysis{}) + if err := m.Children[len(m.Children)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQueryrange(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQueryrange + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipQueryrange(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/internal/cortex/querier/queryrange/queryrange.proto b/internal/cortex/querier/queryrange/queryrange.proto index 77e3bbdc55..f6a7b2e383 100644 --- a/internal/cortex/querier/queryrange/queryrange.proto +++ b/internal/cortex/querier/queryrange/queryrange.proto @@ -48,7 +48,7 @@ message PrometheusData { string ResultType = 1 [(gogoproto.jsontag) = "resultType"]; repeated SampleStream Result = 2 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "result"]; PrometheusResponseStats stats = 3 [(gogoproto.jsontag) = "stats,omitempty"]; - Explanation Explanation = 4 [(gogoproto.jsontag) = "explanation"]; + Analysis analysis = 4 [(gogoproto.jsontag) = "analysis"]; } message PrometheusInstantQueryResponse { @@ -63,7 +63,7 @@ message PrometheusInstantQueryData { string ResultType = 1 [(gogoproto.jsontag) = "resultType"]; PrometheusInstantQueryResult Result = 2 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "result"]; PrometheusResponseStats stats = 3 [(gogoproto.jsontag) = "stats,omitempty"]; - Explanation Explanation = 4 [(gogoproto.jsontag) = "explanation"]; + Analysis analysis = 4 [(gogoproto.jsontag) = "analysis"]; } message PrometheusInstantQueryResult { @@ -157,3 +157,9 @@ message Explanation { string name = 1 [(gogoproto.jsontag) = "name"]; repeated Explanation children = 2 [(gogoproto.jsontag) = "children"]; } + +message Analysis { + string name = 1 [(gogoproto.jsontag) = "name"]; + google.protobuf.Duration executionTime = 2 [(gogoproto.customtype) = "Duration", (gogoproto.nullable) = false, (gogoproto.jsontag) = "executionTime"]; + repeated Analysis children = 3 [(gogoproto.jsontag) = "children"]; +} diff --git a/internal/cortex/querier/queryrange/results_cache.go b/internal/cortex/querier/queryrange/results_cache.go index de0f7e8149..a0e467d6a7 100644 --- a/internal/cortex/querier/queryrange/results_cache.go +++ b/internal/cortex/querier/queryrange/results_cache.go @@ -94,10 +94,10 @@ func (PrometheusResponseExtractor) Extract(start, end int64, from Response) Resp return &PrometheusResponse{ Status: StatusSuccess, Data: PrometheusData{ - ResultType: promRes.Data.ResultType, - Result: extractMatrix(start, end, promRes.Data.Result), - Stats: extractStats(start, end, promRes.Data.Stats), - Explanation: promRes.Data.Explanation, + ResultType: promRes.Data.ResultType, + Result: extractMatrix(start, end, promRes.Data.Result), + Stats: extractStats(start, end, promRes.Data.Stats), + Analysis: promRes.Data.Analysis, }, Headers: promRes.Headers, } @@ -110,10 +110,10 @@ func (PrometheusResponseExtractor) ResponseWithoutHeaders(resp Response) Respons return &PrometheusResponse{ Status: StatusSuccess, Data: PrometheusData{ - ResultType: promRes.Data.ResultType, - Result: promRes.Data.Result, - Stats: promRes.Data.Stats, - Explanation: promRes.Data.Explanation, + ResultType: promRes.Data.ResultType, + Result: promRes.Data.Result, + Stats: promRes.Data.Stats, + Analysis: promRes.Data.Analysis, }, } } @@ -124,9 +124,9 @@ func (PrometheusResponseExtractor) ResponseWithoutStats(resp Response) Response return &PrometheusResponse{ Status: StatusSuccess, Data: PrometheusData{ - ResultType: promRes.Data.ResultType, - Result: promRes.Data.Result, - Explanation: promRes.Data.Explanation, + ResultType: promRes.Data.ResultType, + Result: promRes.Data.Result, + Analysis: promRes.Data.Analysis, }, Headers: promRes.Headers, } diff --git a/internal/cortex/querier/queryrange/results_cache_test.go b/internal/cortex/querier/queryrange/results_cache_test.go index cb12d5cb23..346c9e4a25 100644 --- a/internal/cortex/querier/queryrange/results_cache_test.go +++ b/internal/cortex/querier/queryrange/results_cache_test.go @@ -24,8 +24,8 @@ import ( const ( query = "/api/v1/query_range?end=1536716898&query=sum%28container_memory_rss%29+by+%28namespace%29&start=1536673680&stats=all&step=120" - responseBody = `{"status":"success","data":{"resultType":"matrix","result":[{"metric":{"foo":"bar"},"values":[[1536673680,"137"],[1536673780,"137"]]}],"explanation":null}}` - histogramResponseBody = `{"status":"success","data":{"resultType":"matrix","result":[{"metric":{"fake":"histogram"},"histograms":[[1536673680,{"count":"5","sum":"18.4","buckets":[[3,"-0.001","0.001","2"],[0,"0.7071067811865475","1","1"],[0,"1","1.414213562373095","2"],[0,"2","2.82842712474619","1"],[0,"2.82842712474619","4","1"]]}]]}],"explanation":null}}` + responseBody = `{"status":"success","data":{"resultType":"matrix","result":[{"metric":{"foo":"bar"},"values":[[1536673680,"137"],[1536673780,"137"]]}],"analysis":null}}` + histogramResponseBody = `{"status":"success","data":{"resultType":"matrix","result":[{"metric":{"fake":"histogram"},"histograms":[[1536673680,{"count":"5","sum":"18.4","buckets":[[3,"-0.001","0.001","2"],[0,"0.7071067811865475","1","1"],[0,"1","1.414213562373095","2"],[0,"2","2.82842712474619","1"],[0,"2.82842712474619","4","1"]]}]]}],"analysis":null}}` ) var ( @@ -78,6 +78,7 @@ var ( Status: "success", Data: PrometheusData{ ResultType: model.ValMatrix.String(), + Analysis: (*Analysis)(nil), Result: []SampleStream{ { Labels: []cortexpb.LabelAdapter{ @@ -95,6 +96,7 @@ var ( Status: "success", Data: PrometheusData{ ResultType: model.ValMatrix.String(), + Analysis: (*Analysis)(nil), Result: []SampleStream{ { Labels: []cortexpb.LabelAdapter{ @@ -143,6 +145,7 @@ func mkAPIResponseWithStats(start, end, step int64, withStats bool) *PrometheusR Data: PrometheusData{ ResultType: matrix, Stats: stats, + Analysis: &Analysis{}, Result: []SampleStream{ { Labels: []cortexpb.LabelAdapter{ @@ -1070,21 +1073,24 @@ func TestResultsCache(t *testing.T) { ) require.NoError(t, err) + useResp := *parsedResponse + useResp.Data.Analysis = &Analysis{} + rc := rcm.Wrap(HandlerFunc(func(_ context.Context, req Request) (Response, error) { calls++ - return parsedResponse, nil + return &useResp, nil })) ctx := user.InjectOrgID(context.Background(), "1") resp, err := rc.Do(ctx, parsedRequest) require.NoError(t, err) require.Equal(t, 1, calls) - require.Equal(t, parsedResponse, resp) + require.Equal(t, &useResp, resp) // Doing same request again shouldn't change anything. resp, err = rc.Do(ctx, parsedRequest) require.NoError(t, err) require.Equal(t, 1, calls) - require.Equal(t, parsedResponse, resp) + require.Equal(t, &useResp, resp) // Doing request with new end time should do one more query. req := parsedRequest.WithStartEnd(parsedRequest.GetStart(), parsedRequest.GetEnd()+100) @@ -1351,21 +1357,24 @@ func TestNativeHistograms(t *testing.T) { ) require.NoError(t, err) + useResp := *parsedHistogramResponse + useResp.Data.Analysis = &Analysis{} + rc := rcm.Wrap(HandlerFunc(func(_ context.Context, req Request) (Response, error) { calls++ - return parsedHistogramResponse, nil + return &useResp, nil })) ctx := user.InjectOrgID(context.Background(), "1") resp, err := rc.Do(ctx, parsedHistogramRequest) require.NoError(t, err) require.Equal(t, 1, calls) - require.Equal(t, parsedHistogramResponse, resp) + require.Equal(t, &useResp, resp) // Doing same request again shouldn't change anything. resp, err = rc.Do(ctx, parsedHistogramRequest) require.NoError(t, err) require.Equal(t, 1, calls) - require.Equal(t, parsedHistogramResponse, resp) + require.Equal(t, &useResp, resp) // Doing request with new end time should do one more query. req := parsedHistogramRequest.WithStartEnd(parsedHistogramRequest.GetStart(), parsedHistogramRequest.GetEnd()+100) diff --git a/pkg/queryfrontend/queryinstant_codec.go b/pkg/queryfrontend/queryinstant_codec.go index 4882e80c6c..e367784ab7 100644 --- a/pkg/queryfrontend/queryinstant_codec.go +++ b/pkg/queryfrontend/queryinstant_codec.go @@ -14,6 +14,7 @@ import ( "strconv" "strings" + "dario.cat/mergo" "github.com/opentracing/opentracing-go" otlog "github.com/opentracing/opentracing-go/log" "github.com/prometheus/common/model" @@ -54,11 +55,17 @@ func (c queryInstantCodec) MergeResponse(req queryrange.Request, responses ...qu promResponses = append(promResponses, resp.(*queryrange.PrometheusInstantQueryResponse)) } - var explanation *queryrange.Explanation + var analysis queryrange.Analysis for i := range promResponses { - if promResponses[i].Data.GetExplanation() != nil { - explanation = promResponses[i].Data.GetExplanation() - break + if promResponses[i].Data.GetAnalysis() == nil { + continue + } + + if err := mergo.Merge(&analysis, + promResponses[i].Data.GetAnalysis(), + mergo.WithTransformers(queryrange.TimeDurationTransformer{}), + ); err != nil { + return nil, err } } @@ -74,8 +81,8 @@ func (c queryInstantCodec) MergeResponse(req queryrange.Request, responses ...qu Matrix: matrixMerge(promResponses), }, }, - Stats: queryrange.StatsMerge(responses), - Explanation: explanation, + Analysis: &analysis, + Stats: queryrange.StatsMerge(responses), }, } default: @@ -92,8 +99,8 @@ func (c queryInstantCodec) MergeResponse(req queryrange.Request, responses ...qu Vector: v, }, }, - Stats: queryrange.StatsMerge(responses), - Explanation: explanation, + Analysis: &analysis, + Stats: queryrange.StatsMerge(responses), }, } } @@ -113,6 +120,14 @@ func (c queryInstantCodec) DecodeRequest(_ context.Context, r *http.Request, for } } + if len(r.FormValue("analyze")) > 0 { + analyze, err := strconv.ParseBool(r.FormValue("analyze")) + if err != nil { + return nil, err + } + result.Analyze = analyze + } + result.Dedup, err = parseEnableDedupParam(r.FormValue(queryv1.DedupParam)) if err != nil { return nil, err @@ -153,7 +168,6 @@ func (c queryInstantCodec) DecodeRequest(_ context.Context, r *http.Request, for result.Query = r.FormValue("query") result.Path = r.URL.Path - result.Analyze = r.FormValue("analyze") result.Engine = r.FormValue("engine") for _, header := range forwardHeaders { @@ -164,6 +178,7 @@ func (c queryInstantCodec) DecodeRequest(_ context.Context, r *http.Request, for } } } + return &result, nil } @@ -175,8 +190,8 @@ func (c queryInstantCodec) EncodeRequest(ctx context.Context, r queryrange.Reque params := url.Values{ "query": []string{thanosReq.Query}, queryv1.DedupParam: []string{strconv.FormatBool(thanosReq.Dedup)}, + queryv1.QueryAnalyzeParam: []string{strconv.FormatBool(thanosReq.Analyze)}, queryv1.PartialResponseParam: []string{strconv.FormatBool(thanosReq.PartialResponse)}, - queryv1.QueryAnalyzeParam: []string{thanosReq.Analyze}, queryv1.EngineParam: []string{thanosReq.Engine}, queryv1.ReplicaLabelsParam: thanosReq.ReplicaLabels, } diff --git a/pkg/queryfrontend/queryinstant_codec_test.go b/pkg/queryfrontend/queryinstant_codec_test.go index b525bc85e6..3d60cf6960 100644 --- a/pkg/queryfrontend/queryinstant_codec_test.go +++ b/pkg/queryfrontend/queryinstant_codec_test.go @@ -9,6 +9,7 @@ import ( "io" "net/http" "testing" + "time" "github.com/prometheus/common/model" "github.com/prometheus/prometheus/model/labels" @@ -58,6 +59,19 @@ func TestQueryInstantCodec_DecodeRequest(t *testing.T) { StoreMatchers: [][]*labels.Matcher{}, }, }, + { + name: "parse with analyze", + url: "/api/v1/query?time=123&query=up&analyze=true", + partialResponse: false, + expectedRequest: &ThanosQueryInstantRequest{ + Path: "/api/v1/query", + Query: "up", + Time: 123000, + Dedup: true, + StoreMatchers: [][]*labels.Matcher{}, + Analyze: true, + }, + }, { name: "cannot parse dedup", url: "/api/v1/query?dedup=bar", @@ -271,6 +285,48 @@ func TestMergeResponse(t *testing.T) { expectedResp queryrange.Response expectedErr error }{ + { + name: "response with analysis", + req: defaultReq, + expectedResp: &queryrange.PrometheusInstantQueryResponse{ + Status: queryrange.StatusSuccess, + Data: queryrange.PrometheusInstantQueryData{ + ResultType: model.ValScalar.String(), + Analysis: &queryrange.Analysis{ + Name: "foo", + ExecutionTime: queryrange.Duration(1 * time.Second), + }, + Result: queryrange.PrometheusInstantQueryResult{ + Result: &queryrange.PrometheusInstantQueryResult_Scalar{ + Scalar: &cortexpb.Sample{ + TimestampMs: 0, + Value: 1, + }, + }, + }, + }, + }, + resps: []queryrange.Response{ + &queryrange.PrometheusInstantQueryResponse{ + Status: queryrange.StatusSuccess, + Data: queryrange.PrometheusInstantQueryData{ + ResultType: model.ValScalar.String(), + Analysis: &queryrange.Analysis{ + Name: "foo", + ExecutionTime: queryrange.Duration(1 * time.Second), + }, + Result: queryrange.PrometheusInstantQueryResult{ + Result: &queryrange.PrometheusInstantQueryResult_Scalar{ + Scalar: &cortexpb.Sample{ + TimestampMs: 0, + Value: 1, + }, + }, + }, + }, + }, + }, + }, { name: "empty response", req: defaultReq, @@ -278,6 +334,7 @@ func TestMergeResponse(t *testing.T) { expectedResp: &queryrange.PrometheusInstantQueryResponse{ Status: queryrange.StatusSuccess, Data: queryrange.PrometheusInstantQueryData{ + Analysis: nil, ResultType: model.ValVector.String(), Result: queryrange.PrometheusInstantQueryResult{ Result: &queryrange.PrometheusInstantQueryResult_Vector{}, @@ -315,6 +372,7 @@ func TestMergeResponse(t *testing.T) { Status: queryrange.StatusSuccess, Data: queryrange.PrometheusInstantQueryData{ ResultType: model.ValVector.String(), + Analysis: nil, Result: queryrange.PrometheusInstantQueryResult{ Result: &queryrange.PrometheusInstantQueryResult_Vector{ Vector: &queryrange.Vector{ @@ -388,6 +446,7 @@ func TestMergeResponse(t *testing.T) { Status: queryrange.StatusSuccess, Data: queryrange.PrometheusInstantQueryData{ ResultType: model.ValVector.String(), + Analysis: &queryrange.Analysis{}, Result: queryrange.PrometheusInstantQueryResult{ Result: &queryrange.PrometheusInstantQueryResult_Vector{ Vector: &queryrange.Vector{ @@ -469,6 +528,7 @@ func TestMergeResponse(t *testing.T) { expectedResp: &queryrange.PrometheusInstantQueryResponse{ Status: queryrange.StatusSuccess, Data: queryrange.PrometheusInstantQueryData{ + Analysis: &queryrange.Analysis{}, ResultType: model.ValVector.String(), Result: queryrange.PrometheusInstantQueryResult{ Result: &queryrange.PrometheusInstantQueryResult_Vector{ @@ -550,6 +610,7 @@ func TestMergeResponse(t *testing.T) { Status: queryrange.StatusSuccess, Data: queryrange.PrometheusInstantQueryData{ ResultType: model.ValVector.String(), + Analysis: &queryrange.Analysis{}, Result: queryrange.PrometheusInstantQueryResult{ Result: &queryrange.PrometheusInstantQueryResult_Vector{ Vector: &queryrange.Vector{ @@ -630,6 +691,7 @@ func TestMergeResponse(t *testing.T) { Status: queryrange.StatusSuccess, Data: queryrange.PrometheusInstantQueryData{ ResultType: model.ValVector.String(), + Analysis: &queryrange.Analysis{}, Result: queryrange.PrometheusInstantQueryResult{ Result: &queryrange.PrometheusInstantQueryResult_Vector{ Vector: &queryrange.Vector{ @@ -686,6 +748,7 @@ func TestMergeResponse(t *testing.T) { Status: queryrange.StatusSuccess, Data: queryrange.PrometheusInstantQueryData{ ResultType: model.ValVector.String(), + Analysis: &queryrange.Analysis{}, Result: queryrange.PrometheusInstantQueryResult{ Result: &queryrange.PrometheusInstantQueryResult_Vector{ Vector: &queryrange.Vector{ @@ -761,6 +824,7 @@ func TestMergeResponse(t *testing.T) { Status: queryrange.StatusSuccess, Data: queryrange.PrometheusInstantQueryData{ ResultType: model.ValMatrix.String(), + Analysis: &queryrange.Analysis{}, Result: queryrange.PrometheusInstantQueryResult{ Result: &queryrange.PrometheusInstantQueryResult_Matrix{ Matrix: &queryrange.Matrix{ @@ -794,6 +858,7 @@ func TestMergeResponse(t *testing.T) { Status: queryrange.StatusSuccess, Data: queryrange.PrometheusInstantQueryData{ ResultType: model.ValMatrix.String(), + Analysis: &queryrange.Analysis{}, Result: queryrange.PrometheusInstantQueryResult{ Result: &queryrange.PrometheusInstantQueryResult_Matrix{ Matrix: &queryrange.Matrix{ @@ -851,6 +916,7 @@ func TestMergeResponse(t *testing.T) { Status: queryrange.StatusSuccess, Data: queryrange.PrometheusInstantQueryData{ ResultType: model.ValMatrix.String(), + Analysis: &queryrange.Analysis{}, Result: queryrange.PrometheusInstantQueryResult{ Result: &queryrange.PrometheusInstantQueryResult_Matrix{ Matrix: &queryrange.Matrix{ @@ -897,37 +963,33 @@ func TestDecodeResponse(t *testing.T) { expectedErr error }{ { - name: "with explanation", + name: "with analysis", body: `{ - "status":"success", - "data":{ - "resultType":"vector", - "result":[], - "explanation": { - "name":"[*concurrencyOperator(buff=2)]", - "children":[{"name":"[*aggregate] sum by ([])", "children": []}] - } -} -}`, + "status": "success", + "data": { + "resultType": "scalar", + "result": [ + 1708690766.576, + "1708690766.576" + ], + "analysis": { + "name": "[noArgFunction]", + "executionTime": "1s" + } + } + }`, expectedResponse: &queryrange.PrometheusInstantQueryResponse{ Status: queryrange.StatusSuccess, Headers: headers, Data: queryrange.PrometheusInstantQueryData{ - Explanation: &queryrange.Explanation{ - Name: "[*concurrencyOperator(buff=2)]", - Children: []*queryrange.Explanation{ - { - Name: "[*aggregate] sum by ([])", - Children: []*queryrange.Explanation{}, - }, - }, + Analysis: &queryrange.Analysis{ + Name: "[noArgFunction]", + ExecutionTime: queryrange.Duration(1 * time.Second), }, - ResultType: model.ValVector.String(), + ResultType: model.ValScalar.String(), Result: queryrange.PrometheusInstantQueryResult{ - Result: &queryrange.PrometheusInstantQueryResult_Vector{ - Vector: &queryrange.Vector{ - Samples: []*queryrange.Sample{}, - }, + Result: &queryrange.PrometheusInstantQueryResult_Scalar{ + Scalar: &cortexpb.Sample{TimestampMs: 1708690766576, Value: 1708690766.576}, }, }, }, diff --git a/pkg/queryfrontend/queryrange_codec.go b/pkg/queryfrontend/queryrange_codec.go index 36080d6821..fca6ea7fc7 100644 --- a/pkg/queryfrontend/queryrange_codec.go +++ b/pkg/queryfrontend/queryrange_codec.go @@ -129,7 +129,12 @@ func (c queryRangeCodec) DecodeRequest(_ context.Context, r *http.Request, forwa } result.Query = r.FormValue("query") - result.Analyze = r.FormValue(queryv1.QueryAnalyzeParam) + if len(r.FormValue(queryv1.QueryAnalyzeParam)) > 0 { + result.Analyze, err = strconv.ParseBool(r.FormValue(queryv1.QueryAnalyzeParam)) + if err != nil { + return nil, err + } + } result.Engine = r.FormValue(queryv1.EngineParam) result.Path = r.URL.Path @@ -161,7 +166,7 @@ func (c queryRangeCodec) EncodeRequest(ctx context.Context, r queryrange.Request "end": []string{encodeTime(thanosReq.End)}, "step": []string{encodeDurationMillis(thanosReq.Step)}, "query": []string{thanosReq.Query}, - queryv1.QueryAnalyzeParam: []string{thanosReq.Analyze}, + queryv1.QueryAnalyzeParam: []string{strconv.FormatBool(thanosReq.Analyze)}, queryv1.EngineParam: []string{thanosReq.Engine}, queryv1.DedupParam: []string{strconv.FormatBool(thanosReq.Dedup)}, queryv1.PartialResponseParam: []string{strconv.FormatBool(thanosReq.PartialResponse)}, diff --git a/pkg/queryfrontend/request.go b/pkg/queryfrontend/request.go index 7497f1002b..4a6fb3f0d8 100644 --- a/pkg/queryfrontend/request.go +++ b/pkg/queryfrontend/request.go @@ -55,7 +55,7 @@ type ThanosQueryRangeRequest struct { Stats string ShardInfo *storepb.ShardInfo LookbackDelta int64 - Analyze string + Analyze bool Engine string } @@ -156,7 +156,7 @@ type ThanosQueryInstantRequest struct { Stats string ShardInfo *storepb.ShardInfo LookbackDelta int64 // in milliseconds. - Analyze string + Analyze bool Engine string } diff --git a/test/e2e/query_frontend_test.go b/test/e2e/query_frontend_test.go index 78810d60a4..867a8b81ba 100644 --- a/test/e2e/query_frontend_test.go +++ b/test/e2e/query_frontend_test.go @@ -1195,10 +1195,9 @@ func TestQueryFrontendAnalyze(t *testing.T) { require.Equal(t, http.StatusOK, resp.StatusCode) r := regexp.MustCompile( - `{"status":"success","data":{"resultType":"scalar","result":\[.+,".+"\],"analysis":{"name":"\[duplicateLabelCheck\]","executionTime":".+"}}}`, + `{"status":"success","data":{"resultType":"scalar","result":\[.+,".+"\],"analysis":{"name":"\[duplicateLabelCheck\]","executionTime":".+","children":null}}}`, ) t.Log(strings.TrimSpace(string(body))) - // TODO(Giedrius): fix. - require.NotEqual(t, true, r.MatchString(strings.TrimSpace(string(body)))) + require.Equal(t, true, r.MatchString(strings.TrimSpace(string(body)))) }