|
|
|
@@ -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);
|
|
|
|
|
}
|
|
|
|
|