diff --git a/public/app/plugins/datasource/loki/components/LokiExploreQueryEditor.tsx b/public/app/plugins/datasource/loki/components/LokiExploreQueryEditor.tsx index 925f2150249..76d98913690 100644 --- a/public/app/plugins/datasource/loki/components/LokiExploreQueryEditor.tsx +++ b/public/app/plugins/datasource/loki/components/LokiExploreQueryEditor.tsx @@ -11,7 +11,7 @@ import { LokiOptionFields } from './LokiOptionFields'; type Props = ExploreQueryFieldProps; export function LokiExploreQueryEditor(props: Props) { - const { query, data, datasource, history, onChange, onRunQuery } = props; + const { query, data, datasource, history, onChange, onRunQuery, range } = props; return ( ; + +const defaultProps: Props = { + datasource: { + languageProvider: { + start: () => Promise.resolve(['label1']), + fetchLabels: Promise.resolve(['label1']), + getSyntax: () => {}, + getLabelKeys: () => ['label1'], + getLabelValues: () => ['value1'], + } as any, + getInitHints: () => [], + } as any, + range: { + from: dateTime([2021, 1, 11, 12, 0, 0]), + to: dateTime([2021, 1, 11, 18, 0, 0]), + raw: { + from: 'now-1h', + to: 'now', + }, + }, + query: { expr: '', refId: '' }, + onRunQuery: () => {}, + onChange: () => {}, + history: [], +}; + +describe('LokiQueryField', () => { + it('refreshes metrics when time range changes over 1 minute', async () => { + const fetchLabelsMock = jest.fn(); + const props = defaultProps; + props.datasource.languageProvider.fetchLabels = fetchLabelsMock; + + const { rerender } = render(); + + expect(fetchLabelsMock).not.toHaveBeenCalled(); + + // 2 minutes difference over the initial time + const newRange = { + from: dateTime([2021, 1, 11, 12, 2, 0]), + to: dateTime([2021, 1, 11, 18, 2, 0]), + raw: { + from: 'now-1h', + to: 'now', + }, + }; + + rerender(); + expect(fetchLabelsMock).toHaveBeenCalledTimes(1); + }); + + it('does not refreshes metrics when time range change by less than 1 minute', async () => { + const fetchLabelsMock = jest.fn(); + const props = defaultProps; + props.datasource.languageProvider.fetchLabels = fetchLabelsMock; + + const { rerender } = render(); + + expect(fetchLabelsMock).not.toHaveBeenCalled(); + + // 20 seconds difference over the initial time + const newRange = { + from: dateTime([2021, 1, 11, 12, 0, 20]), + to: dateTime([2021, 1, 11, 18, 0, 20]), + raw: { + from: 'now-1h', + to: 'now', + }, + }; + + rerender(); + expect(fetchLabelsMock).not.toHaveBeenCalled(); + }); +}); diff --git a/public/app/plugins/datasource/loki/components/LokiQueryField.tsx b/public/app/plugins/datasource/loki/components/LokiQueryField.tsx index bc00bdc897d..02c24a42121 100644 --- a/public/app/plugins/datasource/loki/components/LokiQueryField.tsx +++ b/public/app/plugins/datasource/loki/components/LokiQueryField.tsx @@ -1,6 +1,4 @@ -// Libraries import React, { ReactNode } from 'react'; - import { SlatePrism, TypeaheadOutput, @@ -11,17 +9,13 @@ import { DOMUtil, Icon, } from '@grafana/ui'; - -// Utils & Services -// dom also includes Element polyfills import { Plugin, Node } from 'slate'; import { LokiLabelBrowser } from './LokiLabelBrowser'; - -// Types import { ExploreQueryFieldProps } from '@grafana/data'; import { LokiQuery, LokiOptions } from '../types'; import { LanguageMap, languages as prismLanguages } from 'prismjs'; import LokiLanguageProvider, { LokiHistoryItem } from '../language_provider'; +import { shouldRefreshLabels } from '../language_utils'; import LokiDatasource from '../datasource'; function getChooserText(hasSyntax: boolean, hasLogLabels: boolean) { @@ -98,6 +92,18 @@ export class LokiQueryField extends React.PureComponent { this.onChangeQuery(selector, true); this.setState({ labelBrowserVisible: false }); diff --git a/public/app/plugins/datasource/loki/components/__snapshots__/LokiExploreQueryEditor.test.tsx.snap b/public/app/plugins/datasource/loki/components/__snapshots__/LokiExploreQueryEditor.test.tsx.snap index 69927720b25..817ea043042 100644 --- a/public/app/plugins/datasource/loki/components/__snapshots__/LokiExploreQueryEditor.test.tsx.snap +++ b/public/app/plugins/datasource/loki/components/__snapshots__/LokiExploreQueryEditor.test.tsx.snap @@ -115,5 +115,15 @@ exports[`LokiExploreQueryEditor should render component 1`] = ` "refId": "A", } } + range={ + Object { + "from": "2020-01-01T00:00:00.000Z", + "raw": Object { + "from": "2020-01-01T00:00:00.000Z", + "to": "2020-01-02T00:00:00.000Z", + }, + "to": "2020-01-02T00:00:00.000Z", + } + } /> `; diff --git a/public/app/plugins/datasource/loki/language_utils.ts b/public/app/plugins/datasource/loki/language_utils.ts new file mode 100644 index 00000000000..c7c140022fa --- /dev/null +++ b/public/app/plugins/datasource/loki/language_utils.ts @@ -0,0 +1,19 @@ +import { TimeRange } from '@grafana/data'; + +function roundMsToMin(milliseconds: number): number { + return roundSecToMin(milliseconds / 1000); +} + +function roundSecToMin(seconds: number): number { + return Math.floor(seconds / 60); +} + +export function shouldRefreshLabels(range?: TimeRange, prevRange?: TimeRange): boolean { + if (range && prevRange) { + const sameMinuteFrom = roundMsToMin(range.from.valueOf()) === roundMsToMin(prevRange.from.valueOf()); + const sameMinuteTo = roundMsToMin(range.to.valueOf()) === roundMsToMin(prevRange.to.valueOf()); + // If both are same, don't need to refresh + return !(sameMinuteFrom && sameMinuteTo); + } + return false; +}