Skip to content

Commit

Permalink
use common component MonitoringAlertsRulesDetailsPage for alerts/rule…
Browse files Browse the repository at this point in the history
…s detail page
  • Loading branch information
vikram-raj committed Jul 27, 2020
1 parent 11c8021 commit dd80f04
Show file tree
Hide file tree
Showing 13 changed files with 111 additions and 138 deletions.
Expand Up @@ -6,7 +6,13 @@ import * as _ from 'lodash';
// @ts-ignore
import { useDispatch, connect } from 'react-redux';
import { match as RMatch } from 'react-router-dom';
import { Table, TableHeader, TableBody, SortByDirection } from '@patternfly/react-table';
import {
Table,
TableHeader,
TableBody,
SortByDirection,
TableGridBreakpoint,
} from '@patternfly/react-table';
import { FilterToolbar } from '@console/internal/components/filter-toolbar';
import { getAlertsAndRules } from '@console/internal/components/monitoring/utils';
import { monitoringSetRules, monitoringLoaded, sortList } from '@console/internal/actions/ui';
Expand Down Expand Up @@ -67,7 +73,7 @@ export const MonitoringAlerts: React.FC<props> = ({ match, rules, filters, listS

React.useEffect(() => {
const sortThanosRules = _.sortBy(thanosAlertsAndRules.rules, alertingRuleStateOrder);
dispatch(monitoringSetRules('devRules', sortThanosRules));
dispatch(monitoringSetRules('devRules', sortThanosRules, 'dev'));
dispatch(monitoringLoaded('devAlerts', thanosAlertsAndRules.alerts, 'dev'));
}, [dispatch, thanosAlertsAndRules]);

Expand Down Expand Up @@ -134,6 +140,7 @@ export const MonitoringAlerts: React.FC<props> = ({ match, rules, filters, listS
cells={monitoringAlertColumn}
sortBy={sortBy}
onSort={handleSort}
gridBreakPoint={TableGridBreakpoint.gridXl}
>
<TableHeader />
<TableBody />
Expand Down
Expand Up @@ -7,7 +7,10 @@ import { useDispatch } from 'react-redux';
import { history, StatusBox, LoadingBox } from '@console/internal/components/utils';
import { ALL_NAMESPACES_KEY } from '@console/shared';
import NamespacedPage, { NamespacedPageVariants } from '../../NamespacedPage';
import { AlertsDetailsPage } from '@console/internal/components/monitoring/alerting';
import {
AlertsDetailsPage,
AlertRulesDetailsPage,
} from '@console/internal/components/monitoring/alerting';
import { PrometheusRulesResponse } from '@console/internal/components/monitoring/types';
import { useURLPoll } from '@console/internal/components/utils/url-poll-hook';
import { PROMETHEUS_TENANCY_BASE_PATH } from '@console/internal/components/graphs';
Expand All @@ -23,6 +26,8 @@ interface MonitoringAlertsDetailsPageProps {
}

const POLL_DELAY = 15 * 1000;
const ALERT_DETAILS_PATH = '/dev-monitoring/ns/:ns/alerts/:ruleID';
const RULE_DETAILS_PATH = '/dev-monitoring/ns/:ns/rules/:id';

const handleNamespaceChange = (newNamespace: string): void => {
if (newNamespace === ALL_NAMESPACES_KEY) {
Expand All @@ -34,6 +39,7 @@ const handleNamespaceChange = (newNamespace: string): void => {

const MonitoringAlertsDetailsPage: React.FC<MonitoringAlertsDetailsPageProps> = ({ match }) => {
const namespace = match.params.ns;
const { path } = match;
const dispatch = useDispatch();
const [response, loadError, loading] = useURLPoll<PrometheusRulesResponse>(
`${PROMETHEUS_TENANCY_BASE_PATH}/api/v1/rules?namespace=${namespace}`,
Expand All @@ -46,10 +52,8 @@ const MonitoringAlertsDetailsPage: React.FC<MonitoringAlertsDetailsPageProps> =
);

React.useEffect(() => {
const sortThanosRules = _.sortBy(thanosAlertsAndRules.rules, (rule) =>
alertingRuleStateOrder(rule),
);
dispatch(monitoringSetRules('devRules', sortThanosRules));
const sortThanosRules = _.sortBy(thanosAlertsAndRules.rules, alertingRuleStateOrder);
dispatch(monitoringSetRules('devRules', sortThanosRules, 'dev'));
dispatch(monitoringLoaded('devAlerts', thanosAlertsAndRules.alerts, 'dev'));
}, [dispatch, thanosAlertsAndRules]);

Expand All @@ -67,7 +71,8 @@ const MonitoringAlertsDetailsPage: React.FC<MonitoringAlertsDetailsPageProps> =
hideApplications
onNamespaceChange={handleNamespaceChange}
>
<AlertsDetailsPage match={match} />
{path === ALERT_DETAILS_PATH && <AlertsDetailsPage match={match} />}
{path === RULE_DETAILS_PATH && <AlertRulesDetailsPage match={match} />}
</NamespacedPage>
);
};
Expand Down

This file was deleted.

This file was deleted.

Expand Up @@ -4,42 +4,46 @@ import { Switch } from '@patternfly/react-core';
import { Rule } from '@console/internal/components/monitoring/types';
import { RuleStates } from '@console/internal/reducers/monitoring';
import { StateTimestamp } from '@console/internal/components/monitoring/alerting';
import { coFetchJSON } from '@console/internal/co-fetch';
import SilenceDurationDropDown from './SilenceDurationDropdown';
import './SilenceAlert.scss';

type SilenceAlertProps = {
rule: Rule;
namespace: string;
};

const { alertManagerBaseURL } = window.SERVER_FLAGS;

const SilenceUntil = ({ rule }) => {
if (alert && !_.isEmpty(rule.silencedBy)) {
if (!_.isEmpty(rule.silencedBy)) {
return <StateTimestamp text="Until" timestamp={_.max(_.map(rule.silencedBy, 'endsAt'))} />;
}
return null;
};

const SilenceAlert: React.FC<SilenceAlertProps> = ({ rule, namespace }) => {
const [isChecked, setIsChecked] = React.useState(true);
React.useEffect(
() => (rule.state === RuleStates.Silenced ? setIsChecked(false) : setIsChecked(true)),
[rule],
);
const SilenceAlert: React.FC<SilenceAlertProps> = ({ rule }) => {
const [isChecked, setIsChecked] = React.useState(rule.state !== RuleStates.Silenced);
const [ruleState] = React.useState(rule);
React.useEffect(() => setIsChecked(ruleState.state !== RuleStates.Silenced), [ruleState]);

const handleChange = (checked: boolean) => {
if (checked) {
_.each(rule.silencedBy, (silence) => {
coFetchJSON.delete(`${alertManagerBaseURL}/api/v2/silence/${silence.id}`);
});
}
setIsChecked(checked);
};

return (
<Switch
aria-label="Silence switch"
className="odc-silence-alert"
label="On"
label={null}
labelOff={
rule.state === RuleStates.Silenced ? (
<SilenceUntil rule={rule} />
) : (
<SilenceDurationDropDown rule={rule} namespace={namespace} />
<SilenceDurationDropDown rule={rule} />
)
}
isChecked={isChecked}
Expand Down
Expand Up @@ -12,51 +12,58 @@ import { Rule } from '@console/internal/components/monitoring/types';

type SilenceDurationDropDownProps = {
rule: Rule;
namespace: string;
};

const SILENCE_FOR = 'Silence for ';
const durations = [SILENCE_FOR, '30m', '1h', '2h', '6h', '12h', '1d', '2d', '1w'];
const durationItems = _.zipObject(durations, durations);
const durations = {
silenceFor: 'Silence for',
'30m': '30 minutes',
'1h': '1 hour',
'2h': '2 hours',
'1d': '1 day',
};

const { alertManagerBaseURL } = window.SERVER_FLAGS;

const SilenceDurationDropDown: React.FC<SilenceDurationDropDownProps> = ({ rule, namespace }) => {
const SilenceDurationDropDown: React.FC<SilenceDurationDropDownProps> = ({ rule }) => {
const createdBy = useSelector((state: RootState) => state.UI.get('user')?.metadata?.name);
const ruleLabelKeys = _.keys(rule?.labels);
const ruleLabelValues = _.values(rule?.labels);
const ruleMatchers = _.zipWith(ruleLabelKeys, ruleLabelValues, (key, value) => {
return { name: key, value, isRegex: false };
});

const matchers = [
{
isRegex: false,
name: 'alertname',
value: rule.name,
},
{
isRegex: false,
name: 'namespace',
value: namespace,
},
...ruleMatchers,
];

const setDuration = (duration: string) => {
const startsAt = new Date();
const endsAt = new Date(startsAt.getTime() + parsePrometheusDuration(duration));
if (duration !== 'silenceFor') {
const startsAt = new Date();
const endsAt = new Date(startsAt.getTime() + parsePrometheusDuration(duration));

const payload = {
createdBy,
endsAt: endsAt.toISOString(),
startsAt: startsAt.toISOString(),
matchers,
comment: '',
};
const payload = {
createdBy,
endsAt: endsAt.toISOString(),
startsAt: startsAt.toISOString(),
matchers,
comment: '',
};

coFetchJSON.post(`${alertManagerBaseURL}/api/v2/silences`, payload);
coFetchJSON.post(`${alertManagerBaseURL}/api/v2/silences`, payload);
}
};

return (
<Dropdown
dropDownClassName="dropdown--full-width"
items={durationItems}
items={durations}
onChange={(v: string) => setDuration(v)}
selectedKey={SILENCE_FOR}
selectedKey={'silenceFor'}
/>
);
};
Expand Down
Expand Up @@ -6,12 +6,12 @@ import { RuleStates } from '@console/internal/reducers/monitoring';
describe('monitoring-alerts-utils', () => {
it('row should be expanded if rule state is FIRING', () => {
const alertRules = getAlertsAndRules(rules?.data).rules;
const rows = monitoringAlertRows(alertRules, ['KubeNodeReadinessFlapping'], 'ns');
const rows = monitoringAlertRows(alertRules, [alertRules[1].id], 'ns');
expect(rows[0].isOpen).toBe(true);
});
it('row should be collapsed if rule state is FIRING but collapsed by user', () => {
const alertRules = getAlertsAndRules(rules?.data).rules;
const rows = monitoringAlertRows(alertRules, ['KubeNodeNotReady'], 'ns');
const rows = monitoringAlertRows(alertRules, [alertRules[0].id], 'ns');
expect(rows[0].isOpen).toBe(false);
});
it('row should be collapse if rule state is not FIRING', () => {
Expand Down
Expand Up @@ -62,7 +62,12 @@ export const monitoringAlertColumn: MonitoringAlertColumn[] = [
fieldName: 'alertState',
sortFunc: 'alertingRuleStateOrder',
},
{ title: 'Notifications', transforms: [cellWidth(20)] },
{
title: 'Notifications',
transforms: [sortable, cellWidth(30)],
fieldName: 'notifications',
sortFunc: 'alertingRuleNotificationsOrder',
},
{ title: '' },
];

Expand All @@ -76,8 +81,8 @@ export const monitoringAlertRows = (
rows.push({
...(rls.state !== RuleStates.Inactive && {
isOpen:
(rls.state === RuleStates.Firing && !_.includes(collapsedRowsIds, rls.name)) ||
(rls.state !== RuleStates.Firing && _.includes(collapsedRowsIds, rls.name)),
(rls.state === RuleStates.Firing && !_.includes(collapsedRowsIds, rls.id)) ||
(rls.state !== RuleStates.Firing && _.includes(collapsedRowsIds, rls.id)),
}),
cells: [
{
Expand All @@ -89,7 +94,7 @@ export const monitoringAlertRows = (
<YellowExclamationTriangleIcon /> {rls.name}
</>
),
id: rls.name,
id: rls.id,
},
{
title: <Severity severity={rls.labels?.severity} />,
Expand All @@ -98,7 +103,7 @@ export const monitoringAlertRows = (
title: _.isEmpty(rls.alerts) ? 'Not Firing' : <StateCounts alerts={rls.alerts} />,
},
{
title: <SilenceAlert rule={rls} namespace={namespace} />,
title: <SilenceAlert rule={rls} />,
},
{
title: (
Expand All @@ -111,7 +116,7 @@ export const monitoringAlertRows = (
});
_.forEach(rls.alerts, (alert: Alert) => {
rows.push({
parent: _.findIndex(rows, (r) => r.cells[0].id === rls.name),
parent: _.findIndex(rows, (r) => r.cells[0].id === rls.id),
fullWidth: true,
cells: [
{
Expand Down Expand Up @@ -146,7 +151,7 @@ export const alertFilters = [
filterGroupName: 'Alert State',
type: 'alert-state',
reducer: alertState,
items: alertsRowFilters[0].items,
items: [...alertsRowFilters[0].items, ...[{ id: 'inactive', title: 'Not Firing' }]],
},
severityRowFilter,
];
Expand All @@ -155,10 +160,16 @@ const setOrderBy = (orderBy: SortByDirection, data: Rule[]): Rule[] => {
return orderBy === SortByDirection.asc ? data : data.reverse();
};

const alertingRuleNotificationsOrder = (rule: Rule) => [
rule.state === RuleStates.Silenced ? 1 : 0,
rule.state,
];

const sortFunc = {
nameOrder: (rule) => rule.name,
alertSeverityOrder,
alertingRuleStateOrder,
alertingRuleNotificationsOrder,
};

export const applyListSort = (rules: Rule[], orderBy: SortByDirection, func: string): Rule[] => {
Expand Down
4 changes: 2 additions & 2 deletions frontend/packages/dev-console/src/plugin.tsx
Expand Up @@ -805,7 +805,7 @@ const plugin: Plugin<ConsumedExtensions> = [
loader: async () =>
(
await import(
'./components/monitoring/alerts/MonitoringAlertsDetailsPage' /* webpackChunkName: "dev-console-monitoring-alerts" */
'./components/monitoring/alerts/MonitoringAlertsRulesDetailsPage' /* webpackChunkName: "dev-console-monitoring-alerts" */
)
).default,
},
Expand All @@ -818,7 +818,7 @@ const plugin: Plugin<ConsumedExtensions> = [
loader: async () =>
(
await import(
'./components/monitoring/alerts/MonitoringRuleDetailsPage' /* webpackChunkName: "dev-console-monitoring-rules" */
'./components/monitoring/alerts/MonitoringAlertsRulesDetailsPage' /* webpackChunkName: "dev-console-monitoring-rules" */
)
).default,
},
Expand Down
7 changes: 5 additions & 2 deletions frontend/public/actions/ui.ts
Expand Up @@ -336,8 +336,11 @@ export const monitoringErrored = (
key,
data: { loaded: true, loadError, data: null, perspective },
});
export const monitoringSetRules = (key: 'rules' | 'devRules', rules: Rule[]) =>
action(ActionType.MonitoringSetRules, { key, data: rules });
export const monitoringSetRules = (
key: 'rules' | 'devRules',
rules: Rule[],
perspective = 'admin',
) => action(ActionType.MonitoringSetRules, { key, data: rules, perspective });
export const monitoringToggleGraphs = () => action(ActionType.ToggleMonitoringGraphs);
export const notificationDrawerToggleExpanded = () =>
action(ActionType.NotificationDrawerToggleExpanded);
Expand Down

0 comments on commit dd80f04

Please sign in to comment.