Prometheus: Remove running of duplicated metrics query (#30108)

* Remove metrics rerenders

* Refactor

* Update public/app/plugins/datasource/prometheus/components/PromQueryField.tsx

Co-authored-by: Zoltán Bedi <zoltan.bedi@gmail.com>

* Update public/app/plugins/datasource/prometheus/language_utils.ts

Co-authored-by: Zoltán Bedi <zoltan.bedi@gmail.com>

* Add test

* Update public/app/plugins/datasource/prometheus/components/PromQueryField.test.tsx

Co-authored-by: Zoltán Bedi <zoltan.bedi@gmail.com>
This commit is contained in:
Ivana Huckova
2021-01-08 19:19:00 +01:00
committed by GitHub
parent ae1d2fb505
commit 8ad79a2635
4 changed files with 88 additions and 20 deletions

View File

@@ -94,6 +94,55 @@ describe('PromQueryField', () => {
checkMetricsInCascader(await screen.findByRole('button'), changedMetrics);
});
it('does not refreshes metrics when after rounding to minute time range does not change', async () => {
const defaultProps = {
query: { expr: '', refId: '' },
onRunQuery: () => {},
onChange: () => {},
history: [],
};
const metrics = ['foo', 'bar'];
const changedMetrics = ['foo', 'baz'];
const range = {
from: dateTime('2020-10-28T00:00:00Z'),
to: dateTime('2020-10-28T01:00:00Z'),
};
const languageProvider = makeLanguageProvider({ metrics: [metrics, changedMetrics] });
const queryField = render(
<PromQueryField
// @ts-ignore
datasource={{ languageProvider }}
range={{
...range,
raw: range,
}}
{...defaultProps}
/>
);
checkMetricsInCascader(await screen.findByRole('button'), metrics);
const newRange = {
from: dateTime('2020-10-28T00:00:01Z'),
to: dateTime('2020-10-28T01:00:01Z'),
};
queryField.rerender(
<PromQueryField
// @ts-ignore
datasource={{ languageProvider }}
range={{
...newRange,
raw: newRange,
}}
{...defaultProps}
/>
);
let cascader = screen.getByRole('button');
// Should not show loading
expect(cascader.textContent).toContain('Metrics');
checkMetricsInCascader(await screen.findByRole('button'), metrics);
});
it('refreshes metrics when time range changes but dont show loading state', async () => {
const defaultProps = {
query: { expr: '', refId: '' },

View File

@@ -16,8 +16,16 @@ import { LanguageMap, languages as prismLanguages } from 'prismjs';
// dom also includes Element polyfills
import { PromQuery, PromOptions, PromMetricsMetadata } from '../types';
import { roundMsToMin } from '../language_utils';
import { CancelablePromise, makePromiseCancelable } from 'app/core/utils/CancelablePromise';
import { ExploreQueryFieldProps, QueryHint, isDataFrame, toLegacyResponseData, HistoryItem } from '@grafana/data';
import {
ExploreQueryFieldProps,
QueryHint,
isDataFrame,
toLegacyResponseData,
HistoryItem,
TimeRange,
} from '@grafana/data';
import { DOMUtil, SuggestionsState } from '@grafana/ui';
import { PrometheusDatasource } from '../datasource';
@@ -168,17 +176,6 @@ class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryF
range,
} = this.props;
const rangeChanged =
range &&
prevProps.range &&
!_.isEqual(
{ from: range.from.valueOf(), to: range.to.valueOf() },
{
from: prevProps.range.from.valueOf(),
to: prevProps.range.to.valueOf(),
}
);
if (languageProvider !== prevProps.datasource.languageProvider) {
// We reset this only on DS change so we do not flesh loading state on every rangeChange which happens on every
// query run if using relative range.
@@ -188,7 +185,9 @@ class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryF
});
}
if (languageProvider !== prevProps.datasource.languageProvider || rangeChanged) {
const changedRangeToRefresh = this.rangeChangedToRefresh(range, prevProps.range);
// We want to refresh metrics when language provider changes and/or when range changes (we round up intervals to a minute)
if (languageProvider !== prevProps.datasource.languageProvider || changedRangeToRefresh) {
this.refreshMetrics();
}
@@ -237,6 +236,16 @@ class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryF
}
};
rangeChangedToRefresh(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;
}
onChangeMetrics = (values: string[], selectedOptions: CascaderOption[]) => {
let query;
if (selectedOptions.length === 1) {