Like Prometheus, but for logs.
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.
 
 
 
 
 
 
loki/pkg/querier/queryrange/extensions.go

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
}