Skip to content

Commit

Permalink
[Actionable Observability] Add links to navigate from alerts table to…
Browse files Browse the repository at this point in the history
… rule (#118035)

[Actionable Observability] Add links to navigate from alerts table and flyout to rule generate it
  • Loading branch information
ersin-erdal committed Nov 11, 2021
1 parent 9c0016f commit 29981ad
Show file tree
Hide file tree
Showing 9 changed files with 244 additions and 126 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { EuiSelect } from '@elastic/eui';
import { uniqBy } from 'lodash';
import { Alert } from '../../../../../../alerting/common';
import { usePluginContext } from '../../../../hooks/use_plugin_context';
import { paths } from '../../../../config';

const ALL_TYPES = 'ALL_TYPES';
const allTypes = {
Expand All @@ -41,8 +42,8 @@ export function AlertsSection({ alerts }: Props) {
const { config, core } = usePluginContext();
const [filter, setFilter] = useState(ALL_TYPES);
const manageLink = config.unsafe.alertingExperience.enabled
? core.http.basePath.prepend(`/app/observability/alerts`)
: core.http.basePath.prepend(`/app/management/insightsAndAlerting/triggersActions/rules`);
? core.http.basePath.prepend(paths.observability.alerts)
: core.http.basePath.prepend(paths.management.rules);
const filterOptions = uniqBy(alerts, (alert) => alert.consumer).map(({ consumer }) => ({
value: consumer,
text: consumer,
Expand Down Expand Up @@ -89,9 +90,7 @@ export function AlertsSection({ alerts }: Props) {
<EuiFlexGroup direction="column" gutterSize="s" key={alert.id}>
<EuiFlexItem grow={false}>
<EuiLink
href={core.http.basePath.prepend(
`/app/management/insightsAndAlerting/triggersActions/alert/${alert.id}`
)}
href={core.http.basePath.prepend(paths.management.alertDetails(alert.id))}
>
<EuiText size="s">{alert.name}</EuiText>
</EuiLink>
Expand Down
9 changes: 9 additions & 0 deletions x-pack/plugins/observability/public/config/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

export { paths } from './paths';
export { translations } from './translations';
19 changes: 19 additions & 0 deletions x-pack/plugins/observability/public/config/paths.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

export const paths = {
observability: {
alerts: '/app/observability/alerts',
},
management: {
rules: '/app/management/insightsAndAlerting/triggersActions/rules',
ruleDetails: (ruleId: string) =>
`/app/management/insightsAndAlerting/triggersActions/rule/${encodeURI(ruleId)}`,
alertDetails: (alertId: string) =>
`/app/management/insightsAndAlerting/triggersActions/alert/${encodeURI(alertId)}`,
},
};
104 changes: 104 additions & 0 deletions x-pack/plugins/observability/public/config/translations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { i18n } from '@kbn/i18n';

export const translations = {
alertsTable: {
viewDetailsTextLabel: i18n.translate('xpack.observability.alertsTable.viewDetailsTextLabel', {
defaultMessage: 'View details',
}),
viewInAppTextLabel: i18n.translate('xpack.observability.alertsTable.viewInAppTextLabel', {
defaultMessage: 'View in app',
}),
moreActionsTextLabel: i18n.translate('xpack.observability.alertsTable.moreActionsTextLabel', {
defaultMessage: 'More actions',
}),
notEnoughPermissions: i18n.translate('xpack.observability.alertsTable.notEnoughPermissions', {
defaultMessage: 'Additional privileges required',
}),
statusColumnDescription: i18n.translate(
'xpack.observability.alertsTGrid.statusColumnDescription',
{
defaultMessage: 'Alert Status',
}
),
lastUpdatedColumnDescription: i18n.translate(
'xpack.observability.alertsTGrid.lastUpdatedColumnDescription',
{
defaultMessage: 'Last updated',
}
),
durationColumnDescription: i18n.translate(
'xpack.observability.alertsTGrid.durationColumnDescription',
{
defaultMessage: 'Duration',
}
),
reasonColumnDescription: i18n.translate(
'xpack.observability.alertsTGrid.reasonColumnDescription',
{
defaultMessage: 'Reason',
}
),
actionsTextLabel: i18n.translate('xpack.observability.alertsTable.actionsTextLabel', {
defaultMessage: 'Actions',
}),
loadingTextLabel: i18n.translate('xpack.observability.alertsTable.loadingTextLabel', {
defaultMessage: 'loading alerts',
}),
footerTextLabel: i18n.translate('xpack.observability.alertsTable.footerTextLabel', {
defaultMessage: 'alerts',
}),
showingAlertsTitle: (totalAlerts: number) =>
i18n.translate('xpack.observability.alertsTable.showingAlertsTitle', {
values: { totalAlerts },
defaultMessage: '{totalAlerts, plural, =1 {alert} other {alerts}}',
}),
viewRuleDetailsButtonText: i18n.translate(
'xpack.observability.alertsTable.viewRuleDetailsButtonText',
{
defaultMessage: 'View rule details',
}
),
},
alertsFlyout: {
statusLabel: i18n.translate('xpack.observability.alertsFlyout.statusLabel', {
defaultMessage: 'Status',
}),
lastUpdatedLabel: i18n.translate('xpack.observability.alertsFlyout.lastUpdatedLabel', {
defaultMessage: 'Last updated',
}),
durationLabel: i18n.translate('xpack.observability.alertsFlyout.durationLabel', {
defaultMessage: 'Duration',
}),
expectedValueLabel: i18n.translate('xpack.observability.alertsFlyout.expectedValueLabel', {
defaultMessage: 'Expected value',
}),
actualValueLabel: i18n.translate('xpack.observability.alertsFlyout.actualValueLabel', {
defaultMessage: 'Actual value',
}),
ruleTypeLabel: i18n.translate('xpack.observability.alertsFlyout.ruleTypeLabel', {
defaultMessage: 'Rule type',
}),
reasonTitle: i18n.translate('xpack.observability.alertsFlyout.reasonTitle', {
defaultMessage: 'Reason',
}),
viewRulesDetailsLinkText: i18n.translate(
'xpack.observability.alertsFlyout.viewRulesDetailsLinkText',
{
defaultMessage: 'View rule details',
}
),
documentSummaryTitle: i18n.translate('xpack.observability.alertsFlyout.documentSummaryTitle', {
defaultMessage: 'Document Summary',
}),
viewInAppButtonText: i18n.translate('xpack.observability.alertsFlyout.viewInAppButtonText', {
defaultMessage: 'View in app',
}),
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ import {
EuiFlyoutFooter,
EuiFlyoutHeader,
EuiFlyoutProps,
EuiLink,
EuiSpacer,
EuiText,
EuiTitle,
EuiHorizontalRule,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import type {
ALERT_DURATION as ALERT_DURATION_TYPED,
ALERT_EVALUATION_THRESHOLD as ALERT_EVALUATION_THRESHOLD_TYPED,
Expand Down Expand Up @@ -47,6 +48,7 @@ import type { ObservabilityRuleTypeRegistry } from '../../../rules/create_observ
import { parseAlert } from '../parse_alert';
import { AlertStatusIndicator } from '../../../components/shared/alert_status_indicator';
import { ExperimentalBadge } from '../../../components/shared/experimental_badge';
import { translations, paths } from '../../../config';

type AlertsFlyoutProps = {
alert?: TopAlert;
Expand Down Expand Up @@ -77,6 +79,7 @@ export function AlertsFlyout({
const { services } = useKibana();
const { http } = services;
const prepend = http?.basePath.prepend;

const decoratedAlerts = useMemo(() => {
const parseObservabilityAlert = parseAlert(observabilityRuleTypeRegistry);
return (alerts ?? []).map(parseObservabilityAlert);
Expand All @@ -90,64 +93,68 @@ export function AlertsFlyout({
return null;
}

const ruleId = alertData.fields['kibana.alert.rule.uuid'] ?? null;
const linkToRule = ruleId && prepend ? prepend(paths.management.ruleDetails(ruleId)) : null;

const overviewListItems = [
{
title: i18n.translate('xpack.observability.alertsFlyout.statusLabel', {
defaultMessage: 'Status',
}),
title: translations.alertsFlyout.statusLabel,
description: (
<AlertStatusIndicator
alertStatus={alertData.active ? ALERT_STATUS_ACTIVE : ALERT_STATUS_RECOVERED}
/>
),
},
{
title: i18n.translate('xpack.observability.alertsFlyout.lastUpdatedLabel', {
defaultMessage: 'Last updated',
}),
title: translations.alertsFlyout.lastUpdatedLabel,
description: (
<span title={alertData.start.toString()}>{moment(alertData.start).format(dateFormat)}</span>
),
},
{
title: i18n.translate('xpack.observability.alertsFlyout.durationLabel', {
defaultMessage: 'Duration',
}),
title: translations.alertsFlyout.durationLabel,
description: asDuration(alertData.fields[ALERT_DURATION], { extended: true }),
},
{
title: i18n.translate('xpack.observability.alertsFlyout.expectedValueLabel', {
defaultMessage: 'Expected value',
}),
title: translations.alertsFlyout.expectedValueLabel,
description: alertData.fields[ALERT_EVALUATION_THRESHOLD] ?? '-',
},
{
title: i18n.translate('xpack.observability.alertsFlyout.actualValueLabel', {
defaultMessage: 'Actual value',
}),
title: translations.alertsFlyout.actualValueLabel,
description: alertData.fields[ALERT_EVALUATION_VALUE] ?? '-',
},
{
title: i18n.translate('xpack.observability.alertsFlyout.ruleTypeLabel', {
defaultMessage: 'Rule type',
}),
title: translations.alertsFlyout.ruleTypeLabel,
description: alertData.fields[ALERT_RULE_CATEGORY] ?? '-',
},
];

return (
<EuiFlyout onClose={onClose} size="s" data-test-subj="alertsFlyout">
<EuiFlyoutHeader>
<EuiFlyoutHeader hasBorder>
<ExperimentalBadge />
<EuiSpacer size="s" />
<EuiTitle size="m" data-test-subj="alertsFlyoutTitle">
<h2>{alertData.fields[ALERT_RULE_NAME]}</h2>
</EuiTitle>
<EuiSpacer size="s" />
<EuiText size="s">{alertData.reason}</EuiText>
</EuiFlyoutHeader>
<EuiFlyoutBody>
<EuiTitle size="xs">
<h4>{translations.alertsFlyout.reasonTitle}</h4>
</EuiTitle>
<EuiSpacer size="s" />
<EuiText size="s">{alertData.reason}</EuiText>
<EuiSpacer size="s" />
{!!linkToRule && (
<EuiLink href={linkToRule} data-test-subj="viewRuleDetailsFlyout">
{translations.alertsFlyout.viewRulesDetailsLinkText}
</EuiLink>
)}
<EuiHorizontalRule size="full" />
<EuiTitle size="xs">
<h4>{translations.alertsFlyout.documentSummaryTitle}</h4>
</EuiTitle>
<EuiSpacer size="m" />
<EuiDescriptionList
compressed={true}
type="responsiveColumn"
Expand All @@ -173,7 +180,7 @@ export function AlertsFlyout({
data-test-subj="alertsFlyoutViewInAppButton"
fill
>
View in app
{translations.alertsFlyout.viewInAppButtonText}
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
Expand Down
Loading

0 comments on commit 29981ad

Please sign in to comment.