From bb0f17ce5938a387fca18c045fbf570e0a644c81 Mon Sep 17 00:00:00 2001 From: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com> Date: Fri, 14 Aug 2020 10:33:37 +0200 Subject: [PATCH] Loki: Fix refresh on time range change for template variable queries (#26968) * Pass timerange and aadd tests * Update test --- .../datasource/loki/datasource.test.ts | 24 ++++++++++++++++ .../app/plugins/datasource/loki/datasource.ts | 28 +++++++++++-------- public/app/plugins/datasource/loki/mocks.ts | 4 +++ 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/public/app/plugins/datasource/loki/datasource.test.ts b/public/app/plugins/datasource/loki/datasource.test.ts index 053ffdf788c..9fbc3d15266 100644 --- a/public/app/plugins/datasource/loki/datasource.test.ts +++ b/public/app/plugins/datasource/loki/datasource.test.ts @@ -16,6 +16,17 @@ jest.mock('@grafana/runtime', () => ({ getBackendSrv: () => backendSrv, })); +jest.mock('app/features/dashboard/services/TimeSrv', () => { + return { + getTimeSrv: () => ({ + timeRange: () => ({ + from: new Date(0), + to: new Date(1), + }), + }), + }; +}); + const datasourceRequestMock = jest.spyOn(backendSrv, 'datasourceRequest'); describe('LokiDatasource', () => { @@ -442,6 +453,19 @@ describe('LokiDatasource', () => { expect(res.length).toBe(0); }); }); + + mocks.forEach((mock, index) => { + it(`should return label names according to provided rangefor Loki v${index} `, async () => { + ds.getVersion = mock.getVersion; + ds.metadataRequest = mock.metadataRequest; + const query = 'label_names()'; + const res = await ds.metricFindQuery(query, { + range: { from: new Date(2), to: new Date(3) }, + }); + expect(res[0].text).toEqual('label1'); + expect(res.length).toBe(1); + }); + }); }); }); diff --git a/public/app/plugins/datasource/loki/datasource.ts b/public/app/plugins/datasource/loki/datasource.ts index b0ae8f88660..16933e8d624 100644 --- a/public/app/plugins/datasource/loki/datasource.ts +++ b/public/app/plugins/datasource/loki/datasource.ts @@ -4,13 +4,14 @@ import { Observable, from, merge, of } from 'rxjs'; import { map, catchError, switchMap } from 'rxjs/operators'; // Services & Utils -import { DataFrame, dateMath, FieldCache, QueryResultMeta } from '@grafana/data'; +import { DataFrame, dateMath, FieldCache, QueryResultMeta, TimeRange } from '@grafana/data'; import { getBackendSrv, BackendSrvRequest, FetchError } from '@grafana/runtime'; import { addLabelToQuery } from 'app/plugins/datasource/prometheus/add_label_to_query'; import { TemplateSrv } from 'app/features/templating/template_srv'; import { convertToWebSocketUrl } from 'app/core/utils/explore'; import { lokiResultsToTableModel, processRangeQueryResponse, lokiStreamResultToDataFrame } from './result_transformer'; import { getHighlighterExpressionsFromQuery } from './query_utils'; +import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv'; // Types import { @@ -38,7 +39,7 @@ import { LokiStreamResponse, } from './types'; import { LiveStreams, LokiLiveTarget } from './live_streams'; -import LanguageProvider from './language_provider'; +import LanguageProvider, { rangeToParams } from './language_provider'; import { serializeParams } from '../../../core/utils/fetch'; import { RowContextOptions } from '@grafana/ui/src/components/Logs/LogRowContextProvider'; @@ -267,45 +268,48 @@ export class LokiDatasource extends DataSourceApi { return this.languageProvider.importQueries(queries, originMeta.id); } - async metadataRequest(url: string, params?: Record) { + async metadataRequest(url: string, params?: Record) { const res = await this._request(url, params, { hideFromInspector: true }).toPromise(); return res.data.data || res.data.values || []; } - async metricFindQuery(query: string) { + async metricFindQuery(query: string, optionalOptions?: any) { if (!query) { return Promise.resolve([]); } const interpolated = this.templateSrv.replace(query, {}, this.interpolateQueryExpr); - return await this.processMetricFindQuery(interpolated); + return await this.processMetricFindQuery(interpolated, optionalOptions?.range); } - async processMetricFindQuery(query: string) { + async processMetricFindQuery(query: string, range?: TimeRange) { const labelNamesRegex = /^label_names\(\)\s*$/; const labelValuesRegex = /^label_values\((?:(.+),\s*)?([a-zA-Z_][a-zA-Z0-9_]*)\)\s*$/; + const timeRange = range || getTimeSrv().timeRange(); + const params = rangeToParams({ from: timeRange.from.valueOf(), to: timeRange.to.valueOf() }); + const labelNames = query.match(labelNamesRegex); if (labelNames) { - return await this.labelNamesQuery(); + return await this.labelNamesQuery(params); } const labelValues = query.match(labelValuesRegex); if (labelValues) { - return await this.labelValuesQuery(labelValues[2]); + return await this.labelValuesQuery(labelValues[2], params); } return Promise.resolve([]); } - async labelNamesQuery() { + async labelNamesQuery(params?: Record) { const url = `${LOKI_ENDPOINT}/label`; - const result = await this.metadataRequest(url); + const result = await this.metadataRequest(url, params); return result.map((value: string) => ({ text: value })); } - async labelValuesQuery(label: string) { + async labelValuesQuery(label: string, params?: Record) { const url = `${LOKI_ENDPOINT}/label/${label}/values`; - const result = await this.metadataRequest(url); + const result = await this.metadataRequest(url, params); return result.map((value: string) => ({ text: value })); } diff --git a/public/app/plugins/datasource/loki/mocks.ts b/public/app/plugins/datasource/loki/mocks.ts index e91830e89b2..fe84a5f3d28 100644 --- a/public/app/plugins/datasource/loki/mocks.ts +++ b/public/app/plugins/datasource/loki/mocks.ts @@ -25,6 +25,10 @@ export function makeMockLokiDatasource(labelsAndValues: Labels, series?: SeriesF return { metadataRequest: (url: string, params?: { [key: string]: string }) => { if (url === lokiLabelsEndpoint) { + //To test custom time ranges + if (Number(params?.start) === 2000000) { + return [labels[0]]; + } return labels; } else { const labelsMatch = url.match(lokiLabelsAndValuesEndpointRegex);