diff --git a/public/app/plugins/datasource/loki/components/LokiQueryEditor.tsx b/public/app/plugins/datasource/loki/components/LokiQueryEditor.tsx index bd248c76a60..7631ac690a9 100644 --- a/public/app/plugins/datasource/loki/components/LokiQueryEditor.tsx +++ b/public/app/plugins/datasource/loki/components/LokiQueryEditor.tsx @@ -1,5 +1,5 @@ import { isEqual } from 'lodash'; -import React, { SyntheticEvent, useCallback, useEffect, useState } from 'react'; +import React, { SyntheticEvent, useCallback, useEffect, useId, useState } from 'react'; import { usePrevious } from 'react-use'; import { CoreApp, LoadingState } from '@grafana/data'; @@ -29,6 +29,7 @@ export const testIds = { }; export const LokiQueryEditor = React.memo((props) => { + const id = useId(); const { onChange, onRunQuery, onAddQuery, data, app, queries, datasource, range: timeRange } = props; const [parseModalOpen, setParseModalOpen] = useState(false); const [queryPatternsModalOpen, setQueryPatternsModalOpen] = useState(false); @@ -106,12 +107,13 @@ export const LokiQueryEditor = React.memo((props) => { ); if (shouldUpdate && timeRange) { const makeAsyncRequest = async () => { - const stats = await datasource.getStats(query, timeRange); + // overwriting the refId that is later used to cancel inflight queries with the same ID. + const stats = await datasource.getStats({ ...query, refId: `${id}_${query.refId}` }, timeRange); setQueryStats(stats); }; makeAsyncRequest(); } - }, [datasource, timeRange, previousTimeRange, query, previousQueryExpr, previousQueryType, setQueryStats]); + }, [datasource, timeRange, previousTimeRange, query, previousQueryExpr, previousQueryType, setQueryStats, id]); return ( <> diff --git a/public/app/plugins/datasource/loki/datasource.test.ts b/public/app/plugins/datasource/loki/datasource.test.ts index 01027706bae..47a2dbf8606 100644 --- a/public/app/plugins/datasource/loki/datasource.test.ts +++ b/public/app/plugins/datasource/loki/datasource.test.ts @@ -1592,6 +1592,21 @@ describe('LokiDatasource', () => { expect(ds.statsMetadataRequest).toHaveBeenCalled(); expect(result).toEqual({ streams: 2, chunks: 2, bytes: 2, entries: 2 }); }); + + it('calls statsMetadataRequest with the right properties', async () => { + query.expr = 'count_over_time({foo="bar"}[1m])'; + await ds.getQueryStats(query, mockTimeRange); + + expect(ds.statsMetadataRequest).toHaveBeenCalledWith( + `index/stats`, + { + start: 0, + end: 1000000, + query: '{foo="bar"}', + }, + { requestId: 'log-stats-A', showErrorAlert: false } + ); + }); }); describe('statsMetadataRequest', () => { diff --git a/public/app/plugins/datasource/loki/datasource.ts b/public/app/plugins/datasource/loki/datasource.ts index 05cf21c475e..664f0014a1f 100644 --- a/public/app/plugins/datasource/loki/datasource.ts +++ b/public/app/plugins/datasource/loki/datasource.ts @@ -108,6 +108,8 @@ export const REF_ID_STARTER_ANNOTATION = 'annotation-'; export const REF_ID_STARTER_LOG_ROW_CONTEXT = 'log-row-context-query-'; export const REF_ID_STARTER_LOG_VOLUME = 'log-volume-'; export const REF_ID_STARTER_LOG_SAMPLE = 'log-sample-'; +export const REF_ID_STARTER_STATS = 'log-stats-'; + const NS_IN_MS = 1000000; export function makeRequest( @@ -560,7 +562,7 @@ export class LokiDatasource start: start, end: end, }, - { showErrorAlert: false } + { showErrorAlert: false, requestId: `${REF_ID_STARTER_STATS}${query.refId}` } ); statsForAll = {