mirror of https://github.com/grafana/loki
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
306 lines
8.9 KiB
306 lines
8.9 KiB
package queryrange
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/grafana/jsonparser"
|
|
|
|
"github.com/grafana/loki/v3/pkg/logproto"
|
|
"github.com/grafana/loki/v3/pkg/querier/queryrange/queryrangebase"
|
|
)
|
|
|
|
// To satisfy queryrange.Response interface(https://github.com/cortexproject/cortex/blob/21bad57b346c730d684d6d0205efef133422ab28/pkg/querier/queryrange/query_range.go#L88)
|
|
// we need to have following method as well on response types:
|
|
// GetHeaders() []*queryrange.PrometheusResponseHeader.
|
|
// This could have been done by adding "Headers" field with custom type in proto definition for various Response types which doesn't work because
|
|
// gogoproto doesn't generate getters for custom types so adding them here.
|
|
// See issue https://github.com/gogo/protobuf/issues/477 for more details.
|
|
// It also has issue of generating slices without pointer to the custom type for Repeated customtype fields, see https://github.com/gogo/protobuf/issues/478
|
|
// which is why we also have to do conversion from non-pointer to pointer type.
|
|
|
|
func (m *LokiLabelNamesResponse) GetHeaders() []*queryrangebase.PrometheusResponseHeader {
|
|
if m != nil {
|
|
return convertPrometheusResponseHeadersToPointers(m.Headers)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *LokiLabelNamesResponse) SetHeader(name, value string) {
|
|
m.Headers = setHeader(m.Headers, name, value)
|
|
}
|
|
|
|
func (m *LokiLabelNamesResponse) WithHeaders(h []queryrangebase.PrometheusResponseHeader) queryrangebase.Response {
|
|
m.Headers = h
|
|
return m
|
|
}
|
|
|
|
func (m *LokiSeriesResponse) GetHeaders() []*queryrangebase.PrometheusResponseHeader {
|
|
if m != nil {
|
|
return convertPrometheusResponseHeadersToPointers(m.Headers)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *LokiSeriesResponse) SetHeader(name, value string) {
|
|
m.Headers = setHeader(m.Headers, name, value)
|
|
}
|
|
|
|
func (m *LokiSeriesResponse) WithHeaders(h []queryrangebase.PrometheusResponseHeader) queryrangebase.Response {
|
|
m.Headers = h
|
|
return m
|
|
}
|
|
|
|
// UnmarshalJSON decodes from loghttpSeriesResponse JSON format directly into
|
|
// the protobuf LokiSeriesResponse.
|
|
func (m *LokiSeriesResponse) UnmarshalJSON(data []byte) error {
|
|
var err error
|
|
m.Status, err = jsonparser.GetString(data, "status")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var parseErr error
|
|
_, err = jsonparser.ArrayEach(data, func(value []byte, vt jsonparser.ValueType, _ int, _ error) {
|
|
if vt != jsonparser.Object {
|
|
parseErr = fmt.Errorf("unexpected data type: got(%s), expected (object)", vt)
|
|
return
|
|
}
|
|
|
|
identifier := logproto.SeriesIdentifier{}
|
|
parseErr = jsonparser.ObjectEach(value, func(key, val []byte, vt jsonparser.ValueType, _ int) error {
|
|
if vt != jsonparser.String {
|
|
return fmt.Errorf("unexpected label value type: got(%s), expected (string)", vt)
|
|
}
|
|
v, err := jsonparser.ParseString(val)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
k, err := jsonparser.ParseString(key)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
identifier.Labels = append(identifier.Labels, logproto.SeriesIdentifier_LabelsEntry{Key: k, Value: v})
|
|
return nil
|
|
})
|
|
|
|
if parseErr != nil {
|
|
return
|
|
}
|
|
m.Data = append(m.Data, identifier)
|
|
}, "data")
|
|
if parseErr != nil {
|
|
return parseErr
|
|
}
|
|
return err
|
|
}
|
|
|
|
func (m *LokiPromResponse) GetHeaders() []*queryrangebase.PrometheusResponseHeader {
|
|
if m != nil {
|
|
return m.Response.GetHeaders()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *LokiPromResponse) SetHeader(name, value string) {
|
|
m.Response.SetHeader(name, value)
|
|
}
|
|
|
|
func (m *LokiPromResponse) WithHeaders(h []queryrangebase.PrometheusResponseHeader) queryrangebase.Response {
|
|
m.Response.Headers = convertPrometheusResponseHeadersToPointers(h)
|
|
return m
|
|
}
|
|
|
|
func (m *LokiResponse) GetHeaders() []*queryrangebase.PrometheusResponseHeader {
|
|
if m != nil {
|
|
return convertPrometheusResponseHeadersToPointers(m.Headers)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *LokiResponse) SetHeader(name, value string) {
|
|
m.Headers = setHeader(m.Headers, name, value)
|
|
}
|
|
|
|
func (m *LokiResponse) WithHeaders(h []queryrangebase.PrometheusResponseHeader) queryrangebase.Response {
|
|
m.Headers = h
|
|
return m
|
|
}
|
|
|
|
func convertPrometheusResponseHeadersToPointers(h []queryrangebase.PrometheusResponseHeader) []*queryrangebase.PrometheusResponseHeader {
|
|
if h == nil {
|
|
return nil
|
|
}
|
|
|
|
resp := make([]*queryrangebase.PrometheusResponseHeader, len(h))
|
|
for i := range h {
|
|
resp[i] = &h[i]
|
|
}
|
|
|
|
return resp
|
|
}
|
|
|
|
// setHeader returns the passed headers with the new key-valur pair. Existing
|
|
// entries with the same key are overridden. The order is *not* maintained.
|
|
func setHeader(headers []queryrangebase.PrometheusResponseHeader, key, value string) []queryrangebase.PrometheusResponseHeader {
|
|
for i, h := range headers {
|
|
if h.Name == key {
|
|
headers[i].Values = []string{value}
|
|
return headers
|
|
}
|
|
}
|
|
|
|
return append(headers, queryrangebase.PrometheusResponseHeader{Name: key, Values: []string{value}})
|
|
}
|
|
|
|
// GetHeaders returns the HTTP headers in the response.
|
|
func (m *IndexStatsResponse) GetHeaders() []*queryrangebase.PrometheusResponseHeader {
|
|
if m != nil {
|
|
return convertPrometheusResponseHeadersToPointers(m.Headers)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *IndexStatsResponse) SetHeader(name, value string) {
|
|
m.Headers = setHeader(m.Headers, name, value)
|
|
}
|
|
|
|
func (m *IndexStatsResponse) WithHeaders(h []queryrangebase.PrometheusResponseHeader) queryrangebase.Response {
|
|
m.Headers = h
|
|
return m
|
|
}
|
|
|
|
// GetHeaders returns the HTTP headers in the response.
|
|
func (m *VolumeResponse) GetHeaders() []*queryrangebase.PrometheusResponseHeader {
|
|
if m != nil {
|
|
return convertPrometheusResponseHeadersToPointers(m.Headers)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *VolumeResponse) SetHeader(name, value string) {
|
|
m.Headers = setHeader(m.Headers, name, value)
|
|
}
|
|
|
|
func (m *VolumeResponse) WithHeaders(h []queryrangebase.PrometheusResponseHeader) queryrangebase.Response {
|
|
m.Headers = h
|
|
return m
|
|
}
|
|
|
|
// GetHeaders returns the HTTP headers in the response.
|
|
func (m *TopKSketchesResponse) GetHeaders() []*queryrangebase.PrometheusResponseHeader {
|
|
if m != nil {
|
|
return convertPrometheusResponseHeadersToPointers(m.Headers)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *TopKSketchesResponse) SetHeader(name, value string) {
|
|
m.Headers = setHeader(m.Headers, name, value)
|
|
}
|
|
|
|
func (m *TopKSketchesResponse) WithHeaders(h []queryrangebase.PrometheusResponseHeader) queryrangebase.Response {
|
|
m.Headers = h
|
|
return m
|
|
}
|
|
|
|
// GetHeaders returns the HTTP headers in the response.
|
|
func (m *QuantileSketchResponse) GetHeaders() []*queryrangebase.PrometheusResponseHeader {
|
|
if m != nil {
|
|
return convertPrometheusResponseHeadersToPointers(m.Headers)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *QuantileSketchResponse) SetHeader(name, value string) {
|
|
m.Headers = setHeader(m.Headers, name, value)
|
|
}
|
|
|
|
func (m *QuantileSketchResponse) WithHeaders(h []queryrangebase.PrometheusResponseHeader) queryrangebase.Response {
|
|
m.Headers = h
|
|
return m
|
|
}
|
|
|
|
// GetHeaders returns the HTTP headers in the response.
|
|
func (m *CountMinSketchResponse) GetHeaders() []*queryrangebase.PrometheusResponseHeader {
|
|
if m != nil {
|
|
return convertPrometheusResponseHeadersToPointers(m.Headers)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *CountMinSketchResponse) SetHeader(name, value string) {
|
|
m.Headers = setHeader(m.Headers, name, value)
|
|
}
|
|
|
|
func (m *CountMinSketchResponse) WithHeaders(h []queryrangebase.PrometheusResponseHeader) queryrangebase.Response {
|
|
m.Headers = h
|
|
return m
|
|
}
|
|
|
|
func (m *ShardsResponse) GetHeaders() []*queryrangebase.PrometheusResponseHeader {
|
|
if m != nil {
|
|
return convertPrometheusResponseHeadersToPointers(m.Headers)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *ShardsResponse) SetHeader(name, value string) {
|
|
m.Headers = setHeader(m.Headers, name, value)
|
|
}
|
|
|
|
func (m *ShardsResponse) WithHeaders(h []queryrangebase.PrometheusResponseHeader) queryrangebase.Response {
|
|
m.Headers = h
|
|
return m
|
|
}
|
|
|
|
// GetHeaders returns the HTTP headers in the response.
|
|
func (m *DetectedFieldsResponse) GetHeaders() []*queryrangebase.PrometheusResponseHeader {
|
|
if m != nil {
|
|
return convertPrometheusResponseHeadersToPointers(m.Headers)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *DetectedFieldsResponse) SetHeader(name, value string) {
|
|
m.Headers = setHeader(m.Headers, name, value)
|
|
}
|
|
|
|
func (m *DetectedFieldsResponse) WithHeaders(h []queryrangebase.PrometheusResponseHeader) queryrangebase.Response {
|
|
m.Headers = h
|
|
return m
|
|
}
|
|
|
|
// GetHeaders returns the HTTP headers in the response.
|
|
func (m *QueryPatternsResponse) GetHeaders() []*queryrangebase.PrometheusResponseHeader {
|
|
if m != nil {
|
|
return convertPrometheusResponseHeadersToPointers(m.Headers)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetHeaders returns the HTTP headers in the response.
|
|
func (m *DetectedLabelsResponse) GetHeaders() []*queryrangebase.PrometheusResponseHeader {
|
|
if m != nil {
|
|
return convertPrometheusResponseHeadersToPointers(m.Headers)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *QueryPatternsResponse) SetHeader(name, value string) {
|
|
m.Headers = setHeader(m.Headers, name, value)
|
|
}
|
|
|
|
func (m *QueryPatternsResponse) WithHeaders(h []queryrangebase.PrometheusResponseHeader) queryrangebase.Response {
|
|
m.Headers = h
|
|
return m
|
|
}
|
|
|
|
func (m *DetectedLabelsResponse) SetHeader(name, value string) {
|
|
m.Headers = setHeader(m.Headers, name, value)
|
|
}
|
|
|
|
func (m *DetectedLabelsResponse) WithHeaders(h []queryrangebase.PrometheusResponseHeader) queryrangebase.Response {
|
|
m.Headers = h
|
|
return m
|
|
}
|
|
|