mirror of
https://github.com/grafana/grafana.git
synced 2024-11-25 18:30:41 -06:00
Alerting: Add label filters to the logic of showing hidden instances (#65674)
* Add label filters to the logic of showing hidden instances Co-authored-by: Virginia Cepeda <virginia.cepeda@grafana.com> * Add tests Co-Authored-By: Sonia Aguilar <33540275+soniaAguilarPeiron@users.noreply.github.com> --------- Co-authored-by: Virginia Cepeda <virginia.cepeda@grafana.com>
This commit is contained in:
parent
96453c6e69
commit
008bf143ac
@ -35,6 +35,7 @@ import {
|
||||
} from 'app/types/unified-alerting';
|
||||
import {
|
||||
AlertQuery,
|
||||
GrafanaAlertState,
|
||||
GrafanaAlertStateDecision,
|
||||
GrafanaRuleDefinition,
|
||||
PromAlertingRuleState,
|
||||
@ -630,3 +631,7 @@ export function getCloudRule(override?: Partial<CombinedRule>) {
|
||||
...override,
|
||||
});
|
||||
}
|
||||
|
||||
export function mockAlertWithState(state: GrafanaAlertState, labels?: {}): Alert {
|
||||
return { activeAt: '', annotations: {}, labels: labels || {}, state: state, value: '' };
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ import alertDef from 'app/features/alerting/state/alertDef';
|
||||
import { useCombinedRuleNamespaces } from 'app/features/alerting/unified/hooks/useCombinedRuleNamespaces';
|
||||
import { useUnifiedAlertingSelector } from 'app/features/alerting/unified/hooks/useUnifiedAlertingSelector';
|
||||
import { fetchAllPromAndRulerRulesAction } from 'app/features/alerting/unified/state/actions';
|
||||
import { labelsMatchMatchers, parseMatchers } from 'app/features/alerting/unified/utils/alertmanager';
|
||||
import { Annotation } from 'app/features/alerting/unified/utils/constants';
|
||||
import {
|
||||
getAllRulesSourceNames,
|
||||
@ -190,22 +189,6 @@ function filterRules(props: PanelProps<UnifiedAlertListOptions>, rules: Combined
|
||||
);
|
||||
});
|
||||
|
||||
if (options.alertInstanceLabelFilter) {
|
||||
const replacedLabelFilter = replaceVariables(options.alertInstanceLabelFilter);
|
||||
const matchers = parseMatchers(replacedLabelFilter);
|
||||
|
||||
// Reduce rules and instances to only those that match
|
||||
filteredRules = filteredRules.reduce<CombinedRuleWithLocation[]>((rules, rule) => {
|
||||
const alertingRule = getAlertingRule(rule);
|
||||
const filteredAlerts = (alertingRule?.alerts ?? []).filter(({ labels }) => labelsMatchMatchers(labels, matchers));
|
||||
if (filteredAlerts.length) {
|
||||
const alertRule: AlertingRule | null = getAlertingRule(rule);
|
||||
alertRule && rules.push({ ...rule, promRule: { ...alertRule, alerts: filteredAlerts } });
|
||||
}
|
||||
return rules;
|
||||
}, []);
|
||||
}
|
||||
|
||||
if (options.folder) {
|
||||
filteredRules = filteredRules.filter((rule) => {
|
||||
return rule.namespaceName === options.folder.title;
|
||||
|
73
public/app/plugins/panel/alertlist/util.test.tsx
Normal file
73
public/app/plugins/panel/alertlist/util.test.tsx
Normal file
@ -0,0 +1,73 @@
|
||||
import { mockAlertWithState as withState } from 'app/features/alerting/unified/mocks';
|
||||
import { Alert } from 'app/types/unified-alerting';
|
||||
import { GrafanaAlertState } from 'app/types/unified-alerting-dto';
|
||||
|
||||
import { GroupMode, SortOrder, UnifiedAlertListOptions, ViewMode } from './types';
|
||||
import { filterAlerts } from './util';
|
||||
|
||||
const defaultOption: UnifiedAlertListOptions = {
|
||||
maxItems: 2,
|
||||
sortOrder: SortOrder.AlphaAsc,
|
||||
dashboardAlerts: true,
|
||||
groupMode: GroupMode.Default,
|
||||
groupBy: [''],
|
||||
alertName: 'test',
|
||||
showInstances: false,
|
||||
folder: { id: 1, title: 'test folder' },
|
||||
stateFilter: { firing: true, pending: true, noData: true, normal: true, error: true },
|
||||
alertInstanceLabelFilter: '',
|
||||
datasource: 'Alertmanager',
|
||||
viewMode: ViewMode.List,
|
||||
};
|
||||
|
||||
const alerts: Alert[] = [
|
||||
withState(GrafanaAlertState.Pending, { severity: 'critical' }),
|
||||
withState(GrafanaAlertState.Error, { severity: 'low' }),
|
||||
withState(GrafanaAlertState.Error, { region: 'asia' }),
|
||||
withState(GrafanaAlertState.Normal),
|
||||
];
|
||||
|
||||
describe('filterAlerts', () => {
|
||||
it('Returns all alert instances when there are no filters', () => {
|
||||
const result = filterAlerts(defaultOption, alerts);
|
||||
|
||||
expect(result.length).toBe(4);
|
||||
});
|
||||
|
||||
it('Filters by alert instance state ', () => {
|
||||
const noNormalStateOptions = {
|
||||
...defaultOption,
|
||||
...{ stateFilter: { firing: true, pending: true, noData: true, normal: false, error: true } },
|
||||
};
|
||||
|
||||
expect(filterAlerts(noNormalStateOptions, alerts).length).toBe(3);
|
||||
|
||||
const noErrorOrNormalStateOptions = {
|
||||
...defaultOption,
|
||||
...{ stateFilter: { firing: true, pending: true, noData: true, normal: false, error: false } },
|
||||
};
|
||||
|
||||
expect(filterAlerts(noErrorOrNormalStateOptions, alerts).length).toBe(1);
|
||||
});
|
||||
|
||||
it('Filters by alert instance label', () => {
|
||||
const options = {
|
||||
...defaultOption,
|
||||
...{ alertInstanceLabelFilter: '{severity=low}' },
|
||||
};
|
||||
const result = filterAlerts(options, alerts);
|
||||
|
||||
expect(result.length).toBe(1);
|
||||
});
|
||||
|
||||
it('Filters by alert instance state and label', () => {
|
||||
const options = {
|
||||
...defaultOption,
|
||||
...{ stateFilter: { firing: false, pending: false, noData: false, normal: false, error: true } },
|
||||
...{ alertInstanceLabelFilter: '{severity=low}' },
|
||||
};
|
||||
const result = filterAlerts(options, alerts);
|
||||
|
||||
expect(result.length).toBe(1);
|
||||
});
|
||||
});
|
@ -1,13 +1,21 @@
|
||||
import { isEmpty } from 'lodash';
|
||||
|
||||
import { PanelProps } from '@grafana/data';
|
||||
import { Labels, PanelProps } from '@grafana/data';
|
||||
import { labelsMatchMatchers, parseMatchers } from 'app/features/alerting/unified/utils/alertmanager';
|
||||
import { replaceVariables } from 'app/plugins/datasource/prometheus/querybuilder/shared/parsingUtils';
|
||||
import { Alert, hasAlertState } from 'app/types/unified-alerting';
|
||||
import { GrafanaAlertState, PromAlertingRuleState } from 'app/types/unified-alerting-dto';
|
||||
|
||||
import { UnifiedAlertListOptions } from './types';
|
||||
|
||||
function hasLabelFilter(alertInstanceLabelFilter: string, labels: Labels) {
|
||||
const replacedLabelFilter = replaceVariables(alertInstanceLabelFilter);
|
||||
const matchers = parseMatchers(replacedLabelFilter);
|
||||
return labelsMatchMatchers(labels, matchers);
|
||||
}
|
||||
|
||||
export function filterAlerts(options: PanelProps<UnifiedAlertListOptions>['options'], alerts: Alert[]): Alert[] {
|
||||
const { stateFilter } = options;
|
||||
const { stateFilter, alertInstanceLabelFilter } = options;
|
||||
|
||||
if (isEmpty(stateFilter)) {
|
||||
return alerts;
|
||||
@ -15,14 +23,16 @@ export function filterAlerts(options: PanelProps<UnifiedAlertListOptions>['optio
|
||||
|
||||
return alerts.filter((alert) => {
|
||||
return (
|
||||
(stateFilter.firing &&
|
||||
((stateFilter.firing &&
|
||||
(hasAlertState(alert, GrafanaAlertState.Alerting) || hasAlertState(alert, PromAlertingRuleState.Firing))) ||
|
||||
(stateFilter.pending &&
|
||||
(hasAlertState(alert, GrafanaAlertState.Pending) || hasAlertState(alert, PromAlertingRuleState.Pending))) ||
|
||||
(stateFilter.noData && hasAlertState(alert, GrafanaAlertState.NoData)) ||
|
||||
(stateFilter.normal && hasAlertState(alert, GrafanaAlertState.Normal)) ||
|
||||
(stateFilter.error && hasAlertState(alert, GrafanaAlertState.Error)) ||
|
||||
(stateFilter.inactive && hasAlertState(alert, PromAlertingRuleState.Inactive))
|
||||
(stateFilter.pending &&
|
||||
(hasAlertState(alert, GrafanaAlertState.Pending) || hasAlertState(alert, PromAlertingRuleState.Pending))) ||
|
||||
(stateFilter.noData && hasAlertState(alert, GrafanaAlertState.NoData)) ||
|
||||
(stateFilter.normal && hasAlertState(alert, GrafanaAlertState.Normal)) ||
|
||||
(stateFilter.error && hasAlertState(alert, GrafanaAlertState.Error)) ||
|
||||
(stateFilter.inactive && hasAlertState(alert, PromAlertingRuleState.Inactive))) &&
|
||||
((alertInstanceLabelFilter && hasLabelFilter(options.alertInstanceLabelFilter, alert.labels)) ||
|
||||
!alertInstanceLabelFilter)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user