Split label names queries in the frontend. (#2441)

* Split the Series API by 24h.

We currently split too much by using the same split duration for query range.
Let's start with 24h, just tested in ops-tools and it works better.
We could later introduce a config.

Signed-off-by: Cyril Tovena <cyril.tovena@gmail.com>

* Split label name queries in the frontend.

Build on top of #2436 and adds the ability to split label names queries.
Those queries are heavy to run for long period and so splitting by day should improve query performance.

The frontend also support the old legacy label names API which has a different response.

Signed-off-by: Cyril Tovena <cyril.tovena@gmail.com>
k27
Cyril Tovena 5 years ago committed by GitHub
parent bf0a8cb58b
commit 9ad98dfa7c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 140
      pkg/querier/queryrange/codec.go
  2. 90
      pkg/querier/queryrange/codec_test.go
  3. 15
      pkg/querier/queryrange/limits.go
  4. 784
      pkg/querier/queryrange/queryrange.pb.go
  5. 12
      pkg/querier/queryrange/queryrange.proto
  6. 53
      pkg/querier/queryrange/roundtrip.go
  7. 73
      pkg/querier/queryrange/roundtrip_test.go
  8. 43
      pkg/querier/queryrange/split_by_interval.go

@ -108,12 +108,47 @@ func (r *LokiSeriesRequest) LogToSpan(sp opentracing.Span) {
)
}
func (r *LokiLabelNamesRequest) GetEnd() int64 {
return r.EndTs.UnixNano() / (int64(time.Millisecond) / int64(time.Nanosecond))
}
func (r *LokiLabelNamesRequest) GetStart() int64 {
return r.StartTs.UnixNano() / (int64(time.Millisecond) / int64(time.Nanosecond))
}
func (r *LokiLabelNamesRequest) WithStartEnd(s int64, e int64) queryrange.Request {
new := *r
new.StartTs = time.Unix(0, s*int64(time.Millisecond))
new.EndTs = time.Unix(0, e*int64(time.Millisecond))
return &new
}
func (r *LokiLabelNamesRequest) WithQuery(query string) queryrange.Request {
new := *r
return &new
}
func (r *LokiLabelNamesRequest) GetQuery() string {
return ""
}
func (r *LokiLabelNamesRequest) GetStep() int64 {
return 0
}
func (r *LokiLabelNamesRequest) LogToSpan(sp opentracing.Span) {
sp.LogFields(
otlog.String("start", timestamp.Time(r.GetStart()).String()),
otlog.String("end", timestamp.Time(r.GetEnd()).String()),
)
}
func (codec) DecodeRequest(_ context.Context, r *http.Request) (queryrange.Request, error) {
if err := r.ParseForm(); err != nil {
return nil, httpgrpc.Errorf(http.StatusBadRequest, err.Error())
}
switch op := getOperation(r); op {
switch op := getOperation(r.URL.Path); op {
case QueryRangeOp:
req, err := loghttp.ParseRangeQuery(r)
if err != nil {
@ -141,6 +176,16 @@ func (codec) DecodeRequest(_ context.Context, r *http.Request) (queryrange.Reque
EndTs: req.End.UTC(),
Path: r.URL.Path,
}, nil
case LabelNamesOp:
req, err := loghttp.ParseLabelQuery(r)
if err != nil {
return nil, httpgrpc.Errorf(http.StatusBadRequest, err.Error())
}
return &LokiLabelNamesRequest{
StartTs: *req.Start,
EndTs: *req.End,
Path: r.URL.Path,
}, nil
default:
return nil, httpgrpc.Errorf(http.StatusBadRequest, fmt.Sprintf("unknown request path: %s", r.URL.Path))
}
@ -196,6 +241,24 @@ func (codec) EncodeRequest(ctx context.Context, r queryrange.Request) (*http.Req
Header: http.Header{},
}
return req.WithContext(ctx), nil
case *LokiLabelNamesRequest:
params := url.Values{
"start": []string{fmt.Sprintf("%d", request.StartTs.UnixNano())},
"end": []string{fmt.Sprintf("%d", request.EndTs.UnixNano())},
}
u := &url.URL{
Path: "/loki/api/v1/labels",
RawQuery: params.Encode(),
}
req := &http.Request{
Method: "GET",
RequestURI: u.String(), // This is what the httpgrpc code looks at.
URL: u,
Body: http.NoBody,
Header: http.Header{},
}
return req.WithContext(ctx), nil
default:
return nil, httpgrpc.Errorf(http.StatusInternalServerError, "invalid request format")
}
@ -238,6 +301,16 @@ func (codec) DecodeResponse(ctx context.Context, r *http.Response, req queryrang
Version: uint32(loghttp.GetVersion(req.Path)),
Data: data,
}, nil
case *LokiLabelNamesRequest:
var resp loghttp.LabelResponse
if err := json.Unmarshal(buf, &resp); err != nil {
return nil, httpgrpc.Errorf(http.StatusInternalServerError, "error decoding response: %v", err)
}
return &LokiLabelNamesResponse{
Status: resp.Status,
Version: uint32(loghttp.GetVersion(req.Path)),
Data: resp.Data,
}, nil
default:
var resp loghttp.QueryResponse
if err := json.Unmarshal(buf, &resp); err != nil {
@ -277,6 +350,7 @@ func (codec) DecodeResponse(ctx context.Context, r *http.Response, req queryrang
func (codec) EncodeResponse(ctx context.Context, res queryrange.Response) (*http.Response, error) {
sp, _ := opentracing.StartSpanFromContext(ctx, "codec.EncodeResponse")
defer sp.Finish()
var buf bytes.Buffer
switch response := res.(type) {
case *LokiPromResponse:
@ -294,7 +368,6 @@ func (codec) EncodeResponse(ctx context.Context, res queryrange.Response) (*http
Data: logql.Streams(streams),
Statistics: response.Statistics,
}
var buf bytes.Buffer
if loghttp.Version(response.Version) == loghttp.VersionLegacy {
if err := marshal_legacy.WriteQueryResponseJSON(result, &buf); err != nil {
return nil, err
@ -305,38 +378,37 @@ func (codec) EncodeResponse(ctx context.Context, res queryrange.Response) (*http
}
}
sp.LogFields(otlog.Int("bytes", buf.Len()))
resp := http.Response{
Header: http.Header{
"Content-Type": []string{"application/json"},
},
Body: ioutil.NopCloser(&buf),
StatusCode: http.StatusOK,
}
return &resp, nil
case *LokiSeriesResponse:
result := logproto.SeriesResponse{
Series: response.Data,
}
var buf bytes.Buffer
if err := marshal.WriteSeriesResponseJSON(result, &buf); err != nil {
return nil, err
}
sp.LogFields(otlog.Int("bytes", buf.Len()))
resp := http.Response{
Header: http.Header{
"Content-Type": []string{"application/json"},
},
Body: ioutil.NopCloser(&buf),
StatusCode: http.StatusOK,
case *LokiLabelNamesResponse:
if loghttp.Version(response.Version) == loghttp.VersionLegacy {
if err := marshal_legacy.WriteLabelResponseJSON(logproto.LabelResponse{Values: response.Data}, &buf); err != nil {
return nil, err
}
} else {
if err := marshal.WriteLabelResponseJSON(logproto.LabelResponse{Values: response.Data}, &buf); err != nil {
return nil, err
}
}
return &resp, nil
default:
return nil, httpgrpc.Errorf(http.StatusInternalServerError, "invalid response format")
}
sp.LogFields(otlog.Int("bytes", buf.Len()))
resp := http.Response{
Header: http.Header{
"Content-Type": []string{"application/json"},
},
Body: ioutil.NopCloser(&buf),
StatusCode: http.StatusOK,
}
return &resp, nil
}
func (codec) MergeResponse(responses ...queryrange.Response) (queryrange.Response, error) {
@ -406,6 +478,28 @@ func (codec) MergeResponse(responses ...queryrange.Response) (queryrange.Respons
Version: lokiSeriesRes.Version,
Data: lokiSeriesData,
}, nil
case *LokiLabelNamesResponse:
labelNameRes := responses[0].(*LokiLabelNamesResponse)
uniqueNames := make(map[string]struct{})
names := []string{}
// only unique name should be merged
for _, res := range responses {
lokiResult := res.(*LokiLabelNamesResponse)
for _, labelName := range lokiResult.Data {
if _, ok := uniqueNames[labelName]; !ok {
names = append(names, labelName)
uniqueNames[labelName] = struct{}{}
}
}
}
return &LokiLabelNamesResponse{
Status: labelNameRes.Status,
Version: labelNameRes.Version,
Data: names,
}, nil
default:
return nil, errors.New("unknown response in merging responses")
}

@ -57,6 +57,14 @@ func Test_codec_DecodeRequest(t *testing.T) {
StartTs: start,
EndTs: end,
}, false},
{"labels", func() (*http.Request, error) {
return http.NewRequest(http.MethodGet,
fmt.Sprintf(`/label?start=%d&end=%d`, start.UnixNano(), end.UnixNano()), nil)
}, &LokiLabelNamesRequest{
Path: "/label",
StartTs: start,
EndTs: end,
}, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@ -131,6 +139,13 @@ func Test_codec_DecodeResponse(t *testing.T) {
Version: uint32(loghttp.VersionV1),
Data: seriesData,
}, false},
{"labels legacy", &http.Response{StatusCode: 200, Body: ioutil.NopCloser(strings.NewReader(labelsString))},
&LokiLabelNamesRequest{Path: "/api/prom/label"},
&LokiLabelNamesResponse{
Status: "success",
Version: uint32(loghttp.VersionLegacy),
Data: labelsData,
}, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@ -213,6 +228,29 @@ func Test_codec_series_EncodeRequest(t *testing.T) {
require.Equal(t, "/loki/api/v1/series", req.(*LokiSeriesRequest).Path)
}
func Test_codec_labels_EncodeRequest(t *testing.T) {
ctx := context.Background()
toEncode := &LokiLabelNamesRequest{
Path: "/loki/api/v1/labels",
StartTs: start,
EndTs: end,
}
got, err := lokiCodec.EncodeRequest(ctx, toEncode)
require.NoError(t, err)
require.Equal(t, ctx, got.Context())
require.Equal(t, "/loki/api/v1/labels", got.URL.Path)
require.Equal(t, fmt.Sprintf("%d", start.UnixNano()), got.URL.Query().Get("start"))
require.Equal(t, fmt.Sprintf("%d", end.UnixNano()), got.URL.Query().Get("end"))
// testing a full roundtrip
req, err := lokiCodec.DecodeRequest(context.TODO(), got)
require.NoError(t, err)
require.Equal(t, toEncode.StartTs, req.(*LokiLabelNamesRequest).StartTs)
require.Equal(t, toEncode.EndTs, req.(*LokiLabelNamesRequest).EndTs)
require.Equal(t, "/loki/api/v1/labels", req.(*LokiLabelNamesRequest).Path)
}
func Test_codec_EncodeResponse(t *testing.T) {
tests := []struct {
@ -262,6 +300,18 @@ func Test_codec_EncodeResponse(t *testing.T) {
Version: uint32(loghttp.VersionV1),
Data: seriesData,
}, seriesString, false},
{"loki labels",
&LokiLabelNamesResponse{
Status: "success",
Version: uint32(loghttp.VersionV1),
Data: labelsData,
}, labelsString, false},
{"loki labels legacy",
&LokiLabelNamesResponse{
Status: "success",
Version: uint32(loghttp.VersionLegacy),
Data: labelsData,
}, labelsLegacyString, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@ -700,6 +750,32 @@ func Test_codec_MergeResponse(t *testing.T) {
},
false,
},
{
"loki labels",
[]queryrange.Response{
&LokiLabelNamesResponse{
Status: "success",
Version: 1,
Data: []string{"foo", "bar", "buzz"},
},
&LokiLabelNamesResponse{
Status: "success",
Version: 1,
Data: []string{"foo", "bar", "buzz"},
},
&LokiLabelNamesResponse{
Status: "success",
Version: 1,
Data: []string{"foo", "blip", "blop"},
},
},
&LokiLabelNamesResponse{
Status: "success",
Version: 1,
Data: []string{"foo", "bar", "buzz", "blip", "blop"},
},
false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@ -867,6 +943,20 @@ var (
Labels: map[string]string{"filename": "/var/hostlog/test.log", "job": "varlogs"},
},
}
labelsString = `{
"status": "success",
"data": [
"foo",
"bar"
]
}`
labelsLegacyString = `{
"values": [
"foo",
"bar"
]
}`
labelsData = []string{"foo", "bar"}
statsResult = stats.Result{
Summary: stats.Summary{
BytesProcessedPerSecond: 20,

@ -17,9 +17,13 @@ type Limits interface {
type limits struct {
Limits
splitDuration time.Duration
overrides bool
}
func (l limits) QuerySplitDuration(user string) time.Duration {
if !l.overrides {
return l.splitDuration
}
dur := l.Limits.QuerySplitDuration(user)
if dur == 0 {
return l.splitDuration
@ -30,7 +34,8 @@ func (l limits) QuerySplitDuration(user string) time.Duration {
// WithDefaults will construct a Limits with a default value for QuerySplitDuration when no overrides are present.
func WithDefaultLimits(l Limits, conf queryrange.Config) Limits {
res := limits{
Limits: l,
Limits: l,
overrides: true,
}
if conf.SplitQueriesByDay {
@ -44,6 +49,14 @@ func WithDefaultLimits(l Limits, conf queryrange.Config) Limits {
return res
}
// WithSplitByLimits will construct a Limits with a static split by duration.
func WithSplitByLimits(l Limits, splitBy time.Duration) Limits {
return limits{
Limits: l,
splitDuration: splitBy,
}
}
// cacheKeyLimits intersects Limits and CacheSplitter
type cacheKeyLimits struct {
Limits

@ -356,6 +356,124 @@ func (m *LokiSeriesResponse) GetVersion() uint32 {
return 0
}
type LokiLabelNamesRequest struct {
StartTs time.Time `protobuf:"bytes,1,opt,name=startTs,proto3,stdtime" json:"startTs"`
EndTs time.Time `protobuf:"bytes,2,opt,name=endTs,proto3,stdtime" json:"endTs"`
Path string `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"`
}
func (m *LokiLabelNamesRequest) Reset() { *m = LokiLabelNamesRequest{} }
func (*LokiLabelNamesRequest) ProtoMessage() {}
func (*LokiLabelNamesRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_51b9d53b40d11902, []int{4}
}
func (m *LokiLabelNamesRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *LokiLabelNamesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_LokiLabelNamesRequest.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalTo(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *LokiLabelNamesRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_LokiLabelNamesRequest.Merge(m, src)
}
func (m *LokiLabelNamesRequest) XXX_Size() int {
return m.Size()
}
func (m *LokiLabelNamesRequest) XXX_DiscardUnknown() {
xxx_messageInfo_LokiLabelNamesRequest.DiscardUnknown(m)
}
var xxx_messageInfo_LokiLabelNamesRequest proto.InternalMessageInfo
func (m *LokiLabelNamesRequest) GetStartTs() time.Time {
if m != nil {
return m.StartTs
}
return time.Time{}
}
func (m *LokiLabelNamesRequest) GetEndTs() time.Time {
if m != nil {
return m.EndTs
}
return time.Time{}
}
func (m *LokiLabelNamesRequest) GetPath() string {
if m != nil {
return m.Path
}
return ""
}
type LokiLabelNamesResponse struct {
Status string `protobuf:"bytes,1,opt,name=Status,json=status,proto3" json:"status"`
Data []string `protobuf:"bytes,2,rep,name=Data,json=data,proto3" json:"data,omitempty"`
Version uint32 `protobuf:"varint,3,opt,name=version,proto3" json:"version,omitempty"`
}
func (m *LokiLabelNamesResponse) Reset() { *m = LokiLabelNamesResponse{} }
func (*LokiLabelNamesResponse) ProtoMessage() {}
func (*LokiLabelNamesResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_51b9d53b40d11902, []int{5}
}
func (m *LokiLabelNamesResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *LokiLabelNamesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_LokiLabelNamesResponse.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalTo(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *LokiLabelNamesResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_LokiLabelNamesResponse.Merge(m, src)
}
func (m *LokiLabelNamesResponse) XXX_Size() int {
return m.Size()
}
func (m *LokiLabelNamesResponse) XXX_DiscardUnknown() {
xxx_messageInfo_LokiLabelNamesResponse.DiscardUnknown(m)
}
var xxx_messageInfo_LokiLabelNamesResponse proto.InternalMessageInfo
func (m *LokiLabelNamesResponse) GetStatus() string {
if m != nil {
return m.Status
}
return ""
}
func (m *LokiLabelNamesResponse) GetData() []string {
if m != nil {
return m.Data
}
return nil
}
func (m *LokiLabelNamesResponse) GetVersion() uint32 {
if m != nil {
return m.Version
}
return 0
}
type LokiData struct {
ResultType string `protobuf:"bytes,1,opt,name=ResultType,json=resultType,proto3" json:"resultType"`
Result []github_com_grafana_loki_pkg_logproto.Stream `protobuf:"bytes,2,rep,name=Result,json=result,proto3,customtype=github.com/grafana/loki/pkg/logproto.Stream" json:"result"`
@ -364,7 +482,7 @@ type LokiData struct {
func (m *LokiData) Reset() { *m = LokiData{} }
func (*LokiData) ProtoMessage() {}
func (*LokiData) Descriptor() ([]byte, []int) {
return fileDescriptor_51b9d53b40d11902, []int{4}
return fileDescriptor_51b9d53b40d11902, []int{6}
}
func (m *LokiData) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -409,7 +527,7 @@ type LokiPromResponse struct {
func (m *LokiPromResponse) Reset() { *m = LokiPromResponse{} }
func (*LokiPromResponse) ProtoMessage() {}
func (*LokiPromResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_51b9d53b40d11902, []int{5}
return fileDescriptor_51b9d53b40d11902, []int{7}
}
func (m *LokiPromResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@ -457,6 +575,8 @@ func init() {
proto.RegisterType((*LokiResponse)(nil), "queryrange.LokiResponse")
proto.RegisterType((*LokiSeriesRequest)(nil), "queryrange.LokiSeriesRequest")
proto.RegisterType((*LokiSeriesResponse)(nil), "queryrange.LokiSeriesResponse")
proto.RegisterType((*LokiLabelNamesRequest)(nil), "queryrange.LokiLabelNamesRequest")
proto.RegisterType((*LokiLabelNamesResponse)(nil), "queryrange.LokiLabelNamesResponse")
proto.RegisterType((*LokiData)(nil), "queryrange.LokiData")
proto.RegisterType((*LokiPromResponse)(nil), "queryrange.LokiPromResponse")
}
@ -466,55 +586,58 @@ func init() {
}
var fileDescriptor_51b9d53b40d11902 = []byte{
// 764 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x54, 0x4f, 0x6f, 0x13, 0x39,
0x14, 0x1f, 0xe7, 0x7f, 0x9c, 0x6d, 0x77, 0xd7, 0xad, 0xb6, 0xa3, 0xac, 0x34, 0x13, 0xe5, 0xb2,
0x59, 0xed, 0x32, 0x11, 0x29, 0x5c, 0x90, 0x40, 0xed, 0xa8, 0x80, 0x90, 0x38, 0xa0, 0x69, 0xbe,
0x80, 0x9b, 0xb8, 0x93, 0xa1, 0x99, 0x78, 0x6a, 0x3b, 0x88, 0xde, 0xb8, 0x72, 0xeb, 0x99, 0x4f,
0x80, 0x38, 0x73, 0xe1, 0x1b, 0xf4, 0xd8, 0x63, 0xc5, 0x21, 0xd0, 0xf4, 0x82, 0x72, 0xea, 0x07,
0xe0, 0x80, 0x6c, 0xcf, 0x4c, 0x5c, 0x84, 0x44, 0x2b, 0x2e, 0xf1, 0x7b, 0xcf, 0xef, 0x67, 0xff,
0xfc, 0x7b, 0xbf, 0x0c, 0xfc, 0x27, 0x39, 0x08, 0xbb, 0x87, 0x53, 0xc2, 0x22, 0xc2, 0xd4, 0x7a,
0xc4, 0xf0, 0x24, 0x24, 0x46, 0xe8, 0x25, 0x8c, 0x0a, 0x8a, 0xe0, 0xb2, 0xd2, 0xbc, 0x15, 0x46,
0x62, 0x34, 0xdd, 0xf3, 0x06, 0x34, 0xee, 0x86, 0x34, 0xa4, 0x5d, 0xd5, 0xb2, 0x37, 0xdd, 0x57,
0x99, 0x4a, 0x54, 0xa4, 0xa1, 0xcd, 0xbf, 0xe5, 0x1d, 0x63, 0x1a, 0xea, 0x8d, 0x2c, 0xf8, 0x6e,
0xf3, 0x70, 0xdc, 0xe5, 0x02, 0x0b, 0xae, 0x7f, 0xd3, 0xcd, 0xc7, 0xc6, 0x45, 0x03, 0xca, 0x04,
0x79, 0x99, 0x30, 0xfa, 0x9c, 0x0c, 0x44, 0x9a, 0x75, 0xaf, 0xc9, 0xbe, 0xe9, 0x86, 0x94, 0x86,
0x63, 0xb2, 0x24, 0x2a, 0xa2, 0x98, 0x70, 0x81, 0xe3, 0x44, 0x37, 0xb4, 0xdf, 0x17, 0x60, 0xe3,
0x29, 0x3d, 0x88, 0x02, 0x72, 0x38, 0x25, 0x5c, 0xa0, 0x75, 0x58, 0x56, 0x87, 0xd8, 0xa0, 0x05,
0x3a, 0xf5, 0x40, 0x27, 0xb2, 0x3a, 0x8e, 0xe2, 0x48, 0xd8, 0x85, 0x16, 0xe8, 0xac, 0x04, 0x3a,
0x41, 0x08, 0x96, 0xb8, 0x20, 0x89, 0x5d, 0x6c, 0x81, 0x4e, 0x31, 0x50, 0x31, 0x7a, 0x00, 0xab,
0x5c, 0x60, 0x26, 0xfa, 0xdc, 0x2e, 0xb5, 0x40, 0xa7, 0xd1, 0x6b, 0x7a, 0x9a, 0x82, 0x97, 0x51,
0xf0, 0xfa, 0x19, 0x05, 0xbf, 0x76, 0x32, 0x73, 0xad, 0xe3, 0x4f, 0x2e, 0x08, 0x32, 0x10, 0xba,
0x07, 0xcb, 0x64, 0x32, 0xec, 0x73, 0xbb, 0x7c, 0x03, 0xb4, 0x86, 0xa0, 0xdb, 0xb0, 0x3e, 0x8c,
0x18, 0x19, 0x88, 0x88, 0x4e, 0xec, 0x4a, 0x0b, 0x74, 0x56, 0x7b, 0x6b, 0x5e, 0x2e, 0xfb, 0x4e,
0xb6, 0x15, 0x2c, 0xbb, 0xe4, 0x13, 0x12, 0x2c, 0x46, 0x76, 0x55, 0xbd, 0x56, 0xc5, 0xa8, 0x0d,
0x2b, 0x7c, 0x84, 0xd9, 0x90, 0xdb, 0xb5, 0x56, 0xb1, 0x53, 0xf7, 0xe1, 0x62, 0xe6, 0xa6, 0x95,
0x20, 0x5d, 0xdb, 0x5f, 0x0b, 0xf0, 0x37, 0x2d, 0x1b, 0x4f, 0xe8, 0x84, 0x13, 0x09, 0xda, 0x15,
0x58, 0x4c, 0xb9, 0x16, 0x2e, 0x05, 0xa9, 0x4a, 0x90, 0xae, 0x68, 0x0b, 0x96, 0x76, 0xb0, 0xc0,
0x4a, 0xc4, 0x46, 0x6f, 0xdd, 0x33, 0xa6, 0x25, 0xcf, 0x92, 0x7b, 0xfe, 0x5f, 0xf2, 0x51, 0x8b,
0x99, 0xbb, 0x3a, 0xc4, 0x02, 0xff, 0x4f, 0xe3, 0x48, 0x90, 0x38, 0x11, 0x47, 0x41, 0x49, 0xe6,
0xe8, 0x2e, 0xac, 0x3f, 0x64, 0x8c, 0xb2, 0xfe, 0x51, 0x42, 0x94, 0xec, 0x75, 0x7f, 0x63, 0x31,
0x73, 0xd7, 0x48, 0x56, 0x34, 0x10, 0xf5, 0xbc, 0x88, 0xfe, 0x85, 0x65, 0x05, 0x53, 0x23, 0xa9,
0xfb, 0x6b, 0x8b, 0x99, 0xfb, 0xbb, 0xda, 0x35, 0xda, 0xcb, 0xaa, 0x70, 0x55, 0xc3, 0xf2, 0xb5,
0x34, 0xcc, 0xcd, 0x51, 0x31, 0xcd, 0x61, 0xc3, 0xea, 0x0b, 0xc2, 0xb8, 0x3c, 0xa6, 0xaa, 0xea,
0x59, 0x8a, 0xb6, 0x21, 0x94, 0x82, 0x44, 0x5c, 0x44, 0x03, 0xa9, 0xb1, 0x14, 0x63, 0xc5, 0xd3,
0xf6, 0x0f, 0x08, 0x9f, 0x8e, 0x85, 0x8f, 0x52, 0x15, 0x8c, 0xc6, 0xc0, 0x88, 0xdb, 0x1f, 0x00,
0xfc, 0x53, 0x4a, 0xb6, 0x2b, 0xff, 0x01, 0xdc, 0xf0, 0x6e, 0x8c, 0xc5, 0x60, 0x64, 0x03, 0x39,
0xb7, 0x40, 0x27, 0xa6, 0x23, 0x0b, 0xbf, 0xe4, 0xc8, 0xe2, 0xcd, 0x1d, 0x99, 0xd9, 0xab, 0xb4,
0xb4, 0x57, 0xfb, 0x0d, 0x80, 0xc8, 0xe4, 0x7e, 0x03, 0x03, 0x3d, 0xca, 0x0d, 0x54, 0x54, 0x4c,
0xf2, 0xb9, 0xe8, 0xb3, 0x9e, 0x0c, 0xc9, 0x44, 0x44, 0xfb, 0x11, 0x61, 0x3f, 0xb1, 0x91, 0x31,
0x9b, 0xe2, 0x95, 0xd9, 0xb4, 0xdf, 0x01, 0x58, 0xcb, 0xbc, 0x88, 0x3c, 0x08, 0xf5, 0x3c, 0x94,
0xdd, 0x34, 0xad, 0x55, 0x39, 0x15, 0x96, 0x57, 0x03, 0x23, 0x46, 0x13, 0x58, 0xd1, 0xfd, 0x29,
0xc1, 0x0d, 0x83, 0xa0, 0x60, 0x04, 0xc7, 0xdb, 0x43, 0x9c, 0x08, 0xc2, 0xfc, 0xfb, 0x92, 0xdd,
0xc7, 0x99, 0xfb, 0x9f, 0xf9, 0x3d, 0x65, 0x78, 0x1f, 0x4f, 0x70, 0x77, 0x4c, 0x0f, 0xa2, 0xae,
0xf9, 0xe1, 0x4c, 0xb1, 0x52, 0x0e, 0x7d, 0x57, 0x90, 0xae, 0xed, 0xd7, 0x00, 0xfe, 0x21, 0xc9,
0x3e, 0x63, 0x34, 0xce, 0x75, 0xdc, 0x82, 0x35, 0x96, 0xc6, 0x8a, 0x72, 0xa3, 0xe7, 0x98, 0x7f,
0x34, 0xd9, 0x4b, 0xc4, 0x88, 0x4c, 0x73, 0xe5, 0xfd, 0xd2, 0xc9, 0xcc, 0x05, 0x41, 0x8e, 0x42,
0x9b, 0x57, 0xfc, 0x59, 0xf8, 0x91, 0x3f, 0x25, 0xc4, 0x32, 0x1d, 0xe9, 0xdf, 0x39, 0x3d, 0x77,
0xac, 0xb3, 0x73, 0xc7, 0xba, 0x3c, 0x77, 0xc0, 0xab, 0xb9, 0x03, 0xde, 0xce, 0x1d, 0x70, 0x32,
0x77, 0xc0, 0xe9, 0xdc, 0x01, 0x9f, 0xe7, 0x0e, 0xf8, 0x32, 0x77, 0xac, 0xcb, 0xb9, 0x03, 0x8e,
0x2f, 0x1c, 0xeb, 0xf4, 0xc2, 0xb1, 0xce, 0x2e, 0x1c, 0x6b, 0xaf, 0xa2, 0x5e, 0xb8, 0xf9, 0x2d,
0x00, 0x00, 0xff, 0xff, 0x93, 0x63, 0xfc, 0xe4, 0x8e, 0x06, 0x00, 0x00,
// 809 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x55, 0xcd, 0x6e, 0x2b, 0x35,
0x14, 0x1e, 0xe7, 0x7f, 0x5c, 0x5a, 0xc0, 0x2d, 0xed, 0x28, 0x48, 0x33, 0x51, 0x16, 0x10, 0x04,
0x4c, 0x44, 0x0b, 0x1b, 0x24, 0x50, 0x3b, 0x2a, 0x20, 0xa4, 0x0a, 0xa1, 0x69, 0x5e, 0xc0, 0x49,
0xdc, 0xc9, 0xd0, 0x4c, 0x3c, 0xb5, 0x1d, 0x44, 0x37, 0x88, 0x2d, 0xbb, 0xae, 0x79, 0x01, 0x10,
0x6b, 0x36, 0xbc, 0x41, 0x97, 0x5d, 0x56, 0x2c, 0x02, 0x4d, 0x37, 0x28, 0xab, 0x3e, 0xc0, 0x5d,
0x5c, 0xd9, 0x9e, 0x99, 0xb8, 0xd5, 0x95, 0x6e, 0xd3, 0x6e, 0xe2, 0x73, 0x8e, 0xcf, 0x67, 0x1f,
0x7f, 0xe7, 0x3b, 0x19, 0xf8, 0x7e, 0x7a, 0x1a, 0x75, 0xcf, 0xa6, 0x84, 0xc5, 0x84, 0xa9, 0xf5,
0x9c, 0xe1, 0x49, 0x44, 0x0c, 0xd3, 0x4f, 0x19, 0x15, 0x14, 0xc1, 0x65, 0xa4, 0xf9, 0x71, 0x14,
0x8b, 0xd1, 0xb4, 0xef, 0x0f, 0x68, 0xd2, 0x8d, 0x68, 0x44, 0xbb, 0x2a, 0xa5, 0x3f, 0x3d, 0x51,
0x9e, 0x72, 0x94, 0xa5, 0xa1, 0xcd, 0x77, 0xe5, 0x1d, 0x63, 0x1a, 0xe9, 0x8d, 0xdc, 0x78, 0xb0,
0x79, 0x36, 0xee, 0x72, 0x81, 0x05, 0xd7, 0xbf, 0xd9, 0xe6, 0x37, 0xc6, 0x45, 0x03, 0xca, 0x04,
0xf9, 0x29, 0x65, 0xf4, 0x07, 0x32, 0x10, 0x99, 0xd7, 0x7d, 0x64, 0xf5, 0x4d, 0x2f, 0xa2, 0x34,
0x1a, 0x93, 0x65, 0xa1, 0x22, 0x4e, 0x08, 0x17, 0x38, 0x49, 0x75, 0x42, 0xfb, 0xaf, 0x12, 0x5c,
0x3b, 0xa2, 0xa7, 0x71, 0x48, 0xce, 0xa6, 0x84, 0x0b, 0xb4, 0x05, 0xab, 0xea, 0x10, 0x07, 0xb4,
0x40, 0xc7, 0x0e, 0xb5, 0x23, 0xa3, 0xe3, 0x38, 0x89, 0x85, 0x53, 0x6a, 0x81, 0xce, 0x7a, 0xa8,
0x1d, 0x84, 0x60, 0x85, 0x0b, 0x92, 0x3a, 0xe5, 0x16, 0xe8, 0x94, 0x43, 0x65, 0xa3, 0x2f, 0x61,
0x9d, 0x0b, 0xcc, 0x44, 0x8f, 0x3b, 0x95, 0x16, 0xe8, 0xac, 0xed, 0x36, 0x7d, 0x5d, 0x82, 0x9f,
0x97, 0xe0, 0xf7, 0xf2, 0x12, 0x82, 0xc6, 0xe5, 0xcc, 0xb3, 0x2e, 0xfe, 0xf5, 0x40, 0x98, 0x83,
0xd0, 0xe7, 0xb0, 0x4a, 0x26, 0xc3, 0x1e, 0x77, 0xaa, 0x2b, 0xa0, 0x35, 0x04, 0x7d, 0x02, 0xed,
0x61, 0xcc, 0xc8, 0x40, 0xc4, 0x74, 0xe2, 0xd4, 0x5a, 0xa0, 0xb3, 0xb1, 0xbb, 0xe9, 0x17, 0xb4,
0x1f, 0xe6, 0x5b, 0xe1, 0x32, 0x4b, 0x3e, 0x21, 0xc5, 0x62, 0xe4, 0xd4, 0xd5, 0x6b, 0x95, 0x8d,
0xda, 0xb0, 0xc6, 0x47, 0x98, 0x0d, 0xb9, 0xd3, 0x68, 0x95, 0x3b, 0x76, 0x00, 0x17, 0x33, 0x2f,
0x8b, 0x84, 0xd9, 0xda, 0x7e, 0x51, 0x82, 0x6f, 0x68, 0xda, 0x78, 0x4a, 0x27, 0x9c, 0x48, 0xd0,
0xb1, 0xc0, 0x62, 0xca, 0x35, 0x71, 0x19, 0x48, 0x45, 0xc2, 0x6c, 0x45, 0xfb, 0xb0, 0x72, 0x88,
0x05, 0x56, 0x24, 0xae, 0xed, 0x6e, 0xf9, 0x46, 0xb7, 0xe4, 0x59, 0x72, 0x2f, 0xd8, 0x96, 0x8f,
0x5a, 0xcc, 0xbc, 0x8d, 0x21, 0x16, 0xf8, 0x23, 0x9a, 0xc4, 0x82, 0x24, 0xa9, 0x38, 0x0f, 0x2b,
0xd2, 0x47, 0x9f, 0x41, 0xfb, 0x2b, 0xc6, 0x28, 0xeb, 0x9d, 0xa7, 0x44, 0xd1, 0x6e, 0x07, 0x3b,
0x8b, 0x99, 0xb7, 0x49, 0xf2, 0xa0, 0x81, 0xb0, 0x8b, 0x20, 0xfa, 0x00, 0x56, 0x15, 0x4c, 0xb5,
0xc4, 0x0e, 0x36, 0x17, 0x33, 0xef, 0x4d, 0xb5, 0x6b, 0xa4, 0x57, 0x55, 0xe0, 0x3e, 0x87, 0xd5,
0x47, 0x71, 0x58, 0x88, 0xa3, 0x66, 0x8a, 0xc3, 0x81, 0xf5, 0x1f, 0x09, 0xe3, 0xf2, 0x98, 0xba,
0x8a, 0xe7, 0x2e, 0x3a, 0x80, 0x50, 0x12, 0x12, 0x73, 0x11, 0x0f, 0x24, 0xc7, 0x92, 0x8c, 0x75,
0x5f, 0xcb, 0x3f, 0x24, 0x7c, 0x3a, 0x16, 0x01, 0xca, 0x58, 0x30, 0x12, 0x43, 0xc3, 0x6e, 0xff,
0x0d, 0xe0, 0xdb, 0x92, 0xb2, 0x63, 0x39, 0x01, 0xdc, 0xd0, 0x6e, 0x82, 0xc5, 0x60, 0xe4, 0x00,
0xd9, 0xb7, 0x50, 0x3b, 0xa6, 0x22, 0x4b, 0xcf, 0x52, 0x64, 0x79, 0x75, 0x45, 0xe6, 0xf2, 0xaa,
0x2c, 0xe5, 0xd5, 0xfe, 0x0d, 0x40, 0x64, 0xd6, 0xbe, 0x82, 0x80, 0xbe, 0x2e, 0x04, 0x54, 0x56,
0x95, 0x14, 0x7d, 0xd1, 0x67, 0x7d, 0x3b, 0x24, 0x13, 0x11, 0x9f, 0xc4, 0x84, 0xbd, 0x46, 0x46,
0x46, 0x6f, 0xca, 0xf7, 0x7a, 0xd3, 0xfe, 0x1d, 0xc0, 0x77, 0x64, 0x71, 0x47, 0xb8, 0x4f, 0xc6,
0xdf, 0xe1, 0x64, 0x49, 0xae, 0x41, 0x23, 0x78, 0x16, 0x8d, 0xa5, 0xa7, 0xd3, 0x58, 0x36, 0x68,
0xfc, 0x19, 0x6e, 0x3f, 0x2c, 0x74, 0x05, 0x26, 0xdf, 0x33, 0x98, 0xb4, 0x03, 0xf4, 0x04, 0xa6,
0xfe, 0x04, 0xb0, 0x91, 0x4f, 0x2d, 0xf2, 0x21, 0xd4, 0xca, 0x55, 0x83, 0xa9, 0xaf, 0xdd, 0x90,
0xfa, 0x65, 0x45, 0x34, 0x34, 0x6c, 0x34, 0x81, 0x35, 0x9d, 0x9f, 0xb5, 0x72, 0xc7, 0x68, 0xa5,
0x60, 0x04, 0x27, 0x07, 0x43, 0x9c, 0x0a, 0xc2, 0x82, 0x2f, 0x24, 0x15, 0xff, 0xcc, 0xbc, 0x0f,
0xcd, 0x2f, 0x0f, 0xc3, 0x27, 0x78, 0x82, 0xbb, 0x63, 0x7a, 0x1a, 0x77, 0xcd, 0x4f, 0x4c, 0x86,
0x95, 0xcf, 0xd5, 0x77, 0x85, 0xd9, 0xda, 0xfe, 0x15, 0xc0, 0xb7, 0x64, 0xb1, 0xdf, 0x33, 0x9a,
0x14, 0x3c, 0xed, 0xc3, 0x06, 0xcb, 0xec, 0xac, 0xa5, 0xae, 0xf9, 0x97, 0x24, 0x73, 0x89, 0x18,
0x91, 0x69, 0xc1, 0x6c, 0x50, 0xb9, 0x9c, 0x79, 0x20, 0x2c, 0x50, 0x68, 0xef, 0xde, 0x24, 0x97,
0x5e, 0x35, 0xc9, 0x12, 0x62, 0x99, 0xb3, 0x1b, 0x7c, 0x7a, 0x75, 0xe3, 0x5a, 0xd7, 0x37, 0xae,
0x75, 0x77, 0xe3, 0x82, 0x5f, 0xe6, 0x2e, 0xf8, 0x63, 0xee, 0x82, 0xcb, 0xb9, 0x0b, 0xae, 0xe6,
0x2e, 0xf8, 0x6f, 0xee, 0x82, 0xff, 0xe7, 0xae, 0x75, 0x37, 0x77, 0xc1, 0xc5, 0xad, 0x6b, 0x5d,
0xdd, 0xba, 0xd6, 0xf5, 0xad, 0x6b, 0xf5, 0x6b, 0xea, 0x85, 0x7b, 0x2f, 0x03, 0x00, 0x00, 0xff,
0xff, 0x48, 0xfc, 0x00, 0x53, 0xb8, 0x07, 0x00, 0x00,
}
func (this *LokiRequest) Equal(that interface{}) bool {
@ -685,6 +808,71 @@ func (this *LokiSeriesResponse) Equal(that interface{}) bool {
}
return true
}
func (this *LokiLabelNamesRequest) Equal(that interface{}) bool {
if that == nil {
return this == nil
}
that1, ok := that.(*LokiLabelNamesRequest)
if !ok {
that2, ok := that.(LokiLabelNamesRequest)
if ok {
that1 = &that2
} else {
return false
}
}
if that1 == nil {
return this == nil
} else if this == nil {
return false
}
if !this.StartTs.Equal(that1.StartTs) {
return false
}
if !this.EndTs.Equal(that1.EndTs) {
return false
}
if this.Path != that1.Path {
return false
}
return true
}
func (this *LokiLabelNamesResponse) Equal(that interface{}) bool {
if that == nil {
return this == nil
}
that1, ok := that.(*LokiLabelNamesResponse)
if !ok {
that2, ok := that.(LokiLabelNamesResponse)
if ok {
that1 = &that2
} else {
return false
}
}
if that1 == nil {
return this == nil
} else if this == nil {
return false
}
if this.Status != that1.Status {
return false
}
if len(this.Data) != len(that1.Data) {
return false
}
for i := range this.Data {
if this.Data[i] != that1.Data[i] {
return false
}
}
if this.Version != that1.Version {
return false
}
return true
}
func (this *LokiData) Equal(that interface{}) bool {
if that == nil {
return this == nil
@ -809,6 +997,30 @@ func (this *LokiSeriesResponse) GoString() string {
s = append(s, "}")
return strings.Join(s, "")
}
func (this *LokiLabelNamesRequest) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 7)
s = append(s, "&queryrange.LokiLabelNamesRequest{")
s = append(s, "StartTs: "+fmt.Sprintf("%#v", this.StartTs)+",\n")
s = append(s, "EndTs: "+fmt.Sprintf("%#v", this.EndTs)+",\n")
s = append(s, "Path: "+fmt.Sprintf("%#v", this.Path)+",\n")
s = append(s, "}")
return strings.Join(s, "")
}
func (this *LokiLabelNamesResponse) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 7)
s = append(s, "&queryrange.LokiLabelNamesResponse{")
s = append(s, "Status: "+fmt.Sprintf("%#v", this.Status)+",\n")
s = append(s, "Data: "+fmt.Sprintf("%#v", this.Data)+",\n")
s = append(s, "Version: "+fmt.Sprintf("%#v", this.Version)+",\n")
s = append(s, "}")
return strings.Join(s, "")
}
func (this *LokiData) GoString() string {
if this == nil {
return "nil"
@ -1080,6 +1292,90 @@ func (m *LokiSeriesResponse) MarshalTo(dAtA []byte) (int, error) {
return i, nil
}
func (m *LokiLabelNamesRequest) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *LokiLabelNamesRequest) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
dAtA[i] = 0xa
i++
i = encodeVarintQueryrange(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.StartTs)))
n7, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.StartTs, dAtA[i:])
if err != nil {
return 0, err
}
i += n7
dAtA[i] = 0x12
i++
i = encodeVarintQueryrange(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.EndTs)))
n8, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.EndTs, dAtA[i:])
if err != nil {
return 0, err
}
i += n8
if len(m.Path) > 0 {
dAtA[i] = 0x1a
i++
i = encodeVarintQueryrange(dAtA, i, uint64(len(m.Path)))
i += copy(dAtA[i:], m.Path)
}
return i, nil
}
func (m *LokiLabelNamesResponse) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *LokiLabelNamesResponse) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if len(m.Status) > 0 {
dAtA[i] = 0xa
i++
i = encodeVarintQueryrange(dAtA, i, uint64(len(m.Status)))
i += copy(dAtA[i:], m.Status)
}
if len(m.Data) > 0 {
for _, s := range m.Data {
dAtA[i] = 0x12
i++
l = len(s)
for l >= 1<<7 {
dAtA[i] = uint8(uint64(l)&0x7f | 0x80)
l >>= 7
i++
}
dAtA[i] = uint8(l)
i++
i += copy(dAtA[i:], s)
}
}
if m.Version != 0 {
dAtA[i] = 0x18
i++
i = encodeVarintQueryrange(dAtA, i, uint64(m.Version))
}
return i, nil
}
func (m *LokiData) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
@ -1135,20 +1431,20 @@ func (m *LokiPromResponse) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0xa
i++
i = encodeVarintQueryrange(dAtA, i, uint64(m.Response.Size()))
n7, err := m.Response.MarshalTo(dAtA[i:])
n9, err := m.Response.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n7
i += n9
}
dAtA[i] = 0x12
i++
i = encodeVarintQueryrange(dAtA, i, uint64(m.Statistics.Size()))
n8, err := m.Statistics.MarshalTo(dAtA[i:])
n10, err := m.Statistics.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n8
i += n10
return i, nil
}
@ -1276,38 +1572,77 @@ func (m *LokiSeriesResponse) Size() (n int) {
return n
}
func (m *LokiData) Size() (n int) {
func (m *LokiLabelNamesRequest) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.ResultType)
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.StartTs)
n += 1 + l + sovQueryrange(uint64(l))
l = github_com_gogo_protobuf_types.SizeOfStdTime(m.EndTs)
n += 1 + l + sovQueryrange(uint64(l))
l = len(m.Path)
if l > 0 {
n += 1 + l + sovQueryrange(uint64(l))
}
if len(m.Result) > 0 {
for _, e := range m.Result {
l = e.Size()
n += 1 + l + sovQueryrange(uint64(l))
}
}
return n
}
func (m *LokiPromResponse) Size() (n int) {
func (m *LokiLabelNamesResponse) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.Response != nil {
l = m.Response.Size()
l = len(m.Status)
if l > 0 {
n += 1 + l + sovQueryrange(uint64(l))
}
l = m.Statistics.Size()
n += 1 + l + sovQueryrange(uint64(l))
return n
if len(m.Data) > 0 {
for _, s := range m.Data {
l = len(s)
n += 1 + l + sovQueryrange(uint64(l))
}
}
if m.Version != 0 {
n += 1 + sovQueryrange(uint64(m.Version))
}
return n
}
func (m *LokiData) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.ResultType)
if l > 0 {
n += 1 + l + sovQueryrange(uint64(l))
}
if len(m.Result) > 0 {
for _, e := range m.Result {
l = e.Size()
n += 1 + l + sovQueryrange(uint64(l))
}
}
return n
}
func (m *LokiPromResponse) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.Response != nil {
l = m.Response.Size()
n += 1 + l + sovQueryrange(uint64(l))
}
l = m.Statistics.Size()
n += 1 + l + sovQueryrange(uint64(l))
return n
}
func sovQueryrange(x uint64) (n int) {
@ -1382,6 +1717,30 @@ func (this *LokiSeriesResponse) String() string {
}, "")
return s
}
func (this *LokiLabelNamesRequest) String() string {
if this == nil {
return "nil"
}
s := strings.Join([]string{`&LokiLabelNamesRequest{`,
`StartTs:` + strings.Replace(strings.Replace(this.StartTs.String(), "Timestamp", "types.Timestamp", 1), `&`, ``, 1) + `,`,
`EndTs:` + strings.Replace(strings.Replace(this.EndTs.String(), "Timestamp", "types.Timestamp", 1), `&`, ``, 1) + `,`,
`Path:` + fmt.Sprintf("%v", this.Path) + `,`,
`}`,
}, "")
return s
}
func (this *LokiLabelNamesResponse) String() string {
if this == nil {
return "nil"
}
s := strings.Join([]string{`&LokiLabelNamesResponse{`,
`Status:` + fmt.Sprintf("%v", this.Status) + `,`,
`Data:` + fmt.Sprintf("%v", this.Data) + `,`,
`Version:` + fmt.Sprintf("%v", this.Version) + `,`,
`}`,
}, "")
return s
}
func (this *LokiData) String() string {
if this == nil {
return "nil"
@ -2277,6 +2636,293 @@ func (m *LokiSeriesResponse) Unmarshal(dAtA []byte) error {
}
return nil
}
func (m *LokiLabelNamesRequest) 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: LokiLabelNamesRequest: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: LokiLabelNamesRequest: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field StartTs", 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 := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.StartTs, dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field EndTs", 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 := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.EndTs, dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Path", 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.Path = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipQueryrange(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthQueryrange
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthQueryrange
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *LokiLabelNamesResponse) 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: LokiLabelNamesResponse: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: LokiLabelNamesResponse: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Status", 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.Status = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Data", 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.Data = append(m.Data, string(dAtA[iNdEx:postIndex]))
iNdEx = postIndex
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType)
}
m.Version = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowQueryrange
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Version |= uint32(b&0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skipQueryrange(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthQueryrange
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthQueryrange
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *LokiData) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0

@ -46,6 +46,18 @@ message LokiSeriesResponse {
uint32 version = 3;
}
message LokiLabelNamesRequest {
google.protobuf.Timestamp startTs = 1 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
google.protobuf.Timestamp endTs = 2 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false];
string path = 3;
}
message LokiLabelNamesResponse {
string Status = 1 [(gogoproto.jsontag) = "status"];
repeated string Data = 2 [(gogoproto.jsontag) = "data,omitempty"];
uint32 version = 3;
}
message LokiData {
string ResultType = 1 [(gogoproto.jsontag) = "resultType"];
repeated logproto.StreamAdapter Result = 2 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "result", (gogoproto.customtype) = "github.com/grafana/loki/pkg/logproto.Stream"];

@ -69,27 +69,34 @@ func NewTripperware(
return nil, nil, err
}
labelsTripperware, err := NewLabelsTripperware(cfg, log, limits, lokiCodec, instrumentMetrics, retryMetrics, splitByMetrics)
if err != nil {
return nil, nil, err
}
return func(next http.RoundTripper) http.RoundTripper {
metricRT := metricsTripperware(next)
logFilterRT := logFilterTripperware(next)
seriesRT := seriesTripperware(next)
return newRoundTripper(next, logFilterRT, metricRT, seriesRT, limits)
labelsRT := labelsTripperware(next)
return newRoundTripper(next, logFilterRT, metricRT, seriesRT, labelsRT, limits)
}, cache, nil
}
type roundTripper struct {
next, log, metric, series http.RoundTripper
next, log, metric, series, labels http.RoundTripper
limits Limits
}
// newRoundTripper creates a new queryrange roundtripper
func newRoundTripper(next, log, metric, series http.RoundTripper, limits Limits) roundTripper {
func newRoundTripper(next, log, metric, series, labels http.RoundTripper, limits Limits) roundTripper {
return roundTripper{
log: log,
limits: limits,
metric: metric,
series: series,
labels: labels,
next: next,
}
}
@ -100,7 +107,7 @@ func (r roundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
return nil, httpgrpc.Errorf(http.StatusBadRequest, err.Error())
}
switch op := getOperation(req); op {
switch op := getOperation(req.URL.Path); op {
case QueryRangeOp:
rangeQuery, err := loghttp.ParseRangeQuery(req)
if err != nil {
@ -135,6 +142,12 @@ func (r roundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
return nil, httpgrpc.Errorf(http.StatusBadRequest, err.Error())
}
return r.series.RoundTrip(req)
case LabelNamesOp:
_, err := loghttp.ParseLabelQuery(req)
if err != nil {
return nil, httpgrpc.Errorf(http.StatusBadRequest, err.Error())
}
return r.labels.RoundTrip(req)
default:
return r.next.RoundTrip(req)
}
@ -173,14 +186,18 @@ func validateLimits(req *http.Request, reqLimit uint32, limits Limits) error {
const (
QueryRangeOp = "query_range"
SeriesOp = "series"
LabelNamesOp = "labels"
)
func getOperation(req *http.Request) string {
if strings.HasSuffix(req.URL.Path, "/query_range") || strings.HasSuffix(req.URL.Path, "/prom/query") {
func getOperation(path string) string {
switch {
case strings.HasSuffix(path, "/query_range") || strings.HasSuffix(path, "/prom/query"):
return QueryRangeOp
} else if strings.HasSuffix(req.URL.Path, "/series") {
case strings.HasSuffix(path, "/series"):
return SeriesOp
} else {
case strings.HasSuffix(path, "/labels") || strings.HasSuffix(path, "/label"):
return LabelNamesOp
default:
return ""
}
}
@ -242,7 +259,11 @@ func NewSeriesTripperware(
) (frontend.Tripperware, error) {
queryRangeMiddleware := []queryrange.Middleware{}
if cfg.SplitQueriesByInterval != 0 {
queryRangeMiddleware = append(queryRangeMiddleware, queryrange.InstrumentMiddleware("split_by_interval", instrumentMetrics), SplitByIntervalMiddleware(limits, codec, splitByMetrics))
queryRangeMiddleware = append(queryRangeMiddleware,
queryrange.InstrumentMiddleware("split_by_interval", instrumentMetrics),
// Force a 24 hours split by for series API, this will be more efficient with our static daily bucket storage.
SplitByIntervalMiddleware(WithSplitByLimits(limits, 24*time.Hour), codec, splitByMetrics),
)
}
if cfg.MaxRetries > 0 {
queryRangeMiddleware = append(queryRangeMiddleware, queryrange.InstrumentMiddleware("retry", instrumentMetrics), queryrange.NewRetryMiddleware(log, cfg.MaxRetries, retryMiddlewareMetrics))
@ -256,6 +277,20 @@ func NewSeriesTripperware(
}, nil
}
// NewLabelsTripperware creates a new frontend tripperware responsible for handling labels requests.
func NewLabelsTripperware(
cfg Config,
log log.Logger,
limits Limits,
codec queryrange.Codec,
instrumentMetrics *queryrange.InstrumentMiddlewareMetrics,
retryMiddlewareMetrics *queryrange.RetryMiddlewareMetrics,
splitByMetrics *SplitByMetrics,
) (frontend.Tripperware, error) {
// for now we'll use the same config as for the Series API.
return NewSeriesTripperware(cfg, log, limits, codec, instrumentMetrics, retryMiddlewareMetrics, splitByMetrics)
}
// NewMetricTripperware creates a new frontend tripperware responsible for handling metric queries
func NewMetricTripperware(
cfg Config,

@ -216,7 +216,7 @@ func TestSeriesTripperware(t *testing.T) {
lreq := &LokiSeriesRequest{
Match: []string{`{job="varlogs"}`},
StartTs: testTime.Add(-6 * time.Hour), // bigger than the limit
StartTs: testTime.Add(-25 * time.Hour), // bigger than the limit
EndTs: testTime,
Path: "/loki/api/v1/series",
}
@ -244,6 +244,54 @@ func TestSeriesTripperware(t *testing.T) {
require.Equal(t, series.Series, res.Data)
require.NoError(t, err)
}
func TestLabelsTripperware(t *testing.T) {
tpw, stopper, err := NewTripperware(testConfig, util.Logger, fakeLimits{}, chunk.SchemaConfig{}, 0, nil)
if stopper != nil {
defer stopper.Stop()
}
require.NoError(t, err)
rt, err := newfakeRoundTripper()
require.NoError(t, err)
defer rt.Close()
lreq := &LokiLabelNamesRequest{
StartTs: testTime.Add(-25 * time.Hour), // bigger than the limit
EndTs: testTime,
Path: "/loki/api/v1/labels",
}
ctx := user.InjectOrgID(context.Background(), "1")
req, err := lokiCodec.EncodeRequest(ctx, lreq)
require.NoError(t, err)
req = req.WithContext(ctx)
err = user.InjectOrgIDIntoHTTPRequest(ctx, req)
require.NoError(t, err)
handler := newFakeHandler(
// we expect 2 calls.
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
require.NoError(t, marshal.WriteLabelResponseJSON(logproto.LabelResponse{Values: []string{"foo", "bar", "blop"}}, w))
}),
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
require.NoError(t, marshal.WriteLabelResponseJSON(logproto.LabelResponse{Values: []string{"foo", "bar", "blip"}}, w))
}),
)
rt.setHandler(handler)
resp, err := tpw(rt).RoundTrip(req)
// verify 2 calls have been made to downstream.
require.Equal(t, 2, handler.count)
require.NoError(t, err)
lokiLabelsResponse, err := lokiCodec.DecodeResponse(ctx, resp, lreq)
res, ok := lokiLabelsResponse.(*LokiLabelNamesResponse)
require.Equal(t, true, ok)
require.Equal(t, []string{"foo", "bar", "blop", "blip"}, res.Data)
require.Equal(t, "success", res.Status)
require.NoError(t, err)
}
func TestLogNoRegex(t *testing.T) {
tpw, stopper, err := NewTripperware(testConfig, util.Logger, fakeLimits{}, chunk.SchemaConfig{}, 0, nil)
if stopper != nil {
@ -289,7 +337,7 @@ func TestUnhandledPath(t *testing.T) {
defer rt.Close()
ctx := user.InjectOrgID(context.Background(), "1")
req, err := http.NewRequest(http.MethodGet, "/loki/api/v1/labels", nil)
req, err := http.NewRequest(http.MethodGet, "/loki/api/v1/labels/foo/values", nil)
require.NoError(t, err)
req = req.WithContext(ctx)
err = user.InjectOrgIDIntoHTTPRequest(ctx, req)
@ -372,6 +420,10 @@ func TestPostQueries(t *testing.T) {
t.Error("unexpected series roundtripper called")
return nil, nil
}),
frontend.RoundTripFunc(func(*http.Request) (*http.Response, error) {
t.Error("unexpected labels roundtripper called")
return nil, nil
}),
fakeLimits{},
).RoundTrip(req)
require.NoError(t, err)
@ -518,6 +570,23 @@ func seriesResult(v logproto.SeriesResponse) (*int, http.Handler) {
})
}
type fakeHandler struct {
count int
lock sync.Mutex
calls []http.Handler
}
func newFakeHandler(calls ...http.Handler) *fakeHandler {
return &fakeHandler{calls: calls}
}
func (f *fakeHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
f.lock.Lock()
defer f.lock.Unlock()
f.calls[f.count].ServeHTTP(w, req)
f.count++
}
type fakeRoundTripper struct {
*httptest.Server
host string

@ -153,7 +153,6 @@ func (h *splitByInterval) loop(ctx context.Context, ch <-chan *lokiResult) {
}
func (h *splitByInterval) Do(ctx context.Context, r queryrange.Request) (queryrange.Response, error) {
//lokiRequest := r.(*LokiRequest)
userid, err := user.ExtractOrgID(ctx)
if err != nil {
@ -188,8 +187,8 @@ func (h *splitByInterval) Do(ctx context.Context, r queryrange.Request) (queryra
intervals[i], intervals[j] = intervals[j], intervals[i]
}
}
case *LokiSeriesRequest:
// Set this to 0 since this is not used in Series Request.
case *LokiSeriesRequest, *LokiLabelNamesRequest:
// Set this to 0 since this is not used in Series/Labels Request.
limit = 0
default:
return nil, httpgrpc.Errorf(http.StatusBadRequest, "unknown request type")
@ -215,11 +214,7 @@ func splitByTime(req queryrange.Request, interval time.Duration) []queryrange.Re
switch r := req.(type) {
case *LokiRequest:
for start := r.StartTs; start.Before(r.EndTs); start = start.Add(interval) {
end := start.Add(interval)
if end.After(r.EndTs) {
end = r.EndTs
}
forInterval(interval, r.StartTs, r.EndTs, func(start, end time.Time) {
reqs = append(reqs, &LokiRequest{
Query: r.Query,
Limit: r.Limit,
@ -229,23 +224,37 @@ func splitByTime(req queryrange.Request, interval time.Duration) []queryrange.Re
StartTs: start,
EndTs: end,
})
}
return reqs
})
case *LokiSeriesRequest:
for start := r.StartTs; start.Before(r.EndTs); start = start.Add(interval) {
end := start.Add(interval)
if end.After(r.EndTs) {
end = r.EndTs
}
forInterval(interval, r.StartTs, r.EndTs, func(start, end time.Time) {
reqs = append(reqs, &LokiSeriesRequest{
Match: r.Match,
Path: r.Path,
StartTs: start,
EndTs: end,
})
}
return reqs
})
case *LokiLabelNamesRequest:
forInterval(interval, r.StartTs, r.EndTs, func(start, end time.Time) {
reqs = append(reqs, &LokiLabelNamesRequest{
Path: r.Path,
StartTs: start,
EndTs: end,
})
})
default:
return nil
}
return reqs
}
func forInterval(interval time.Duration, start, end time.Time, callback func(start, end time.Time)) {
for start := start; start.Before(end); start = start.Add(interval) {
newEnd := start.Add(interval)
if newEnd.After(end) {
newEnd = end
}
callback(start, newEnd)
}
}

Loading…
Cancel
Save