Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug 1870474: Show monitoring alert decorator for alerts that are warning/error #6209

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -1,9 +1,5 @@
import * as React from 'react';
import {
ExclamationTriangleIcon,
ExclamationCircleIcon,
InfoCircleIcon,
} from '@patternfly/react-icons';
import { ExclamationTriangleIcon, ExclamationCircleIcon } from '@patternfly/react-icons';
import { AlertSeverity } from '@console/internal/components/monitoring/types';

interface AlertSeverityIconProps {
Expand Down Expand Up @@ -37,15 +33,7 @@ const AlertSeverityIcon: React.FC<AlertSeverityIconProps> = ({
/>
);
default:
return (
<InfoCircleIcon
style={{
fontSize,
color: 'var(--pf-global--info-color--100)',
}}
alt="Monitoring Alert"
/>
);
return null;
}
};

Expand Down
Expand Up @@ -123,6 +123,154 @@ export const mockAlerts: Alerts = {
],
};

export const mockAlerts2: Alert[] = [
{
labels: {
alertname: 'KubeNodeNotReady',
severity: 'info',
endpoint: 'web',
instance: '10.131.0.35:8080',
job: 'prometheus-example-app',
namespace: 'ns1',
pod: 'prometheus-example-pod',
prometheus: 'openshift-user-workload-monitoring/user-workload',
service: 'prometheus-example-app',
version: 'v0.1.0',
},
annotations: {
message:
'Alerts are not configured to be sent to a notification system, meaning that you may not be notified in a timely fashion when important failures occur. Check the OpenShift documentation to learn how to configure notifications with Alertmanager.',
},
state: AlertStates.Firing,
activeAt: '2020-06-09T04:06:36.662770393Z',
value: 0,
rule: {
labels: {},
alerts: [],
annotations: {},
duration: 12,
id: '778oioioi',
name: 'xyz',
query: 'query1',
state: RuleStates.Firing,
type: 'type-1',
},
},
{
labels: {
alertname: 'KubeNodeNotReady',
severity: 'none',
endpoint: 'web',
instance: '10.131.0.35:8080',
job: 'prometheus-example-app',
namespace: 'ns1',
pod: 'prometheus-example-pod',
prometheus: 'openshift-user-workload-monitoring/user-workload',
service: 'prometheus-example-app',
version: 'v0.1.0',
},
annotations: {
message:
'Alerts are not configured to be sent to a notification system, meaning that you may not be notified in a timely fashion when important failures occur. Check the OpenShift documentation to learn how to configure notifications with Alertmanager.',
},
state: AlertStates.Firing,
activeAt: '2020-06-09T04:06:36.662770393Z',
value: 0,
rule: {
labels: {},
alerts: [],
annotations: {},
duration: 12,
id: '778oioioi',
name: 'xyz',
query: 'query1',
state: RuleStates.Firing,
type: 'type-1',
},
},
];

export const expectedFiringAlerts: Alert[] = [
{
labels: {
alertname: 'KubeNodeNotReady',
severity: 'warning',
endpoint: 'web',
instance: '10.131.0.35:8080',
job: 'prometheus-example-app',
namespace: 'ns1',
pod: 'prometheus-example-pod',
prometheus: 'openshift-user-workload-monitoring/user-workload',
service: 'prometheus-example-app',
version: 'v0.1.0',
},
annotations: {
message:
'Alerts are not configured to be sent to a notification system, meaning that you may not be notified in a timely fashion when important failures occur. Check the OpenShift documentation to learn how to configure notifications with Alertmanager.',
},
state: AlertStates.Firing,
activeAt: '2020-06-09T04:06:36.662770393Z',
value: 0,
rule: {
labels: {},
alerts: [],
annotations: {},
duration: 12,
id: '778oioioi',
name: 'xyz',
query: 'query1',
state: RuleStates.Firing,
type: 'type-1',
},
},
{
rule: {
state: RuleStates.Pending,
name: 'AlertmanagerReceiversNotConfigured',
query: 'cluster:alertmanager_routing_enabled:max == 0',
duration: 600,
labels: { prometheus: 'openshift-monitoring/k8s', severity: 'warning' },
annotations: {
message:
'Alerts are not configured to be sent to a notifica…how to configure notifications with Alertmanager.',
},
alerts: [],
id: '542717799',
type: 'type-2',
},
labels: { alertname: 'AlertmanagerReceiversNotConfigured', severity: 'warning' },
annotations: {
message:
'Alerts are not configured to be sent to a notifica…how to configure notifications with Alertmanager.',
},
state: AlertStates.Firing,
activeAt: '2020-07-15T06:36:06.662770393Z',
value: 132,
},
{
rule: {
state: RuleStates.Firing,
name: 'WatchDog',
query: 'vector(1)',
duration: 600,
labels: { prometheus: 'openshift-monitoring/k8s', severity: 'none' },
annotations: {
message: 'This alert is meant to ensure that entire pipeline is functional.',
},
alerts: [],
id: '542717499',
type: 'type-3',
},
labels: { alertname: 'WatchDog', severity: 'none' },
annotations: {
message: 'This alert is meant to ensure that entire pipeline is functional.',
},
state: AlertStates.Firing,
activeAt: '2020-07-15T06:36:06.662770393Z',
value: 12,
},
];

