Alerting: Pass exact matchers to the backend in the state history UI (#109292)
This commit is contained in:
@@ -4,11 +4,29 @@ import { alertingApi } from './alertingApi';
|
||||
|
||||
export const stateHistoryApi = alertingApi.injectEndpoints({
|
||||
endpoints: (build) => ({
|
||||
getRuleHistory: build.query<DataFrameJSON, { ruleUid?: string; from?: number; to?: number; limit?: number }>({
|
||||
query: ({ ruleUid, from, to, limit = 100 }) => ({
|
||||
url: '/api/v1/rules/history',
|
||||
params: { ruleUID: ruleUid, from, to, limit },
|
||||
}),
|
||||
getRuleHistory: build.query<
|
||||
DataFrameJSON,
|
||||
{ ruleUid?: string; from?: number; to?: number; limit?: number; labels?: Record<string, string> }
|
||||
>({
|
||||
query: ({ ruleUid, from, to, limit = 100, labels }) => {
|
||||
const params: Record<string, string | number | undefined> = {
|
||||
ruleUID: ruleUid,
|
||||
from,
|
||||
to,
|
||||
limit,
|
||||
};
|
||||
|
||||
if (labels) {
|
||||
Object.entries(labels).forEach(([key, value]) => {
|
||||
params[`labels_${key}`] = value;
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
url: '/api/v1/rules/history',
|
||||
params,
|
||||
};
|
||||
},
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
+14
-1
@@ -29,6 +29,7 @@ import { AITriageButtonComponent } from '../../../enterprise-components/AI/AIGen
|
||||
import { usePagination } from '../../../hooks/usePagination';
|
||||
import { combineMatcherStrings } from '../../../utils/alertmanager';
|
||||
import { GRAFANA_RULES_SOURCE_NAME } from '../../../utils/datasource';
|
||||
import { parsePromQLStyleMatcherLooseSafe } from '../../../utils/matchers';
|
||||
import { createRelativeUrl } from '../../../utils/url';
|
||||
import { AlertLabels } from '../../AlertLabels';
|
||||
import { CollapseToggle } from '../../CollapseToggle';
|
||||
@@ -65,6 +66,17 @@ export const HistoryEventsList = ({
|
||||
const from = timeRange?.from.unix();
|
||||
const to = timeRange?.to.unix();
|
||||
|
||||
const labelMatchers = parsePromQLStyleMatcherLooseSafe(valueInLabelFilter.toString());
|
||||
|
||||
// Prepare labels for filtering on the backend side.
|
||||
// Backend supports only exact matchers.
|
||||
const labelFilters: Record<string, string> = {};
|
||||
labelMatchers.forEach((matcher) => {
|
||||
if (!matcher.isRegex && matcher.isEqual) {
|
||||
labelFilters[matcher.name] = matcher.value;
|
||||
}
|
||||
});
|
||||
|
||||
const {
|
||||
data: stateHistory,
|
||||
isLoading,
|
||||
@@ -74,6 +86,7 @@ export const HistoryEventsList = ({
|
||||
from: from,
|
||||
to: to,
|
||||
limit: LIMIT_EVENTS,
|
||||
labels: Object.keys(labelFilters).length > 0 ? labelFilters : undefined,
|
||||
});
|
||||
|
||||
const { historyRecords: historyRecordsNotSorted } = useRuleHistoryRecords(stateHistory, {
|
||||
@@ -102,7 +115,7 @@ export const HistoryEventsList = ({
|
||||
>
|
||||
{t(
|
||||
'alerting.central-alert-history.too-many-events.text',
|
||||
'The selected time period has too many events to display. Diplaying the latest 5000 events. Try using a shorter time period.'
|
||||
'The selected time period has too many events to display. Displaying the latest 5000 events. Try using a shorter time period.'
|
||||
)}
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
+31
@@ -4,6 +4,7 @@ import { byLabelText, byTestId } from 'testing-library-selector';
|
||||
import { getDefaultTimeRange } from '@grafana/data';
|
||||
|
||||
import { setupMswServer } from '../../../mockApi';
|
||||
import { captureRequests } from '../../../mocks/server/events';
|
||||
|
||||
import { StateFilterValues } from './CentralAlertHistoryScene';
|
||||
import { HistoryEventsList } from './EventListSceneObject';
|
||||
@@ -148,4 +149,34 @@ describe('HistoryEventsList', () => {
|
||||
});
|
||||
expect(ui.rowHeader.query()).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe('backend filtering', () => {
|
||||
it('should send only exact match filters to the backend', async () => {
|
||||
const capture = captureRequests((req) => req.url.includes('/api/v1/rules/history'));
|
||||
|
||||
render(
|
||||
<HistoryEventsList
|
||||
valueInLabelFilter={'alertname=alert1, grafana_folder=~".*folder.*", severity!=high, team="alerting"'}
|
||||
valueInStateToFilter={StateFilterValues.all}
|
||||
valueInStateFromFilter={StateFilterValues.all}
|
||||
addFilter={jest.fn()}
|
||||
timeRange={getDefaultTimeRange()}
|
||||
/>
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(ui.loadingBar.query()).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
const requests = await capture;
|
||||
expect(requests).toHaveLength(1);
|
||||
|
||||
const url = new URL(requests[0].url);
|
||||
|
||||
expect(url.searchParams.get('labels_alertname')).toBe('alert1');
|
||||
expect(url.searchParams.get('labels_team')).toBe('alerting');
|
||||
expect(url.searchParams.get('labels_grafana_folder')).toBeNull();
|
||||
expect(url.searchParams.get('labels_severity')).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -788,7 +788,7 @@
|
||||
},
|
||||
"filterBy": "Filter by:",
|
||||
"too-many-events": {
|
||||
"text": "The selected time period has too many events to display. Diplaying the latest 5000 events. Try using a shorter time period.",
|
||||
"text": "The selected time period has too many events to display. Displaying the latest 5000 events. Try using a shorter time period.",
|
||||
"title": "Unable to display all events"
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user