github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/querier/queryrange/codec.go (about)

     1  package queryrange
     2  
     3  import (
     4  	"bytes"
     5  	"container/heap"
     6  	"context"
     7  	"errors"
     8  	"fmt"
     9  	"io/ioutil"
    10  	"net/http"
    11  	"net/url"
    12  	"sort"
    13  	strings "strings"
    14  	"time"
    15  
    16  	json "github.com/json-iterator/go"
    17  	"github.com/opentracing/opentracing-go"
    18  	otlog "github.com/opentracing/opentracing-go/log"
    19  	"github.com/prometheus/prometheus/model/timestamp"
    20  	"github.com/weaveworks/common/httpgrpc"
    21  
    22  	"github.com/grafana/loki/pkg/loghttp"
    23  	"github.com/grafana/loki/pkg/logproto"
    24  	"github.com/grafana/loki/pkg/logql"
    25  	"github.com/grafana/loki/pkg/logql/syntax"
    26  	"github.com/grafana/loki/pkg/logqlmodel"
    27  	"github.com/grafana/loki/pkg/logqlmodel/stats"
    28  	"github.com/grafana/loki/pkg/querier/queryrange/queryrangebase"
    29  	"github.com/grafana/loki/pkg/util"
    30  	"github.com/grafana/loki/pkg/util/httpreq"
    31  	"github.com/grafana/loki/pkg/util/marshal"
    32  	marshal_legacy "github.com/grafana/loki/pkg/util/marshal/legacy"
    33  )
    34  
    35  var LokiCodec = &Codec{}
    36  
    37  type Codec struct{}
    38  
    39  func (r *LokiRequest) GetEnd() int64 {
    40  	return r.EndTs.UnixNano() / (int64(time.Millisecond) / int64(time.Nanosecond))
    41  }
    42  
    43  func (r *LokiRequest) GetStart() int64 {
    44  	return r.StartTs.UnixNano() / (int64(time.Millisecond) / int64(time.Nanosecond))
    45  }
    46  
    47  func (r *LokiRequest) WithStartEnd(s int64, e int64) queryrangebase.Request {
    48  	new := *r
    49  	new.StartTs = time.Unix(0, s*int64(time.Millisecond))
    50  	new.EndTs = time.Unix(0, e*int64(time.Millisecond))
    51  	return &new
    52  }
    53  
    54  func (r *LokiRequest) WithStartEndTime(s time.Time, e time.Time) *LokiRequest {
    55  	new := *r
    56  	new.StartTs = s
    57  	new.EndTs = e
    58  	return &new
    59  }
    60  
    61  func (r *LokiRequest) WithQuery(query string) queryrangebase.Request {
    62  	new := *r
    63  	new.Query = query
    64  	return &new
    65  }
    66  
    67  func (r *LokiRequest) WithShards(shards logql.Shards) *LokiRequest {
    68  	new := *r
    69  	new.Shards = shards.Encode()
    70  	return &new
    71  }
    72  
    73  func (r *LokiRequest) LogToSpan(sp opentracing.Span) {
    74  	sp.LogFields(
    75  		otlog.String("query", r.GetQuery()),
    76  		otlog.String("start", timestamp.Time(r.GetStart()).String()),
    77  		otlog.String("end", timestamp.Time(r.GetEnd()).String()),
    78  		otlog.Int64("step (ms)", r.GetStep()),
    79  		otlog.Int64("interval (ms)", r.GetInterval()),
    80  		otlog.Int64("limit", int64(r.GetLimit())),
    81  		otlog.String("direction", r.GetDirection().String()),
    82  		otlog.String("shards", strings.Join(r.GetShards(), ",")),
    83  	)
    84  }
    85  
    86  func (*LokiRequest) GetCachingOptions() (res queryrangebase.CachingOptions) { return }
    87  
    88  func (r *LokiInstantRequest) GetStep() int64 {
    89  	return 0
    90  }
    91  
    92  func (r *LokiInstantRequest) GetEnd() int64 {
    93  	return r.TimeTs.UnixNano() / (int64(time.Millisecond) / int64(time.Nanosecond))
    94  }
    95  
    96  func (r *LokiInstantRequest) GetStart() int64 {
    97  	return r.TimeTs.UnixNano() / (int64(time.Millisecond) / int64(time.Nanosecond))
    98  }
    99  
   100  func (r *LokiInstantRequest) WithStartEnd(s int64, e int64) queryrangebase.Request {
   101  	new := *r
   102  	new.TimeTs = time.Unix(0, s*int64(time.Millisecond))
   103  	return &new
   104  }
   105  
   106  func (r *LokiInstantRequest) WithQuery(query string) queryrangebase.Request {
   107  	new := *r
   108  	new.Query = query
   109  	return &new
   110  }
   111  
   112  func (r *LokiInstantRequest) WithShards(shards logql.Shards) *LokiInstantRequest {
   113  	new := *r
   114  	new.Shards = shards.Encode()
   115  	return &new
   116  }
   117  
   118  func (r *LokiInstantRequest) LogToSpan(sp opentracing.Span) {
   119  	sp.LogFields(
   120  		otlog.String("query", r.GetQuery()),
   121  		otlog.String("ts", timestamp.Time(r.GetStart()).String()),
   122  		otlog.Int64("limit", int64(r.GetLimit())),
   123  		otlog.String("direction", r.GetDirection().String()),
   124  		otlog.String("shards", strings.Join(r.GetShards(), ",")),
   125  	)
   126  }
   127  
   128  func (*LokiInstantRequest) GetCachingOptions() (res queryrangebase.CachingOptions) { return }
   129  
   130  func (r *LokiSeriesRequest) GetEnd() int64 {
   131  	return r.EndTs.UnixNano() / (int64(time.Millisecond) / int64(time.Nanosecond))
   132  }
   133  
   134  func (r *LokiSeriesRequest) GetStart() int64 {
   135  	return r.StartTs.UnixNano() / (int64(time.Millisecond) / int64(time.Nanosecond))
   136  }
   137  
   138  func (r *LokiSeriesRequest) WithStartEnd(s int64, e int64) queryrangebase.Request {
   139  	new := *r
   140  	new.StartTs = time.Unix(0, s*int64(time.Millisecond))
   141  	new.EndTs = time.Unix(0, e*int64(time.Millisecond))
   142  	return &new
   143  }
   144  
   145  func (r *LokiSeriesRequest) WithQuery(query string) queryrangebase.Request {
   146  	new := *r
   147  	return &new
   148  }
   149  
   150  func (r *LokiSeriesRequest) GetQuery() string {
   151  	return ""
   152  }
   153  
   154  func (r *LokiSeriesRequest) GetStep() int64 {
   155  	return 0
   156  }
   157  
   158  func (r *LokiSeriesRequest) LogToSpan(sp opentracing.Span) {
   159  	sp.LogFields(
   160  		otlog.String("matchers", strings.Join(r.GetMatch(), ",")),
   161  		otlog.String("start", timestamp.Time(r.GetStart()).String()),
   162  		otlog.String("end", timestamp.Time(r.GetEnd()).String()),
   163  		otlog.String("shards", strings.Join(r.GetShards(), ",")),
   164  	)
   165  }
   166  
   167  func (*LokiSeriesRequest) GetCachingOptions() (res queryrangebase.CachingOptions) { return }
   168  
   169  func (r *LokiLabelNamesRequest) GetEnd() int64 {
   170  	return r.EndTs.UnixNano() / (int64(time.Millisecond) / int64(time.Nanosecond))
   171  }
   172  
   173  func (r *LokiLabelNamesRequest) GetStart() int64 {
   174  	return r.StartTs.UnixNano() / (int64(time.Millisecond) / int64(time.Nanosecond))
   175  }
   176  
   177  func (r *LokiLabelNamesRequest) WithStartEnd(s int64, e int64) queryrangebase.Request {
   178  	new := *r
   179  	new.StartTs = time.Unix(0, s*int64(time.Millisecond))
   180  	new.EndTs = time.Unix(0, e*int64(time.Millisecond))
   181  	return &new
   182  }
   183  
   184  func (r *LokiLabelNamesRequest) WithQuery(query string) queryrangebase.Request {
   185  	new := *r
   186  	return &new
   187  }
   188  
   189  func (r *LokiLabelNamesRequest) GetQuery() string {
   190  	return ""
   191  }
   192  
   193  func (r *LokiLabelNamesRequest) GetStep() int64 {
   194  	return 0
   195  }
   196  
   197  func (r *LokiLabelNamesRequest) LogToSpan(sp opentracing.Span) {
   198  	sp.LogFields(
   199  		otlog.String("start", timestamp.Time(r.GetStart()).String()),
   200  		otlog.String("end", timestamp.Time(r.GetEnd()).String()),
   201  	)
   202  }
   203  
   204  func (*LokiLabelNamesRequest) GetCachingOptions() (res queryrangebase.CachingOptions) { return }
   205  
   206  func (Codec) DecodeRequest(_ context.Context, r *http.Request, forwardHeaders []string) (queryrangebase.Request, error) {
   207  	if err := r.ParseForm(); err != nil {
   208  		return nil, httpgrpc.Errorf(http.StatusBadRequest, err.Error())
   209  	}
   210  
   211  	switch op := getOperation(r.URL.Path); op {
   212  	case QueryRangeOp:
   213  		req, err := loghttp.ParseRangeQuery(r)
   214  		if err != nil {
   215  			return nil, httpgrpc.Errorf(http.StatusBadRequest, err.Error())
   216  		}
   217  		return &LokiRequest{
   218  			Query:     req.Query,
   219  			Limit:     req.Limit,
   220  			Direction: req.Direction,
   221  			StartTs:   req.Start.UTC(),
   222  			EndTs:     req.End.UTC(),
   223  			Step:      req.Step.Milliseconds(),
   224  			Interval:  req.Interval.Milliseconds(),
   225  			Path:      r.URL.Path,
   226  			Shards:    req.Shards,
   227  		}, nil
   228  	case InstantQueryOp:
   229  		req, err := loghttp.ParseInstantQuery(r)
   230  		if err != nil {
   231  			return nil, httpgrpc.Errorf(http.StatusBadRequest, err.Error())
   232  		}
   233  		return &LokiInstantRequest{
   234  			Query:     req.Query,
   235  			Limit:     req.Limit,
   236  			Direction: req.Direction,
   237  			TimeTs:    req.Ts.UTC(),
   238  			Path:      r.URL.Path,
   239  			Shards:    req.Shards,
   240  		}, nil
   241  	case SeriesOp:
   242  		req, err := loghttp.ParseAndValidateSeriesQuery(r)
   243  		if err != nil {
   244  			return nil, httpgrpc.Errorf(http.StatusBadRequest, err.Error())
   245  		}
   246  		return &LokiSeriesRequest{
   247  			Match:   req.Groups,
   248  			StartTs: req.Start.UTC(),
   249  			EndTs:   req.End.UTC(),
   250  			Path:    r.URL.Path,
   251  			Shards:  req.Shards,
   252  		}, nil
   253  	case LabelNamesOp:
   254  		req, err := loghttp.ParseLabelQuery(r)
   255  		if err != nil {
   256  			return nil, httpgrpc.Errorf(http.StatusBadRequest, err.Error())
   257  		}
   258  		return &LokiLabelNamesRequest{
   259  			StartTs: *req.Start,
   260  			EndTs:   *req.End,
   261  			Path:    r.URL.Path,
   262  		}, nil
   263  	case IndexStatsOp:
   264  		req, err := loghttp.ParseIndexStatsQuery(r)
   265  		if err != nil {
   266  			return nil, httpgrpc.Errorf(http.StatusBadRequest, err.Error())
   267  		}
   268  		from, through := util.RoundToMilliseconds(req.Start, req.End)
   269  		return &logproto.IndexStatsRequest{
   270  			From:     from,
   271  			Through:  through,
   272  			Matchers: req.Query,
   273  		}, err
   274  	default:
   275  		return nil, httpgrpc.Errorf(http.StatusBadRequest, fmt.Sprintf("unknown request path: %s", r.URL.Path))
   276  	}
   277  }
   278  
   279  func (Codec) EncodeRequest(ctx context.Context, r queryrangebase.Request) (*http.Request, error) {
   280  	header := make(http.Header)
   281  	queryTags := getQueryTags(ctx)
   282  	if queryTags != "" {
   283  		header.Set(string(httpreq.QueryTagsHTTPHeader), queryTags)
   284  	}
   285  
   286  	switch request := r.(type) {
   287  	case *LokiRequest:
   288  		params := url.Values{
   289  			"start":     []string{fmt.Sprintf("%d", request.StartTs.UnixNano())},
   290  			"end":       []string{fmt.Sprintf("%d", request.EndTs.UnixNano())},
   291  			"query":     []string{request.Query},
   292  			"direction": []string{request.Direction.String()},
   293  			"limit":     []string{fmt.Sprintf("%d", request.Limit)},
   294  		}
   295  		if len(request.Shards) > 0 {
   296  			params["shards"] = request.Shards
   297  		}
   298  		if request.Step != 0 {
   299  			params["step"] = []string{fmt.Sprintf("%f", float64(request.Step)/float64(1e3))}
   300  		}
   301  		if request.Interval != 0 {
   302  			params["interval"] = []string{fmt.Sprintf("%f", float64(request.Interval)/float64(1e3))}
   303  		}
   304  		u := &url.URL{
   305  			// the request could come /api/prom/query but we want to only use the new api.
   306  			Path:     "/loki/api/v1/query_range",
   307  			RawQuery: params.Encode(),
   308  		}
   309  		req := &http.Request{
   310  			Method:     "GET",
   311  			RequestURI: u.String(), // This is what the httpgrpc code looks at.
   312  			URL:        u,
   313  			Body:       http.NoBody,
   314  			Header:     header,
   315  		}
   316  
   317  		return req.WithContext(ctx), nil
   318  	case *LokiSeriesRequest:
   319  		params := url.Values{
   320  			"start":   []string{fmt.Sprintf("%d", request.StartTs.UnixNano())},
   321  			"end":     []string{fmt.Sprintf("%d", request.EndTs.UnixNano())},
   322  			"match[]": request.Match,
   323  		}
   324  		if len(request.Shards) > 0 {
   325  			params["shards"] = request.Shards
   326  		}
   327  		u := &url.URL{
   328  			Path:     "/loki/api/v1/series",
   329  			RawQuery: params.Encode(),
   330  		}
   331  		req := &http.Request{
   332  			Method:     "GET",
   333  			RequestURI: u.String(), // This is what the httpgrpc code looks at.
   334  			URL:        u,
   335  			Body:       http.NoBody,
   336  			Header:     header,
   337  		}
   338  		return req.WithContext(ctx), nil
   339  	case *LokiLabelNamesRequest:
   340  		params := url.Values{
   341  			"start": []string{fmt.Sprintf("%d", request.StartTs.UnixNano())},
   342  			"end":   []string{fmt.Sprintf("%d", request.EndTs.UnixNano())},
   343  		}
   344  
   345  		u := &url.URL{
   346  			Path:     request.Path, // NOTE: this could be either /label or /label/{name}/values endpoint. So forward the original path as it is.
   347  			RawQuery: params.Encode(),
   348  		}
   349  		req := &http.Request{
   350  			Method:     "GET",
   351  			RequestURI: u.String(), // This is what the httpgrpc code looks at.
   352  			URL:        u,
   353  			Body:       http.NoBody,
   354  			Header:     header,
   355  		}
   356  		return req.WithContext(ctx), nil
   357  	case *LokiInstantRequest:
   358  		params := url.Values{
   359  			"query":     []string{request.Query},
   360  			"direction": []string{request.Direction.String()},
   361  			"limit":     []string{fmt.Sprintf("%d", request.Limit)},
   362  			"time":      []string{fmt.Sprintf("%d", request.TimeTs.UnixNano())},
   363  		}
   364  		if len(request.Shards) > 0 {
   365  			params["shards"] = request.Shards
   366  		}
   367  		u := &url.URL{
   368  			// the request could come /api/prom/query but we want to only use the new api.
   369  			Path:     "/loki/api/v1/query",
   370  			RawQuery: params.Encode(),
   371  		}
   372  		req := &http.Request{
   373  			Method:     "GET",
   374  			RequestURI: u.String(), // This is what the httpgrpc code looks at.
   375  			URL:        u,
   376  			Body:       http.NoBody,
   377  			Header:     header,
   378  		}
   379  
   380  		return req.WithContext(ctx), nil
   381  	case *logproto.IndexStatsRequest:
   382  		params := url.Values{
   383  			"start": []string{fmt.Sprintf("%d", request.From.Time().UnixNano())},
   384  			"end":   []string{fmt.Sprintf("%d", request.Through.Time().UnixNano())},
   385  			"query": []string{request.GetQuery()},
   386  		}
   387  		u := &url.URL{
   388  			Path:     "/loki/api/v1/index/stats",
   389  			RawQuery: params.Encode(),
   390  		}
   391  		req := &http.Request{
   392  			Method:     "GET",
   393  			RequestURI: u.String(), // This is what the httpgrpc code looks at.
   394  			URL:        u,
   395  			Body:       http.NoBody,
   396  			Header:     header,
   397  		}
   398  		return req.WithContext(ctx), nil
   399  	default:
   400  		return nil, httpgrpc.Errorf(http.StatusInternalServerError, "invalid request format")
   401  	}
   402  }
   403  
   404  type Buffer interface {
   405  	Bytes() []byte
   406  }
   407  
   408  func (Codec) DecodeResponse(ctx context.Context, r *http.Response, req queryrangebase.Request) (queryrangebase.Response, error) {
   409  	if r.StatusCode/100 != 2 {
   410  		body, _ := ioutil.ReadAll(r.Body)
   411  		return nil, httpgrpc.Errorf(r.StatusCode, string(body))
   412  	}
   413  
   414  	var buf []byte
   415  	var err error
   416  	if buffer, ok := r.Body.(Buffer); ok {
   417  		buf = buffer.Bytes()
   418  	} else {
   419  		buf, err = ioutil.ReadAll(r.Body)
   420  		if err != nil {
   421  			return nil, httpgrpc.Errorf(http.StatusInternalServerError, "error decoding response: %v", err)
   422  		}
   423  	}
   424  
   425  	switch req := req.(type) {
   426  	case *LokiSeriesRequest:
   427  		var resp loghttp.SeriesResponse
   428  		if err := json.Unmarshal(buf, &resp); err != nil {
   429  			return nil, httpgrpc.Errorf(http.StatusInternalServerError, "error decoding response: %v", err)
   430  		}
   431  
   432  		data := make([]logproto.SeriesIdentifier, 0, len(resp.Data))
   433  		for _, label := range resp.Data {
   434  			d := logproto.SeriesIdentifier{
   435  				Labels: label.Map(),
   436  			}
   437  			data = append(data, d)
   438  		}
   439  
   440  		return &LokiSeriesResponse{
   441  			Status:  resp.Status,
   442  			Version: uint32(loghttp.GetVersion(req.Path)),
   443  			Data:    data,
   444  			Headers: httpResponseHeadersToPromResponseHeaders(r.Header),
   445  		}, nil
   446  	case *LokiLabelNamesRequest:
   447  		var resp loghttp.LabelResponse
   448  		if err := json.Unmarshal(buf, &resp); err != nil {
   449  			return nil, httpgrpc.Errorf(http.StatusInternalServerError, "error decoding response: %v", err)
   450  		}
   451  		return &LokiLabelNamesResponse{
   452  			Status:  resp.Status,
   453  			Version: uint32(loghttp.GetVersion(req.Path)),
   454  			Data:    resp.Data,
   455  			Headers: httpResponseHeadersToPromResponseHeaders(r.Header),
   456  		}, nil
   457  	case *logproto.IndexStatsRequest:
   458  		var resp logproto.IndexStatsResponse
   459  		if err := json.Unmarshal(buf, &resp); err != nil {
   460  			return nil, httpgrpc.Errorf(http.StatusInternalServerError, "error decoding response: %v", err)
   461  		}
   462  		return &IndexStatsResponse{
   463  			Response: &resp,
   464  			Headers:  httpResponseHeadersToPromResponseHeaders(r.Header),
   465  		}, nil
   466  	default:
   467  		var resp loghttp.QueryResponse
   468  		if err := resp.UnmarshalJSON(buf); err != nil {
   469  			return nil, httpgrpc.Errorf(http.StatusInternalServerError, "error decoding response: %v", err)
   470  		}
   471  		switch string(resp.Data.ResultType) {
   472  		case loghttp.ResultTypeMatrix:
   473  			return &LokiPromResponse{
   474  				Response: &queryrangebase.PrometheusResponse{
   475  					Status: resp.Status,
   476  					Data: queryrangebase.PrometheusData{
   477  						ResultType: loghttp.ResultTypeMatrix,
   478  						Result:     toProtoMatrix(resp.Data.Result.(loghttp.Matrix)),
   479  					},
   480  					Headers: convertPrometheusResponseHeadersToPointers(httpResponseHeadersToPromResponseHeaders(r.Header)),
   481  				},
   482  				Statistics: resp.Data.Statistics,
   483  			}, nil
   484  		case loghttp.ResultTypeStream:
   485  			// This is the same as in querysharding.go
   486  			params, err := paramsFromRequest(req)
   487  			if err != nil {
   488  				return nil, err
   489  			}
   490  
   491  			var path string
   492  			switch r := req.(type) {
   493  			case *LokiRequest:
   494  				path = r.GetPath()
   495  			case *LokiInstantRequest:
   496  				path = r.GetPath()
   497  			default:
   498  				return nil, fmt.Errorf("expected *LokiRequest or *LokiInstantRequest, got (%T)", r)
   499  			}
   500  			return &LokiResponse{
   501  				Status:     resp.Status,
   502  				Direction:  params.Direction(),
   503  				Limit:      params.Limit(),
   504  				Version:    uint32(loghttp.GetVersion(path)),
   505  				Statistics: resp.Data.Statistics,
   506  				Data: LokiData{
   507  					ResultType: loghttp.ResultTypeStream,
   508  					Result:     resp.Data.Result.(loghttp.Streams).ToProto(),
   509  				},
   510  				Headers: httpResponseHeadersToPromResponseHeaders(r.Header),
   511  			}, nil
   512  		case loghttp.ResultTypeVector:
   513  			return &LokiPromResponse{
   514  				Response: &queryrangebase.PrometheusResponse{
   515  					Status: resp.Status,
   516  					Data: queryrangebase.PrometheusData{
   517  						ResultType: loghttp.ResultTypeVector,
   518  						Result:     toProtoVector(resp.Data.Result.(loghttp.Vector)),
   519  					},
   520  					Headers: convertPrometheusResponseHeadersToPointers(httpResponseHeadersToPromResponseHeaders(r.Header)),
   521  				},
   522  				Statistics: resp.Data.Statistics,
   523  			}, nil
   524  		default:
   525  			return nil, httpgrpc.Errorf(http.StatusInternalServerError, "unsupported response type, got (%s)", string(resp.Data.ResultType))
   526  		}
   527  	}
   528  }
   529  
   530  func (Codec) EncodeResponse(ctx context.Context, res queryrangebase.Response) (*http.Response, error) {
   531  	sp, _ := opentracing.StartSpanFromContext(ctx, "codec.EncodeResponse")
   532  	defer sp.Finish()
   533  	var buf bytes.Buffer
   534  
   535  	switch response := res.(type) {
   536  	case *LokiPromResponse:
   537  		return response.encode(ctx)
   538  	case *LokiResponse:
   539  		streams := make([]logproto.Stream, len(response.Data.Result))
   540  
   541  		for i, stream := range response.Data.Result {
   542  			streams[i] = logproto.Stream{
   543  				Labels:  stream.Labels,
   544  				Entries: stream.Entries,
   545  			}
   546  		}
   547  		result := logqlmodel.Result{
   548  			Data:       logqlmodel.Streams(streams),
   549  			Statistics: response.Statistics,
   550  		}
   551  		if loghttp.Version(response.Version) == loghttp.VersionLegacy {
   552  			if err := marshal_legacy.WriteQueryResponseJSON(result, &buf); err != nil {
   553  				return nil, err
   554  			}
   555  		} else {
   556  			if err := marshal.WriteQueryResponseJSON(result, &buf); err != nil {
   557  				return nil, err
   558  			}
   559  		}
   560  
   561  	case *LokiSeriesResponse:
   562  		result := logproto.SeriesResponse{
   563  			Series: response.Data,
   564  		}
   565  		if err := marshal.WriteSeriesResponseJSON(result, &buf); err != nil {
   566  			return nil, err
   567  		}
   568  	case *LokiLabelNamesResponse:
   569  		if loghttp.Version(response.Version) == loghttp.VersionLegacy {
   570  			if err := marshal_legacy.WriteLabelResponseJSON(logproto.LabelResponse{Values: response.Data}, &buf); err != nil {
   571  				return nil, err
   572  			}
   573  		} else {
   574  			if err := marshal.WriteLabelResponseJSON(logproto.LabelResponse{Values: response.Data}, &buf); err != nil {
   575  				return nil, err
   576  			}
   577  		}
   578  	case *IndexStatsResponse:
   579  		if err := marshal.WriteIndexStatsResponseJSON(response.Response, &buf); err != nil {
   580  			return nil, err
   581  		}
   582  
   583  	default:
   584  		return nil, httpgrpc.Errorf(http.StatusInternalServerError, "invalid response format")
   585  	}
   586  
   587  	sp.LogFields(otlog.Int("bytes", buf.Len()))
   588  
   589  	resp := http.Response{
   590  		Header: http.Header{
   591  			"Content-Type": []string{"application/json"},
   592  		},
   593  		Body:       ioutil.NopCloser(&buf),
   594  		StatusCode: http.StatusOK,
   595  	}
   596  	return &resp, nil
   597  }
   598  
   599  // NOTE: When we would start caching response from non-metric queries we would have to consider cache gen headers as well in
   600  // MergeResponse implementation for Loki codecs same as it is done in Cortex at https://github.com/cortexproject/cortex/blob/21bad57b346c730d684d6d0205efef133422ab28/pkg/querier/queryrange/query_range.go#L170
   601  func (Codec) MergeResponse(responses ...queryrangebase.Response) (queryrangebase.Response, error) {
   602  	if len(responses) == 0 {
   603  		return nil, errors.New("merging responses requires at least one response")
   604  	}
   605  	var mergedStats stats.Result
   606  	switch responses[0].(type) {
   607  	case *LokiPromResponse:
   608  
   609  		promResponses := make([]queryrangebase.Response, 0, len(responses))
   610  		for _, res := range responses {
   611  			mergedStats.Merge(res.(*LokiPromResponse).Statistics)
   612  			promResponses = append(promResponses, res.(*LokiPromResponse).Response)
   613  		}
   614  		promRes, err := queryrangebase.PrometheusCodec.MergeResponse(promResponses...)
   615  		if err != nil {
   616  			return nil, err
   617  		}
   618  		return &LokiPromResponse{
   619  			Response:   promRes.(*queryrangebase.PrometheusResponse),
   620  			Statistics: mergedStats,
   621  		}, nil
   622  	case *LokiResponse:
   623  		return mergeLokiResponse(responses...), nil
   624  	case *LokiSeriesResponse:
   625  		lokiSeriesRes := responses[0].(*LokiSeriesResponse)
   626  
   627  		var lokiSeriesData []logproto.SeriesIdentifier
   628  		uniqueSeries := make(map[string]struct{})
   629  
   630  		// only unique series should be merged
   631  		for _, res := range responses {
   632  			lokiResult := res.(*LokiSeriesResponse)
   633  			for _, series := range lokiResult.Data {
   634  				if _, ok := uniqueSeries[series.String()]; !ok {
   635  					lokiSeriesData = append(lokiSeriesData, series)
   636  					uniqueSeries[series.String()] = struct{}{}
   637  				}
   638  			}
   639  		}
   640  
   641  		return &LokiSeriesResponse{
   642  			Status:  lokiSeriesRes.Status,
   643  			Version: lokiSeriesRes.Version,
   644  			Data:    lokiSeriesData,
   645  		}, nil
   646  	case *LokiLabelNamesResponse:
   647  		labelNameRes := responses[0].(*LokiLabelNamesResponse)
   648  		uniqueNames := make(map[string]struct{})
   649  		names := []string{}
   650  
   651  		// only unique name should be merged
   652  		for _, res := range responses {
   653  			lokiResult := res.(*LokiLabelNamesResponse)
   654  			for _, labelName := range lokiResult.Data {
   655  				if _, ok := uniqueNames[labelName]; !ok {
   656  					names = append(names, labelName)
   657  					uniqueNames[labelName] = struct{}{}
   658  				}
   659  			}
   660  		}
   661  
   662  		return &LokiLabelNamesResponse{
   663  			Status:  labelNameRes.Status,
   664  			Version: labelNameRes.Version,
   665  			Data:    names,
   666  		}, nil
   667  	default:
   668  		return nil, errors.New("unknown response in merging responses")
   669  	}
   670  }
   671  
   672  // mergeOrderedNonOverlappingStreams merges a set of ordered, nonoverlapping responses by concatenating matching streams then running them through a heap to pull out limit values
   673  func mergeOrderedNonOverlappingStreams(resps []*LokiResponse, limit uint32, direction logproto.Direction) []logproto.Stream {
   674  	var total int
   675  
   676  	// turn resps -> map[labels] []entries
   677  	groups := make(map[string]*byDir)
   678  	for _, resp := range resps {
   679  		for _, stream := range resp.Data.Result {
   680  			s, ok := groups[stream.Labels]
   681  			if !ok {
   682  				s = &byDir{
   683  					direction: direction,
   684  					labels:    stream.Labels,
   685  				}
   686  				groups[stream.Labels] = s
   687  			}
   688  
   689  			s.markers = append(s.markers, stream.Entries)
   690  			total += len(stream.Entries)
   691  		}
   692  
   693  		// optimization: since limit has been reached, no need to append entries from subsequent responses
   694  		if total >= int(limit) {
   695  			break
   696  		}
   697  	}
   698  
   699  	keys := make([]string, 0, len(groups))
   700  	for key := range groups {
   701  		keys = append(keys, key)
   702  	}
   703  	if direction == logproto.BACKWARD {
   704  		sort.Sort(sort.Reverse(sort.StringSlice(keys)))
   705  	} else {
   706  		sort.Strings(keys)
   707  	}
   708  
   709  	// escape hatch, can just return all the streams
   710  	if total <= int(limit) {
   711  		results := make([]logproto.Stream, 0, len(keys))
   712  		for _, key := range keys {
   713  			results = append(results, logproto.Stream{
   714  				Labels:  key,
   715  				Entries: groups[key].merge(),
   716  			})
   717  		}
   718  		return results
   719  	}
   720  
   721  	pq := &priorityqueue{
   722  		direction: direction,
   723  	}
   724  
   725  	for _, key := range keys {
   726  		stream := &logproto.Stream{
   727  			Labels:  key,
   728  			Entries: groups[key].merge(),
   729  		}
   730  		if len(stream.Entries) > 0 {
   731  			pq.streams = append(pq.streams, stream)
   732  		}
   733  	}
   734  
   735  	heap.Init(pq)
   736  
   737  	resultDict := make(map[string]*logproto.Stream)
   738  
   739  	// we want the min(limit, num_entries)
   740  	for i := 0; i < int(limit) && pq.Len() > 0; i++ {
   741  		// grab the next entry off the queue. This will be a stream (to preserve labels) with one entry.
   742  		next := heap.Pop(pq).(*logproto.Stream)
   743  
   744  		s, ok := resultDict[next.Labels]
   745  		if !ok {
   746  			s = &logproto.Stream{
   747  				Labels:  next.Labels,
   748  				Entries: make([]logproto.Entry, 0, int(limit)/len(keys)), // allocation hack -- assume uniform distribution across labels
   749  			}
   750  			resultDict[next.Labels] = s
   751  		}
   752  		// TODO: make allocation friendly
   753  		s.Entries = append(s.Entries, next.Entries...)
   754  	}
   755  
   756  	results := make([]logproto.Stream, 0, len(resultDict))
   757  	for _, key := range keys {
   758  		stream, ok := resultDict[key]
   759  		if ok {
   760  			results = append(results, *stream)
   761  		}
   762  	}
   763  
   764  	return results
   765  }
   766  
   767  func toProtoMatrix(m loghttp.Matrix) []queryrangebase.SampleStream {
   768  	res := make([]queryrangebase.SampleStream, 0, len(m))
   769  
   770  	if len(m) == 0 {
   771  		return res
   772  	}
   773  
   774  	for _, stream := range m {
   775  		samples := make([]logproto.LegacySample, 0, len(stream.Values))
   776  		for _, s := range stream.Values {
   777  			samples = append(samples, logproto.LegacySample{
   778  				Value:       float64(s.Value),
   779  				TimestampMs: int64(s.Timestamp),
   780  			})
   781  		}
   782  		res = append(res, queryrangebase.SampleStream{
   783  			Labels:  logproto.FromMetricsToLabelAdapters(stream.Metric),
   784  			Samples: samples,
   785  		})
   786  	}
   787  	return res
   788  }
   789  
   790  func toProtoVector(v loghttp.Vector) []queryrangebase.SampleStream {
   791  	res := make([]queryrangebase.SampleStream, 0, len(v))
   792  
   793  	if len(v) == 0 {
   794  		return res
   795  	}
   796  	for _, s := range v {
   797  		res = append(res, queryrangebase.SampleStream{
   798  			Samples: []logproto.LegacySample{{
   799  				Value:       float64(s.Value),
   800  				TimestampMs: int64(s.Timestamp),
   801  			}},
   802  			Labels: logproto.FromMetricsToLabelAdapters(s.Metric),
   803  		})
   804  	}
   805  	return res
   806  }
   807  
   808  func (res LokiResponse) Count() int64 {
   809  	var result int64
   810  	for _, s := range res.Data.Result {
   811  		result += int64(len(s.Entries))
   812  	}
   813  	return result
   814  }
   815  
   816  func paramsFromRequest(req queryrangebase.Request) (logql.Params, error) {
   817  	switch r := req.(type) {
   818  	case *LokiRequest:
   819  		return &paramsRangeWrapper{
   820  			LokiRequest: r,
   821  		}, nil
   822  	case *LokiInstantRequest:
   823  		return &paramsInstantWrapper{
   824  			LokiInstantRequest: r,
   825  		}, nil
   826  	case *LokiSeriesRequest:
   827  		return &paramsSeriesWrapper{
   828  			LokiSeriesRequest: r,
   829  		}, nil
   830  	case *LokiLabelNamesRequest:
   831  		return &paramsLabelNamesWrapper{
   832  			LokiLabelNamesRequest: r,
   833  		}, nil
   834  	default:
   835  		return nil, fmt.Errorf("expected one of the *LokiRequest, *LokiInstantRequest, *LokiSeriesRequest, *LokiLabelNamesRequest, got (%T)", r)
   836  	}
   837  }
   838  
   839  type paramsRangeWrapper struct {
   840  	*LokiRequest
   841  }
   842  
   843  func (p paramsRangeWrapper) Query() string {
   844  	return p.GetQuery()
   845  }
   846  
   847  func (p paramsRangeWrapper) Start() time.Time {
   848  	return p.GetStartTs()
   849  }
   850  
   851  func (p paramsRangeWrapper) End() time.Time {
   852  	return p.GetEndTs()
   853  }
   854  
   855  func (p paramsRangeWrapper) Step() time.Duration {
   856  	return time.Duration(p.GetStep() * 1e6)
   857  }
   858  func (p paramsRangeWrapper) Interval() time.Duration {
   859  	return time.Duration(p.GetInterval() * 1e6)
   860  }
   861  func (p paramsRangeWrapper) Direction() logproto.Direction {
   862  	return p.GetDirection()
   863  }
   864  func (p paramsRangeWrapper) Limit() uint32 { return p.LokiRequest.Limit }
   865  func (p paramsRangeWrapper) Shards() []string {
   866  	return p.GetShards()
   867  }
   868  
   869  type paramsInstantWrapper struct {
   870  	*LokiInstantRequest
   871  }
   872  
   873  func (p paramsInstantWrapper) Query() string {
   874  	return p.GetQuery()
   875  }
   876  
   877  func (p paramsInstantWrapper) Start() time.Time {
   878  	return p.LokiInstantRequest.GetTimeTs()
   879  }
   880  
   881  func (p paramsInstantWrapper) End() time.Time {
   882  	return p.LokiInstantRequest.GetTimeTs()
   883  }
   884  
   885  func (p paramsInstantWrapper) Step() time.Duration {
   886  	return time.Duration(p.GetStep() * 1e6)
   887  }
   888  func (p paramsInstantWrapper) Interval() time.Duration { return 0 }
   889  func (p paramsInstantWrapper) Direction() logproto.Direction {
   890  	return p.GetDirection()
   891  }
   892  func (p paramsInstantWrapper) Limit() uint32 { return p.LokiInstantRequest.Limit }
   893  func (p paramsInstantWrapper) Shards() []string {
   894  	return p.GetShards()
   895  }
   896  
   897  type paramsSeriesWrapper struct {
   898  	*LokiSeriesRequest
   899  }
   900  
   901  func (p paramsSeriesWrapper) Query() string {
   902  	return p.GetQuery()
   903  }
   904  
   905  func (p paramsSeriesWrapper) Start() time.Time {
   906  	return p.LokiSeriesRequest.GetStartTs()
   907  }
   908  
   909  func (p paramsSeriesWrapper) End() time.Time {
   910  	return p.LokiSeriesRequest.GetEndTs()
   911  }
   912  
   913  func (p paramsSeriesWrapper) Step() time.Duration {
   914  	return time.Duration(p.GetStep() * 1e6)
   915  }
   916  func (p paramsSeriesWrapper) Interval() time.Duration { return 0 }
   917  func (p paramsSeriesWrapper) Direction() logproto.Direction {
   918  	return logproto.FORWARD
   919  }
   920  func (p paramsSeriesWrapper) Limit() uint32 { return 0 }
   921  func (p paramsSeriesWrapper) Shards() []string {
   922  	return p.GetShards()
   923  }
   924  
   925  type paramsLabelNamesWrapper struct {
   926  	*LokiLabelNamesRequest
   927  }
   928  
   929  func (p paramsLabelNamesWrapper) Query() string {
   930  	return p.GetQuery()
   931  }
   932  
   933  func (p paramsLabelNamesWrapper) Start() time.Time {
   934  	return p.LokiLabelNamesRequest.GetStartTs()
   935  }
   936  
   937  func (p paramsLabelNamesWrapper) End() time.Time {
   938  	return p.LokiLabelNamesRequest.GetEndTs()
   939  }
   940  
   941  func (p paramsLabelNamesWrapper) Step() time.Duration {
   942  	return time.Duration(p.GetStep() * 1e6)
   943  }
   944  func (p paramsLabelNamesWrapper) Interval() time.Duration { return 0 }
   945  func (p paramsLabelNamesWrapper) Direction() logproto.Direction {
   946  	return logproto.FORWARD
   947  }
   948  func (p paramsLabelNamesWrapper) Limit() uint32 { return 0 }
   949  func (p paramsLabelNamesWrapper) Shards() []string {
   950  	return make([]string, 0)
   951  }
   952  
   953  func httpResponseHeadersToPromResponseHeaders(httpHeaders http.Header) []queryrangebase.PrometheusResponseHeader {
   954  	var promHeaders []queryrangebase.PrometheusResponseHeader
   955  	for h, hv := range httpHeaders {
   956  		promHeaders = append(promHeaders, queryrangebase.PrometheusResponseHeader{Name: h, Values: hv})
   957  	}
   958  
   959  	return promHeaders
   960  }
   961  
   962  func getQueryTags(ctx context.Context) string {
   963  	v, _ := ctx.Value(httpreq.QueryTagsHTTPHeader).(string) // it's ok to be empty
   964  	return v
   965  }
   966  
   967  func NewEmptyResponse(r queryrangebase.Request) (queryrangebase.Response, error) {
   968  	switch req := r.(type) {
   969  	case *LokiSeriesRequest:
   970  		return &LokiSeriesResponse{
   971  			Status:  loghttp.QueryStatusSuccess,
   972  			Version: uint32(loghttp.GetVersion(req.Path)),
   973  		}, nil
   974  	case *LokiLabelNamesRequest:
   975  		return &LokiLabelNamesResponse{
   976  			Status:  loghttp.QueryStatusSuccess,
   977  			Version: uint32(loghttp.GetVersion(req.Path)),
   978  		}, nil
   979  	case *LokiInstantRequest:
   980  		// instant queries in the frontend are always metrics queries.
   981  		return &LokiPromResponse{
   982  			Response: &queryrangebase.PrometheusResponse{
   983  				Status: loghttp.QueryStatusSuccess,
   984  				Data: queryrangebase.PrometheusData{
   985  					ResultType: loghttp.ResultTypeVector,
   986  				},
   987  			},
   988  		}, nil
   989  	case *LokiRequest:
   990  		// range query can either be metrics or logs
   991  		expr, err := syntax.ParseExpr(req.Query)
   992  		if err != nil {
   993  			return nil, httpgrpc.Errorf(http.StatusBadRequest, err.Error())
   994  		}
   995  		if _, ok := expr.(syntax.SampleExpr); ok {
   996  			return &LokiPromResponse{
   997  				Response: queryrangebase.NewEmptyPrometheusResponse(),
   998  			}, nil
   999  		}
  1000  		return &LokiResponse{
  1001  			Status:    loghttp.QueryStatusSuccess,
  1002  			Direction: req.Direction,
  1003  			Limit:     req.Limit,
  1004  			Version:   uint32(loghttp.GetVersion(req.Path)),
  1005  			Data: LokiData{
  1006  				ResultType: loghttp.ResultTypeStream,
  1007  			},
  1008  		}, nil
  1009  	default:
  1010  		return nil, fmt.Errorf("unsupported request type %T", req)
  1011  	}
  1012  }
  1013  
  1014  func mergeLokiResponse(responses ...queryrangebase.Response) *LokiResponse {
  1015  	if len(responses) == 0 {
  1016  		return nil
  1017  	}
  1018  	var (
  1019  		lokiRes       = responses[0].(*LokiResponse)
  1020  		mergedStats   stats.Result
  1021  		lokiResponses = make([]*LokiResponse, 0, len(responses))
  1022  	)
  1023  
  1024  	for _, res := range responses {
  1025  		lokiResult := res.(*LokiResponse)
  1026  		mergedStats.Merge(lokiResult.Statistics)
  1027  		lokiResponses = append(lokiResponses, lokiResult)
  1028  	}
  1029  
  1030  	return &LokiResponse{
  1031  		Status:     loghttp.QueryStatusSuccess,
  1032  		Direction:  lokiRes.Direction,
  1033  		Limit:      lokiRes.Limit,
  1034  		Version:    lokiRes.Version,
  1035  		ErrorType:  lokiRes.ErrorType,
  1036  		Error:      lokiRes.Error,
  1037  		Statistics: mergedStats,
  1038  		Data: LokiData{
  1039  			ResultType: loghttp.ResultTypeStream,
  1040  			Result:     mergeOrderedNonOverlappingStreams(lokiResponses, lokiRes.Limit, lokiRes.Direction),
  1041  		},
  1042  	}
  1043  }