export const expectedSortedAlerts: Alert[] = [
{
labels: {
Expand Down
@@ -0,0 +1,28 @@
import {
mockAlerts,
mockAlerts2,
expectedFiringAlerts,
} from '@console/shared/src/utils/__mocks__/alerts-and-rules-data';
import { AlertSeverity } from '@console/internal/components/monitoring/types';
import {
getSeverityAlertType,
getFiringAlerts,
shouldHideMonitoringAlertDecorator,
} from '../alert-utils';

describe('alert-utils', () => {
it('should get firing alerts', () => {
const firingAlerts = getFiringAlerts(mockAlerts.data);
expect(firingAlerts).toEqual(expectedFiringAlerts);
});

it('should fetch the severity of the most important alert', () => {
const severityAlertType = getSeverityAlertType(mockAlerts.data);
expect(severityAlertType).toEqual(AlertSeverity.Critical);
});
it('should hide monitoring alert decorator for alerts having severity as info/none', () => {
const severityAlertType = getSeverityAlertType(mockAlerts2);
const hideMonitoringAlertDecorator = shouldHideMonitoringAlertDecorator(severityAlertType);
expect(hideMonitoringAlertDecorator).toBe(true);
});
});
5 changes: 4 additions & 1 deletion frontend/packages/console-shared/src/utils/alert-utils.ts
Expand Up @@ -7,9 +7,12 @@ export const sortMonitoringAlerts = (alerts: Alert[]): Alert[] =>

export const getSeverityAlertType = (alerts: Alert[]): AlertSeverity => {
const sortedAlerts = sortMonitoringAlerts(alerts);
const severityType = (sortedAlerts[0]?.labels?.severity as AlertSeverity) ?? null;
const severityType = (sortedAlerts[0]?.labels?.severity as AlertSeverity) ?? AlertSeverity.None;
return severityType;
};

export const getFiringAlerts = (alerts: Alert[]): Alert[] =>
_.filter(alerts, (alert) => alert.state === AlertStates.Firing);

export const shouldHideMonitoringAlertDecorator = (severityAlertType: AlertSeverity): boolean =>
severityAlertType === AlertSeverity.None || severityAlertType === AlertSeverity.Info;
Expand Up @@ -5,7 +5,12 @@ import { Node, SELECTION_EVENT } from '@patternfly/react-topology';
import { Tooltip, TooltipPosition } from '@patternfly/react-core';
import { Alert } from '@console/internal/components/monitoring/types';
import { selectOverviewDetailsTab } from '@console/internal/actions/ui';
import { getSeverityAlertType, getFiringAlerts, AlertSeverityIcon } from '@console/shared';
import {
getSeverityAlertType,
getFiringAlerts,
AlertSeverityIcon,
shouldHideMonitoringAlertDecorator,
} from '@console/shared';
import { Decorator } from './Decorator';

type DispatchProps = {
Expand Down Expand Up @@ -46,16 +51,16 @@ const MonitoringAlertsDecorator: React.FC<MonitoringAlertsDecoratorType> = ({
.fireEvent(SELECTION_EVENT, [workload.getId()]);
};

if (shouldHideMonitoringAlertDecorator(severityAlertType)) return null;

return (
firingAlerts.length > 0 && (
<Tooltip key="monitoringAlert" content="Monitoring Alert" position={TooltipPosition.left}>
<Decorator x={x} y={y} radius={radius} onClick={showSidebar}>
<g transform={`translate(-${radius / 2}, -${radius / 2})`}>
<AlertSeverityIcon severityAlertType={severityAlertType} fontSize={radius} />
</g>
</Decorator>
</Tooltip>
)
<Tooltip key="monitoringAlert" content="Monitoring Alert" position={TooltipPosition.left}>
<Decorator x={x} y={y} radius={radius} onClick={showSidebar}>
<g transform={`translate(-${radius / 2}, -${radius / 2})`}>
<AlertSeverityIcon severityAlertType={severityAlertType} fontSize={radius} />
</g>
</Decorator>
</Tooltip>
);
};

Expand Down
@@ -1,5 +1,6 @@
import * as React from 'react';
import * as classNames from 'classnames';
import { connect } from 'react-redux';
import {
Button,
DataList,
Expand All @@ -12,7 +13,14 @@ import {
TooltipPosition,
} from '@patternfly/react-core';
import { isNode, Node, observer } from '@patternfly/react-topology';
import { getSeverityAlertType, AlertSeverityIcon, getFiringAlerts } from '@console/shared';
import {
getSeverityAlertType,
AlertSeverityIcon,
getFiringAlerts,
shouldHideMonitoringAlertDecorator,
} from '@console/shared';
import { selectOverviewDetailsTab } from '@console/internal/actions/ui';

import { useSearchFilter } from '../filters';
import { getResourceKind } from '../topology-utils';
import { labelForNodeKind } from './list-view-utils';
Expand All @@ -23,8 +31,6 @@ import {
StatusCell,
TypedResourceBadgeCell,
} from './cells';
import { selectOverviewDetailsTab } from '@console/internal/actions/ui';
import { connect } from 'react-redux';

interface DispatchProps {
onSelectTab?: (name: string) => void;
Expand Down Expand Up @@ -72,7 +78,7 @@ const ObservedTopologyListViewNode: React.FC<TopologyListViewNodeProps & Dispatc
onSelectTab('Monitoring');
};
const severityAlertType = getSeverityAlertType(alerts);
alertIndicator = (
alertIndicator = shouldHideMonitoringAlertDecorator(severityAlertType) ? null : (
<Tooltip key="monitoringAlert" content="Monitoring Alert" position={TooltipPosition.right}>
<Button
variant="plain"
Expand Down
21 changes: 9 additions & 12 deletions frontend/public/components/overview/project-overview.tsx
Expand Up @@ -15,6 +15,7 @@ import {
AlertSeverityIcon,
getSeverityAlertType,
getFiringAlerts,
shouldHideMonitoringAlertDecorator,
} from '@console/shared';
import { K8sResourceKind } from '../../module/k8s';
import * as UIActions from '../../actions/ui';
Expand All @@ -26,7 +27,6 @@ import {
resourceObjPath,
truncateMiddle,
} from '../utils';

import { OverviewGroup, OverviewMetrics } from '.';

// Consider this mobile if the device screen width is less than 768. (This value shouldn't change.)
Expand Down Expand Up @@ -303,6 +303,13 @@ const ProjectOverviewListItem = connect<
selectOverviewDetailsTab('Monitoring');
selectItem(uid);
};
const alertIndicator = shouldHideMonitoringAlertDecorator(severityAlertType) ? null : (
<Tooltip key="monitoringAlert" content="Monitoring Alert" position={TooltipPosition.right}>
<Button onClick={onSeverityIconClick} variant="plain">
<AlertSeverityIcon severityAlertType={severityAlertType} />
</Button>
</Tooltip>
);

const heading = (
<h3 className="project-overview__item-heading">
Expand All @@ -323,17 +330,7 @@ const ProjectOverviewListItem = connect<
<ControllerLink controller={current} />
</>
)}
{firingAlerts.length > 0 && (
<Tooltip
key="monitoringAlert"
content="Monitoring Alert"
position={TooltipPosition.right}
>
<Button onClick={onSeverityIconClick} variant="plain">
<AlertSeverityIcon severityAlertType={severityAlertType} />
</Button>
</Tooltip>
)}
{alertIndicator}
{deletionTimestamp && <ResourceItemDeleting />}
</span>
</h3>
Expand Down