Commit b6efebd9 by Hugo Häggmark Committed by GitHub

Elastic: Fixes so templating queries work (#30003)

* Elastic: Fixes so templating queries work

* Chore: fixes test

* Fix: fixes getFields from metricFindQuery
parent b2b3a603
import { DateTime } from '../datetime/moment_wrapper';
import { dateTime, DateTime } from '../datetime/moment_wrapper';
export interface RawTimeRange {
from: DateTime | string;
......@@ -42,8 +42,10 @@ export type TimeFragment = string | DateTime;
export const TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss';
export const DefaultTimeRange: TimeRange = {
from: {} as DateTime,
to: {} as DateTime,
raw: { from: '6h', to: 'now' },
};
export function getDefaultTimeRange(): TimeRange {
return {
from: dateTime().subtract(6, 'hour'),
to: dateTime(),
raw: { from: 'now-6h', to: 'now' },
};
}
import React, { FC, FormEvent, MouseEvent, useState } from 'react';
import { css, cx } from 'emotion';
import { dateTime, GrafanaTheme, TimeRange, TimeZone, dateMath } from '@grafana/data';
import { dateMath, dateTime, getDefaultTimeRange, GrafanaTheme, TimeRange, TimeZone } from '@grafana/data';
import { useStyles } from '../../themes/ThemeContext';
import { ClickOutsideWrapper } from '../ClickOutsideWrapper/ClickOutsideWrapper';
import { Icon } from '../Icon/Icon';
......@@ -10,12 +10,6 @@ import { TimePickerButtonLabel } from './TimeRangePicker';
import { TimePickerContent } from './TimeRangePicker/TimePickerContent';
import { otherOptions, quickOptions } from './rangeOptions';
export const defaultTimeRange: TimeRange = {
from: dateTime().subtract(6, 'hour'),
to: dateTime(),
raw: { from: 'now-6h', to: 'now' },
};
const isValidTimeRange = (range: any) => {
return dateMath.isValid(range.from) && dateMath.isValid(range.to);
};
......@@ -86,7 +80,7 @@ export const TimeRangeInput: FC<Props> = ({
<ClickOutsideWrapper includeButtonPress={false} onClick={onClose}>
<TimePickerContent
timeZone={timeZone}
value={isValidTimeRange(value) ? (value as TimeRange) : defaultTimeRange}
value={isValidTimeRange(value) ? (value as TimeRange) : getDefaultTimeRange()}
onChange={onRangeChange}
otherOptions={otherOptions}
quickOptions={quickOptions}
......
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { PanelModel } from '../../../state/PanelModel';
import { DefaultTimeRange, LoadingState, PanelData } from '@grafana/data';
import { getDefaultTimeRange, LoadingState, PanelData } from '@grafana/data';
import { DisplayMode } from '../types';
import store from '../../../../../core/store';
......@@ -51,7 +51,7 @@ export const initialState = (): PanelEditorState => {
getData: () => ({
state: LoadingState.NotStarted,
series: [],
timeRange: DefaultTimeRange,
timeRange: getDefaultTimeRange(),
}),
initDone: false,
shouldDiscardChanges: false,
......
......@@ -15,15 +15,15 @@ import { updateLocation } from 'app/core/actions';
import { DashboardModel, PanelModel } from '../state';
import { PANEL_BORDER } from 'app/core/constants';
import {
LoadingState,
AbsoluteTimeRange,
DefaultTimeRange,
toUtc,
toDataFrameDTO,
FieldConfigSource,
getDefaultTimeRange,
LoadingState,
PanelData,
PanelPlugin,
FieldConfigSource,
PanelPluginMeta,
toDataFrameDTO,
toUtc,
} from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { loadSnapshotData } from '../utils/loadSnapshotData';
......@@ -65,7 +65,7 @@ export class PanelChrome extends Component<Props, State> {
data: {
state: LoadingState.NotStarted,
series: [],
timeRange: DefaultTimeRange,
timeRange: getDefaultTimeRange(),
},
};
}
......
......@@ -13,7 +13,7 @@ import config from 'app/core/config';
// Types
import { DashboardModel, PanelModel } from '../state';
import { StoreState } from 'app/types';
import { DefaultTimeRange, LoadingState, PanelData, PanelPlugin } from '@grafana/data';
import { getDefaultTimeRange, LoadingState, PanelData, PanelPlugin } from '@grafana/data';
import { updateLocation } from 'app/core/actions';
import { PANEL_BORDER } from 'app/core/constants';
import { selectors } from '@grafana/e2e-selectors';
......@@ -68,7 +68,7 @@ export class PanelChromeAngularUnconnected extends PureComponent<Props, State> {
data: {
state: LoadingState.NotStarted,
series: [],
timeRange: DefaultTimeRange,
timeRange: getDefaultTimeRange(),
},
};
}
......
......@@ -5,19 +5,19 @@ import coreModule from 'app/core/core_module';
// Types
import {
dateMath,
DefaultTimeRange,
TimeRange,
RawTimeRange,
toUtc,
dateTime,
getDefaultTimeRange,
isDateTime,
rangeUtil,
RawTimeRange,
TimeRange,
toUtc,
} from '@grafana/data';
import { ITimeoutService, ILocationService } from 'angular';
import { ILocationService, ITimeoutService } from 'angular';
import { ContextSrv } from 'app/core/services/context_srv';
import { DashboardModel } from '../state/DashboardModel';
import { GrafanaRootScope } from 'app/routes/GrafanaCtrl';
import { getZoomedTimeRange, getShiftedTimeRange } from 'app/core/utils/timePicker';
import { getShiftedTimeRange, getZoomedTimeRange } from 'app/core/utils/timePicker';
import { appEvents } from '../../../core/core';
import { CoreEvents } from '../../../types';
......@@ -41,7 +41,7 @@ export class TimeSrv {
private contextSrv: ContextSrv
) {
// default time
this.time = DefaultTimeRange.raw;
this.time = getDefaultTimeRange().raw;
appEvents.on(CoreEvents.zoomOut, this.zoomOut.bind(this));
appEvents.on(CoreEvents.shiftTime, this.shiftTime.bind(this));
......
import { applyFieldOverrides, DefaultTimeRange, LoadingState, PanelData } from '@grafana/data';
import { applyFieldOverrides, getDefaultTimeRange, LoadingState, PanelData } from '@grafana/data';
import { config } from 'app/core/config';
import { DashboardModel, PanelModel } from '../state';
import { getProcessedDataFrames } from '../../query/state/runRequest';
......@@ -7,7 +7,7 @@ export function loadSnapshotData(panel: PanelModel, dashboard: DashboardModel):
const data = getProcessedDataFrames(panel.snapshotData);
return {
timeRange: DefaultTimeRange,
timeRange: getDefaultTimeRange(),
state: LoadingState.Done,
series: applyFieldOverrides({
data,
......
import { PayloadAction } from '@reduxjs/toolkit';
import { DataQuery, DefaultTimeZone, ExploreUrlState, LogsDedupStrategy, toUtc, EventBusExtended } from '@grafana/data';
import { DataQuery, DefaultTimeZone, EventBusExtended, ExploreUrlState, LogsDedupStrategy, toUtc } from '@grafana/data';
import { ExploreId, ExploreItemState, ExploreUpdateState } from 'app/types';
import { thunkTester } from 'test/core/thunk/thunkTester';
import {
......@@ -154,7 +154,7 @@ describe('Explore pane reducer', () => {
changeDedupStrategyAction({ exploreId: ExploreId.left, dedupStrategy: LogsDedupStrategy.exact })
)
.thenStateShouldEqual({
...makeExplorePaneState(),
...initialState,
dedupStrategy: LogsDedupStrategy.exact,
});
});
......
import {
addQueryRowAction,
cancelQueries,
cancelQueriesAction,
scanStartAction,
scanStopAction,
queryReducer,
addQueryRowAction,
removeQueryRowAction,
scanStartAction,
scanStopAction,
} from './query';
import { ExploreId, ExploreItemState } from 'app/types';
import { interval } from 'rxjs';
......@@ -71,7 +71,7 @@ describe('reducer', () => {
.givenReducer(queryReducer, initialState)
.whenActionIsDispatched(scanStartAction({ exploreId: ExploreId.left }))
.thenStateShouldEqual({
...makeExplorePaneState(),
...initialState,
scanning: true,
});
});
......@@ -86,7 +86,7 @@ describe('reducer', () => {
.givenReducer(queryReducer, initialState)
.whenActionIsDispatched(scanStopAction({ exploreId: ExploreId.left }))
.thenStateShouldEqual({
...makeExplorePaneState(),
...initialState,
scanning: false,
scanRange: undefined,
});
......
......@@ -10,7 +10,7 @@ describe('Explore item reducer', () => {
it("should result in 'streaming' state, when live-tailing is active", () => {
const initialState = makeExplorePaneState();
const expectedState = {
...makeExplorePaneState(),
...initialState,
refreshInterval: 'LIVE',
isLive: true,
loading: true,
......@@ -19,7 +19,7 @@ describe('Explore item reducer', () => {
rows: [] as any[],
},
queryResponse: {
...makeExplorePaneState().queryResponse,
...initialState.queryResponse,
state: LoadingState.Streaming,
},
};
......@@ -32,14 +32,14 @@ describe('Explore item reducer', () => {
it("should result in 'done' state, when live-tailing is stopped", () => {
const initialState = makeExplorePaneState();
const expectedState = {
...makeExplorePaneState(),
...initialState,
refreshInterval: '',
logsResult: {
hasUniqueLabels: false,
rows: [] as any[],
},
queryResponse: {
...makeExplorePaneState().queryResponse,
...initialState.queryResponse,
state: LoadingState.Done,
},
};
......
import {
DataSourceApi,
EventBusExtended,
DefaultTimeRange,
getDefaultTimeRange,
HistoryItem,
LoadingState,
LogsDedupStrategy,
PanelData,
DataSourceApi,
HistoryItem,
} from '@grafana/data';
import { ExploreItemState, ExploreUpdateState } from 'app/types/explore';
......@@ -64,7 +64,7 @@ export const makeExplorePaneState = (): ExploreItemState => ({
export const createEmptyQueryResponse = (): PanelData => ({
state: LoadingState.NotStarted,
series: [],
timeRange: DefaultTimeRange,
timeRange: getDefaultTimeRange(),
});
export async function loadAndInitDatasource(
......
......@@ -11,11 +11,11 @@ import config from 'app/core/config';
// Types
import {
DataQuery,
DefaultTimeRange,
LoadingState,
PanelData,
DataSourceApi,
DataSourceInstanceSettings,
getDefaultTimeRange,
LoadingState,
PanelData,
} from '@grafana/data';
import { PluginHelp } from 'app/core/components/PluginHelp/PluginHelp';
import { addQuery } from 'app/core/utils/query';
......@@ -62,7 +62,7 @@ export class QueryGroup extends PureComponent<Props, State> {
data: {
state: LoadingState.NotStarted,
series: [],
timeRange: DefaultTimeRange,
timeRange: getDefaultTimeRange(),
},
};
......
import { of, throwError } from 'rxjs';
import { DefaultTimeRange, LoadingState, VariableSupportType } from '@grafana/data';
import { getDefaultTimeRange, LoadingState, VariableSupportType } from '@grafana/data';
import { delay } from 'rxjs/operators';
import { UpdateOptionsResults, VariableQueryRunner } from './VariableQueryRunner';
......@@ -46,7 +46,7 @@ function getTestContext(variable?: QueryVariableModel) {
.withId('query')
.build();
const getTimeSrv = jest.fn().mockReturnValue({
timeRange: jest.fn().mockReturnValue(DefaultTimeRange),
timeRange: jest.fn().mockReturnValue(getDefaultTimeRange()),
});
const datasource: any = { metricFindQuery: jest.fn().mockResolvedValue([]) };
const identifier = toVariableIdentifier(variable);
......
......@@ -5,7 +5,7 @@ import {
DataQuery,
DataQueryRequest,
DataSourceApi,
DefaultTimeRange,
getDefaultTimeRange,
LoadingState,
ScopedVars,
} from '@grafana/data';
......@@ -177,7 +177,7 @@ export class VariableQueryRunner {
const range =
variable.refresh === VariableRefresh.onTimeRangeChanged
? this.dependencies.getTimeSrv().timeRange()
: DefaultTimeRange;
: getDefaultTimeRange();
const request: DataQueryRequest = {
app: CoreApp.Dashboard,
......
import { DefaultTimeRange, LoadingState } from '@grafana/data';
import { getDefaultTimeRange, LoadingState } from '@grafana/data';
import { variableAdapters } from '../adapters';
import { createQueryVariableAdapter } from './adapter';
......@@ -68,7 +68,7 @@ describe('query actions', () => {
beforeEach(() => {
originalTimeSrv = getTimeSrv();
setTimeSrv(({
timeRange: jest.fn().mockReturnValue(DefaultTimeRange),
timeRange: jest.fn().mockReturnValue(getDefaultTimeRange()),
} as unknown) as TimeSrv);
setVariableQueryRunner(new VariableQueryRunner());
});
......
import { QueryRunners } from './queryRunners';
import { DefaultTimeRange, VariableSupportType } from '@grafana/data';
import { getDefaultTimeRange, VariableSupportType } from '@grafana/data';
import { VariableRefresh } from '../types';
import { of } from 'rxjs';
describe('QueryRunners', () => {
describe('when using a legacy data source', () => {
const getLegacyTestContext = (variable?: any) => {
const defaultTimeRange = getDefaultTimeRange();
variable = variable ?? { query: 'A query' };
const timeSrv = {
timeRange: jest.fn().mockReturnValue(DefaultTimeRange),
timeRange: jest.fn().mockReturnValue(defaultTimeRange),
};
const datasource: any = { metricFindQuery: jest.fn().mockResolvedValue([{ text: 'A', value: 'A' }]) };
const runner = new QueryRunners().getRunnerForDatasource(datasource);
......@@ -16,7 +17,7 @@ describe('QueryRunners', () => {
const runnerArgs: any = { datasource, variable, searchFilter: 'A searchFilter', timeSrv, runRequest };
const request: any = {};
return { timeSrv, datasource, runner, variable, runnerArgs, request };
return { timeSrv, datasource, runner, variable, runnerArgs, request, defaultTimeRange };
};
describe('and calling getRunnerForDatasource', () => {
......@@ -35,7 +36,7 @@ describe('QueryRunners', () => {
});
describe('and calling runRequest with a variable that refreshes when time range changes', () => {
const { datasource, runner, runnerArgs, request, timeSrv } = getLegacyTestContext({
const { datasource, runner, runnerArgs, request, timeSrv, defaultTimeRange } = getLegacyTestContext({
query: 'A query',
refresh: VariableRefresh.onTimeRangeChanged,
});
......@@ -47,7 +48,7 @@ describe('QueryRunners', () => {
expect(value).toEqual({
series: [{ text: 'A', value: 'A' }],
state: 'Done',
timeRange: { from: {}, raw: { from: '6h', to: 'now' }, to: {} },
timeRange: defaultTimeRange,
});
});
});
......@@ -59,14 +60,7 @@ describe('QueryRunners', () => {
it('and it should call metricFindQuery with correct options', () => {
expect(datasource.metricFindQuery).toHaveBeenCalledTimes(1);
expect(datasource.metricFindQuery).toHaveBeenCalledWith('A query', {
range: {
from: {},
raw: {
from: '6h',
to: 'now',
},
to: {},
},
range: defaultTimeRange,
searchFilter: 'A searchFilter',
variable: {
query: 'A query',
......@@ -89,7 +83,7 @@ describe('QueryRunners', () => {
expect(values).toEqual({
series: [{ text: 'A', value: 'A' }],
state: 'Done',
timeRange: { from: {}, raw: { from: '6h', to: 'now' }, to: {} },
timeRange: undefined,
});
});
});
......
......@@ -4,7 +4,7 @@ import {
DataQuery,
DataQueryRequest,
DataSourceApi,
DefaultTimeRange,
getDefaultTimeRange,
LoadingState,
PanelData,
VariableSupportType,
......@@ -91,7 +91,7 @@ class LegacyQueryRunner implements QueryRunner {
}
const series: any = values;
return of({ series, state: LoadingState.Done, timeRange: DefaultTimeRange });
return of({ series, state: LoadingState.Done, timeRange: queryOptions.range });
})
);
}
......@@ -174,5 +174,5 @@ class DatasourceQueryRunner implements QueryRunner {
}
function getEmptyMetricFindValueObservable(): Observable<PanelData> {
return of({ state: LoadingState.Done, series: [], timeRange: DefaultTimeRange });
return of({ state: LoadingState.Done, series: [], timeRange: getDefaultTimeRange() });
}
import { of } from 'rxjs';
import { setBackendSrv } from '@grafana/runtime';
import { dateTime, DefaultTimeRange } from '@grafana/data';
import { dateTime, getDefaultTimeRange } from '@grafana/data';
import { TemplateSrv } from '../../../features/templating/template_srv';
import { CloudWatchDatasource } from './datasource';
......@@ -86,7 +86,7 @@ describe('datasource', () => {
function setup({ data = [] }: { data?: any } = {}) {
const datasource = new CloudWatchDatasource({ jsonData: { defaultRegion: 'us-west-1' } } as any, new TemplateSrv(), {
timeRange() {
return DefaultTimeRange;
return getDefaultTimeRange();
},
} as any);
const fetchMock = jest.fn().mockReturnValue(of({ data }));
......
......@@ -2,7 +2,14 @@ import { Observable } from 'rxjs';
import { QueryRunnerOptions } from 'app/features/query/state/PanelQueryRunner';
import { DashboardQuery, SHARED_DASHBODARD_QUERY } from './types';
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
import { LoadingState, DefaultTimeRange, DataQuery, PanelData, DataSourceApi, DataQueryRequest } from '@grafana/data';
import {
DataQuery,
DataQueryRequest,
DataSourceApi,
getDefaultTimeRange,
LoadingState,
PanelData,
} from '@grafana/data';
export function isSharedDashboardQuery(datasource: string | DataSourceApi | null) {
if (!datasource) {
......@@ -72,6 +79,6 @@ function getQueryError(msg: string): PanelData {
series: [],
request: {} as DataQueryRequest,
error: { message: msg },
timeRange: DefaultTimeRange,
timeRange: getDefaultTimeRange(),
};
}
import _ from 'lodash';
import {
DataSourceApi,
DataSourceInstanceSettings,
DataQueryRequest,
DataQueryResponse,
DataFrame,
ScopedVars,
DataLink,
PluginMeta,
DataQuery,
LogRowModel,
DataQueryRequest,
DataQueryResponse,
DataSourceApi,
DataSourceInstanceSettings,
DateTime,
dateTime,
Field,
getDefaultTimeRange,
LogRowModel,
MetricFindValue,
PluginMeta,
ScopedVars,
TimeRange,
DefaultTimeRange,
DateTime,
dateTime,
toUtc,
} from '@grafana/data';
import LanguageProvider from './language_provider';
import { ElasticResponse } from './elastic_response';
import { IndexPattern } from './index_pattern';
import { ElasticQueryBuilder } from './query_builder';
import { toUtc } from '@grafana/data';
import { defaultBucketAgg, hasMetricOfType } from './query_def';
import { getBackendSrv, getDataSourceSrv } from '@grafana/runtime';
import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_srv';
......@@ -142,7 +142,7 @@ export class ElasticDatasource extends DataSourceApi<ElasticsearchQuery, Elastic
*
* @param url the url to query the index on, for example `/_mapping`.
*/
private get(url: string, range = DefaultTimeRange) {
private get(url: string, range = getDefaultTimeRange()) {
const indexList = this.indexPattern.getIndexList(range.from, range.to);
if (_.isArray(indexList) && indexList.length) {
return this.requestAllIndices(indexList, url).then((results: any) => {
......@@ -667,7 +667,7 @@ export class ElasticDatasource extends DataSourceApi<ElasticsearchQuery, Elastic
});
}
getTerms(queryDef: any, range = DefaultTimeRange) {
getTerms(queryDef: any, range = getDefaultTimeRange()) {
const searchType = this.esVersion >= 5 ? 'query_then_fetch' : 'count';
const header = this.getQueryHeader(searchType, range.from, range.to);
let esQuery = JSON.stringify(this.queryBuilder.getTermsQuery(queryDef));
......@@ -706,14 +706,14 @@ export class ElasticDatasource extends DataSourceApi<ElasticsearchQuery, Elastic
const parsedQuery = JSON.parse(query);
if (query) {
if (parsedQuery.find === 'fields') {
parsedQuery.field = this.templateSrv.replace(parsedQuery.field, {}, 'lucene');
return this.getFields(query, range);
parsedQuery.type = this.templateSrv.replace(parsedQuery.type, {}, 'lucene');
return this.getFields(parsedQuery.type, range);
}
if (parsedQuery.find === 'terms') {
parsedQuery.field = this.templateSrv.replace(parsedQuery.field, {}, 'lucene');
parsedQuery.query = this.templateSrv.replace(parsedQuery.query || '*', {}, 'lucene');
return this.getTerms(query, range);
return this.getTerms(parsedQuery, range);
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment