diff --git a/pkg/querier/queryrange/codec.go b/pkg/querier/queryrange/codec.go index 538611ec0d3f..12ee32e84776 100644 --- a/pkg/querier/queryrange/codec.go +++ b/pkg/querier/queryrange/codec.go @@ -728,10 +728,12 @@ func mergeOrderedNonOverlappingStreams(resps []*LokiResponse, limit uint32, dire } func toProtoMatrix(m loghttp.Matrix) []queryrange.SampleStream { + res := make([]queryrange.SampleStream, 0, len(m)) + if len(m) == 0 { - return nil + return res } - res := make([]queryrange.SampleStream, 0, len(m)) + for _, stream := range m { samples := make([]cortexpb.Sample, 0, len(stream.Values)) for _, s := range stream.Values { @@ -749,10 +751,11 @@ func toProtoMatrix(m loghttp.Matrix) []queryrange.SampleStream { } func toProtoVector(v loghttp.Vector) []queryrange.SampleStream { + res := make([]queryrange.SampleStream, 0, len(v)) + if len(v) == 0 { - return nil + return res } - res := make([]queryrange.SampleStream, 0, len(v)) for _, s := range v { res = append(res, queryrange.SampleStream{ Samples: []cortexpb.Sample{{ diff --git a/pkg/querier/queryrange/codec_test.go b/pkg/querier/queryrange/codec_test.go index a4e80b28e2ea..9e229679bcbc 100644 --- a/pkg/querier/queryrange/codec_test.go +++ b/pkg/querier/queryrange/codec_test.go @@ -122,6 +122,36 @@ func Test_codec_DecodeResponse(t *testing.T) { Statistics: statsResult, }, false, }, + { + "matrix-empty-streams", + &http.Response{StatusCode: 200, Body: ioutil.NopCloser(strings.NewReader(matrixStringEmptyResult))}, + nil, + &LokiPromResponse{ + Response: &queryrange.PrometheusResponse{ + Status: loghttp.QueryStatusSuccess, + Data: queryrange.PrometheusData{ + ResultType: loghttp.ResultTypeMatrix, + Result: make([]queryrange.SampleStream, 0), // shouldn't be nil. + }, + }, + Statistics: statsResult, + }, false, + }, + { + "vector-empty-streams", + &http.Response{StatusCode: 200, Body: ioutil.NopCloser(strings.NewReader(vectorStringEmptyResult))}, + nil, + &LokiPromResponse{ + Response: &queryrange.PrometheusResponse{ + Status: loghttp.QueryStatusSuccess, + Data: queryrange.PrometheusData{ + ResultType: loghttp.ResultTypeVector, + Result: make([]queryrange.SampleStream, 0), // shouldn't be nil. + }, + }, + Statistics: statsResult, + }, false, + }, { "streams v1", &http.Response{StatusCode: 200, Body: ioutil.NopCloser(strings.NewReader(streamsString))}, &LokiRequest{Direction: logproto.FORWARD, Limit: 100, Path: "/loki/api/v1/query_range"}, @@ -905,6 +935,23 @@ var ( }, "status": "success" }` + matrixStringEmptyResult = `{ + "data": { + ` + statsResultString + ` + "resultType": "matrix", + "result": [] + }, + "status": "success" + }` + vectorStringEmptyResult = `{ + "data": { + ` + statsResultString + ` + "resultType": "vector", + "result": [] + }, + "status": "success" + }` + sampleStreams = []queryrange.SampleStream{ { Labels: []cortexpb.LabelAdapter{{Name: "filename", Value: "/var/hostlog/apport.log"}, {Name: "job", Value: "varlogs"}},