loki: run some queries through the backend (#44729)

This commit is contained in:
Gábor Farkas 2022-02-07 08:43:48 +01:00 committed by GitHub
parent 3a2e3267ba
commit 560c773905
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 65 additions and 10 deletions

View File

@ -29,6 +29,7 @@ export interface FeatureToggles {
tempoSearch?: boolean;
tempoBackendSearch?: boolean;
tempoServiceGraph?: boolean;
lokiBackendMode?: boolean;
fullRangeLogsVolume?: boolean;
accesscontrol?: boolean;
prometheus_azure_auth?: boolean;

View File

@ -72,6 +72,12 @@ var (
State: FeatureStateBeta,
FrontendOnly: true,
},
{
Name: "lokiBackendMode",
Description: "Loki datasource works as backend datasource",
State: FeatureStateAlpha,
FrontendOnly: true,
},
{
Name: "fullRangeLogsVolume",
Description: "Show full range logs volume in explore",

View File

@ -55,6 +55,10 @@ const (
// show service
FlagTempoServiceGraph = "tempoServiceGraph"
// FlagLokiBackendMode
// Loki datasource works as backend datasource
FlagLokiBackendMode = "lokiBackendMode"
// FlagFullRangeLogsVolume
// Show full range logs volume in explore
FlagFullRangeLogsVolume = "fullRangeLogsVolume"

View File

@ -8,12 +8,12 @@ import Prism from 'prismjs';
import {
AnnotationEvent,
AnnotationQueryRequest,
CoreApp,
DataFrame,
DataFrameView,
DataQueryError,
DataQueryRequest,
DataQueryResponse,
DataSourceApi,
DataSourceInstanceSettings,
DataSourceWithLogsContextSupport,
DataSourceWithLogsVolumeSupport,
@ -33,7 +33,7 @@ import {
ScopedVars,
TimeRange,
} from '@grafana/data';
import { BackendSrvRequest, FetchError, getBackendSrv } from '@grafana/runtime';
import { BackendSrvRequest, FetchError, getBackendSrv, DataSourceWithBackend } from '@grafana/runtime';
import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_srv';
import { addLabelToQuery } from './add_label_to_query';
import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
@ -44,7 +44,7 @@ import {
lokiStreamsToDataFrames,
processRangeQueryResponse,
} from './result_transformer';
import { addParsedLabelToQuery, queryHasPipeParser } from './query_utils';
import { addParsedLabelToQuery, getNormalizedLokiQuery, queryHasPipeParser } from './query_utils';
import {
LokiOptions,
@ -86,7 +86,7 @@ const DEFAULT_QUERY_PARAMS: Partial<LokiRangeQueryRequest> = {
};
export class LokiDatasource
extends DataSourceApi<LokiQuery, LokiOptions>
extends DataSourceWithBackend<LokiQuery, LokiOptions>
implements
DataSourceWithLogsContextSupport,
DataSourceWithLogsVolumeSupport<LokiQuery>,
@ -157,13 +157,37 @@ export class LokiDatasource
});
}
query(options: DataQueryRequest<LokiQuery>): Observable<DataQueryResponse> {
query(request: DataQueryRequest<LokiQuery>): Observable<DataQueryResponse> {
const subQueries: Array<Observable<DataQueryResponse>> = [];
const scopedVars = {
...options.scopedVars,
...this.getRangeScopedVars(options.range),
...request.scopedVars,
...this.getRangeScopedVars(request.range),
};
const filteredTargets = options.targets
// if all these are true, run query through backend:
// - feature-flag is enabled
// - we are in explore-mode
// - for every query it is true that:
// - query is range query
// - and query is metric query
// - and query is not a log-volume-query (those need a custom http header)
const shouldRunBackendQuery =
config.featureToggles.lokiBackendMode &&
request.app === CoreApp.Explore &&
request.targets.every(
(query) => query.queryType === LokiQueryType.Range && isMetricsQuery(query.expr) && !query.volumeQuery
);
if (shouldRunBackendQuery) {
// we "fix" the loki queries to have `.queryType` and not have `.instant` and `.range`
const fixedRequest = {
...request,
targets: request.targets.map(getNormalizedLokiQuery),
};
return super.query(fixedRequest);
}
const filteredTargets = request.targets
.filter((target) => target.expr && !target.hide)
.map((target) => {
const expr = this.addAdHocFilters(target.expr);
@ -175,9 +199,9 @@ export class LokiDatasource
for (const target of filteredTargets) {
if (target.instant || target.queryType === LokiQueryType.Instant) {
subQueries.push(this.runInstantQuery(target, options, filteredTargets.length));
subQueries.push(this.runInstantQuery(target, request, filteredTargets.length));
} else {
subQueries.push(this.runRangeQuery(target, options, filteredTargets.length));
subQueries.push(this.runRangeQuery(target, request, filteredTargets.length));
}
}
@ -755,6 +779,26 @@ export class LokiDatasource
}
}
// Used when running queries through backend
filterQuery(query: LokiQuery): boolean {
if (query.hide || query.expr === '') {
return false;
}
return true;
}
// Used when running queries through backend
applyTemplateVariables(target: LokiQuery, scopedVars: ScopedVars): Record<string, any> {
// We want to interpolate these variables on backend
const { __interval, __interval_ms, ...rest } = scopedVars;
return {
...target,
legendFormat: this.templateSrv.replace(target.legendFormat, rest),
expr: this.templateSrv.replace(target.expr, rest, this.interpolateQueryExpr),
};
}
interpolateString(string: string) {
return this.templateSrv.replace(string, undefined, this.interpolateQueryExpr);
}