mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Loki: Add X-Query-Tags header for logs sample and data sample (#62333)
This commit is contained in:
parent
9453bec819
commit
d0e95f8c95
@ -85,8 +85,11 @@ func makeDataRequest(ctx context.Context, lokiDsUrl string, query lokiQuery) (*h
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if query.VolumeQuery {
|
if query.SupportingQueryType != SupportingQueryNone {
|
||||||
req.Header.Set("X-Query-Tags", "Source=logvolhist")
|
value := getSupportingQueryHeaderValue(req, query.SupportingQueryType)
|
||||||
|
if value != "" {
|
||||||
|
req.Header.Set("X-Query-Tags", "Source="+value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return req, nil
|
return req, nil
|
||||||
@ -223,3 +226,18 @@ func (api *LokiAPI) RawQuery(ctx context.Context, resourcePath string) (RawLokiR
|
|||||||
|
|
||||||
return encodedBytes, nil
|
return encodedBytes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getSupportingQueryHeaderValue(req *http.Request, supportingQueryType SupportingQueryType) string {
|
||||||
|
value := ""
|
||||||
|
switch supportingQueryType {
|
||||||
|
case SupportingQueryLogsVolume:
|
||||||
|
value = "logvolhist"
|
||||||
|
case SupportingQueryLogsSample:
|
||||||
|
value = "logsample"
|
||||||
|
case SupportingQueryDataSample:
|
||||||
|
value = "datasample"
|
||||||
|
default: //ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
@ -28,7 +28,31 @@ func TestApiLogVolume(t *testing.T) {
|
|||||||
require.Equal(t, "Source=logvolhist", req.Header.Get("X-Query-Tags"))
|
require.Equal(t, "Source=logvolhist", req.Header.Get("X-Query-Tags"))
|
||||||
})
|
})
|
||||||
|
|
||||||
_, err := api.DataQuery(context.Background(), lokiQuery{Expr: "", VolumeQuery: true, QueryType: QueryTypeRange})
|
_, err := api.DataQuery(context.Background(), lokiQuery{Expr: "", SupportingQueryType: SupportingQueryLogsVolume, QueryType: QueryTypeRange})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.True(t, called)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("logs sample queries should set logs sample http header", func(t *testing.T) {
|
||||||
|
called := false
|
||||||
|
api := makeMockedAPI(200, "application/json", response, func(req *http.Request) {
|
||||||
|
called = true
|
||||||
|
require.Equal(t, "Source=logsample", req.Header.Get("X-Query-Tags"))
|
||||||
|
})
|
||||||
|
|
||||||
|
_, err := api.DataQuery(context.Background(), lokiQuery{Expr: "", SupportingQueryType: SupportingQueryLogsSample, QueryType: QueryTypeRange})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.True(t, called)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("data sample queries should set data sample http header", func(t *testing.T) {
|
||||||
|
called := false
|
||||||
|
api := makeMockedAPI(200, "application/json", response, func(req *http.Request) {
|
||||||
|
called = true
|
||||||
|
require.Equal(t, "Source=datasample", req.Header.Get("X-Query-Tags"))
|
||||||
|
})
|
||||||
|
|
||||||
|
_, err := api.DataQuery(context.Background(), lokiQuery{Expr: "", SupportingQueryType: SupportingQueryDataSample, QueryType: QueryTypeRange})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.True(t, called)
|
require.True(t, called)
|
||||||
})
|
})
|
||||||
@ -40,7 +64,7 @@ func TestApiLogVolume(t *testing.T) {
|
|||||||
require.Equal(t, "", req.Header.Get("X-Query-Tags"))
|
require.Equal(t, "", req.Header.Get("X-Query-Tags"))
|
||||||
})
|
})
|
||||||
|
|
||||||
_, err := api.DataQuery(context.Background(), lokiQuery{Expr: "", VolumeQuery: false, QueryType: QueryTypeRange})
|
_, err := api.DataQuery(context.Background(), lokiQuery{Expr: "", SupportingQueryType: SupportingQueryNone, QueryType: QueryTypeRange})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.True(t, called)
|
require.True(t, called)
|
||||||
})
|
})
|
||||||
|
@ -57,15 +57,15 @@ type datasourceInfo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type QueryJSONModel struct {
|
type QueryJSONModel struct {
|
||||||
QueryType string `json:"queryType"`
|
QueryType string `json:"queryType"`
|
||||||
Expr string `json:"expr"`
|
Expr string `json:"expr"`
|
||||||
Direction string `json:"direction"`
|
Direction string `json:"direction"`
|
||||||
LegendFormat string `json:"legendFormat"`
|
LegendFormat string `json:"legendFormat"`
|
||||||
Interval string `json:"interval"`
|
Interval string `json:"interval"`
|
||||||
IntervalMS int `json:"intervalMS"`
|
IntervalMS int `json:"intervalMS"`
|
||||||
Resolution int64 `json:"resolution"`
|
Resolution int64 `json:"resolution"`
|
||||||
MaxLines int `json:"maxLines"`
|
MaxLines int `json:"maxLines"`
|
||||||
VolumeQuery bool `json:"volumeQuery"`
|
SupportingQueryType string `json:"supportingQueryType"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseQueryModel(raw json.RawMessage) (*QueryJSONModel, error) {
|
func parseQueryModel(raw json.RawMessage) (*QueryJSONModel, error) {
|
||||||
|
@ -82,6 +82,21 @@ func parseDirection(jsonValue string) (Direction, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseSupportingQueryType(jsonValue string) (SupportingQueryType, error) {
|
||||||
|
switch jsonValue {
|
||||||
|
case "logsVolume":
|
||||||
|
return SupportingQueryLogsVolume, nil
|
||||||
|
case "logsSample":
|
||||||
|
return SupportingQueryLogsSample, nil
|
||||||
|
case "dataSample":
|
||||||
|
return SupportingQueryDataSample, nil
|
||||||
|
case "":
|
||||||
|
return SupportingQueryNone, nil
|
||||||
|
default:
|
||||||
|
return SupportingQueryNone, fmt.Errorf("invalid supportingQueryType: %s", jsonValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func parseQuery(queryContext *backend.QueryDataRequest) ([]*lokiQuery, error) {
|
func parseQuery(queryContext *backend.QueryDataRequest) ([]*lokiQuery, error) {
|
||||||
qs := []*lokiQuery{}
|
qs := []*lokiQuery{}
|
||||||
for _, query := range queryContext.Queries {
|
for _, query := range queryContext.Queries {
|
||||||
@ -115,17 +130,22 @@ func parseQuery(queryContext *backend.QueryDataRequest) ([]*lokiQuery, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
supportingQueryType, err := parseSupportingQueryType(model.SupportingQueryType)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
qs = append(qs, &lokiQuery{
|
qs = append(qs, &lokiQuery{
|
||||||
Expr: expr,
|
Expr: expr,
|
||||||
QueryType: queryType,
|
QueryType: queryType,
|
||||||
Direction: direction,
|
Direction: direction,
|
||||||
Step: step,
|
Step: step,
|
||||||
MaxLines: model.MaxLines,
|
MaxLines: model.MaxLines,
|
||||||
LegendFormat: model.LegendFormat,
|
LegendFormat: model.LegendFormat,
|
||||||
Start: start,
|
Start: start,
|
||||||
End: end,
|
End: end,
|
||||||
RefID: query.RefID,
|
RefID: query.RefID,
|
||||||
VolumeQuery: model.VolumeQuery,
|
SupportingQueryType: supportingQueryType,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,12 +3,20 @@ package loki
|
|||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
type QueryType string
|
type QueryType string
|
||||||
|
type SupportingQueryType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
QueryTypeRange QueryType = "range"
|
QueryTypeRange QueryType = "range"
|
||||||
QueryTypeInstant QueryType = "instant"
|
QueryTypeInstant QueryType = "instant"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SupportingQueryLogsVolume SupportingQueryType = "logsVolume"
|
||||||
|
SupportingQueryLogsSample SupportingQueryType = "logsSample"
|
||||||
|
SupportingQueryDataSample SupportingQueryType = "dataSample"
|
||||||
|
SupportingQueryNone SupportingQueryType = "none"
|
||||||
|
)
|
||||||
|
|
||||||
type Direction string
|
type Direction string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -17,14 +25,14 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type lokiQuery struct {
|
type lokiQuery struct {
|
||||||
Expr string
|
Expr string
|
||||||
QueryType QueryType
|
QueryType QueryType
|
||||||
Direction Direction
|
Direction Direction
|
||||||
Step time.Duration
|
Step time.Duration
|
||||||
MaxLines int
|
MaxLines int
|
||||||
LegendFormat string
|
LegendFormat string
|
||||||
Start time.Time
|
Start time.Time
|
||||||
End time.Time
|
End time.Time
|
||||||
RefID string
|
RefID string
|
||||||
VolumeQuery bool
|
SupportingQueryType SupportingQueryType
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ import { CustomVariableModel } from '../../../features/variables/types';
|
|||||||
import { LokiDatasource, REF_ID_DATA_SAMPLES } from './datasource';
|
import { LokiDatasource, REF_ID_DATA_SAMPLES } from './datasource';
|
||||||
import { createLokiDatasource, createMetadataRequest } from './mocks';
|
import { createLokiDatasource, createMetadataRequest } from './mocks';
|
||||||
import { parseToNodeNamesArray } from './queryUtils';
|
import { parseToNodeNamesArray } from './queryUtils';
|
||||||
import { LokiOptions, LokiQuery, LokiQueryType, LokiVariableQueryType } from './types';
|
import { LokiOptions, LokiQuery, LokiQueryType, LokiVariableQueryType, SupportingQueryType } from './types';
|
||||||
import { LokiVariableSupport } from './variables';
|
import { LokiVariableSupport } from './variables';
|
||||||
|
|
||||||
jest.mock('@grafana/runtime', () => {
|
jest.mock('@grafana/runtime', () => {
|
||||||
@ -981,7 +981,7 @@ describe('LokiDatasource', () => {
|
|||||||
instant: false,
|
instant: false,
|
||||||
queryType: 'range',
|
queryType: 'range',
|
||||||
refId: 'log-volume-A',
|
refId: 'log-volume-A',
|
||||||
volumeQuery: true,
|
supportingQueryType: SupportingQueryType.LogsVolume,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -86,6 +86,7 @@ import {
|
|||||||
LokiQueryType,
|
LokiQueryType,
|
||||||
LokiVariableQuery,
|
LokiVariableQuery,
|
||||||
LokiVariableQueryType,
|
LokiVariableQueryType,
|
||||||
|
SupportingQueryType,
|
||||||
} from './types';
|
} from './types';
|
||||||
import { LokiVariableSupport } from './variables';
|
import { LokiVariableSupport } from './variables';
|
||||||
|
|
||||||
@ -191,7 +192,7 @@ export class LokiDatasource
|
|||||||
...normalizedQuery,
|
...normalizedQuery,
|
||||||
refId: `${REF_ID_STARTER_LOG_VOLUME}${normalizedQuery.refId}`,
|
refId: `${REF_ID_STARTER_LOG_VOLUME}${normalizedQuery.refId}`,
|
||||||
instant: false,
|
instant: false,
|
||||||
volumeQuery: true,
|
supportingQueryType: SupportingQueryType.LogsVolume,
|
||||||
expr: `sum by (level) (count_over_time(${expr}[$__interval]))`,
|
expr: `sum by (level) (count_over_time(${expr}[$__interval]))`,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -42,8 +42,8 @@ export interface LokiQuery extends DataQuery {
|
|||||||
legendFormat?: string;
|
legendFormat?: string;
|
||||||
maxLines?: number;
|
maxLines?: number;
|
||||||
resolution?: number;
|
resolution?: number;
|
||||||
/** Used in range queries */
|
/** Used only to identify supporting queries, e.g. logs volume, logs sample and data sample */
|
||||||
volumeQuery?: boolean;
|
supportingQueryType?: SupportingQueryType;
|
||||||
/* @deprecated now use queryType */
|
/* @deprecated now use queryType */
|
||||||
range?: boolean;
|
range?: boolean;
|
||||||
/* @deprecated now use queryType */
|
/* @deprecated now use queryType */
|
||||||
@ -154,6 +154,12 @@ export interface LokiVariableQuery extends DataQuery {
|
|||||||
stream?: string;
|
stream?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum SupportingQueryType {
|
||||||
|
LogsVolume = 'logsVolume',
|
||||||
|
LogsSample = 'logsSample',
|
||||||
|
DataSample = 'dataSample',
|
||||||
|
}
|
||||||
|
|
||||||
export interface ContextFilter {
|
export interface ContextFilter {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
label: string;
|
label: string;
|
||||||
|
Loading…
Reference in New Issue
Block a user