Skip to content

Commit

Permalink
[REVERT THE REVERT] [Monitoring] Cluster state watch to Kibana alerti…
Browse files Browse the repository at this point in the history
…ng (#62793)

* Revert "Revert "[Monitoring] Cluster state watch to Kibana alerting (#61685)""

This reverts commit f1bd3bd.

* Fix i18n error

* Fix test
  • Loading branch information
chrisronline committed Apr 7, 2020
1 parent ef09909 commit c00e33f
Show file tree
Hide file tree
Showing 30 changed files with 1,565 additions and 757 deletions.
8 changes: 6 additions & 2 deletions x-pack/legacy/plugins/monitoring/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,11 +239,15 @@ export const ALERT_TYPE_PREFIX = 'monitoring_';
* This is the alert type id for the license expiration alert
*/
export const ALERT_TYPE_LICENSE_EXPIRATION = `${ALERT_TYPE_PREFIX}alert_type_license_expiration`;
/**
* This is the alert type id for the cluster state alert
*/
export const ALERT_TYPE_CLUSTER_STATE = `${ALERT_TYPE_PREFIX}alert_type_cluster_state`;

/**
* A listing of all alert types
*/
export const ALERT_TYPES = [ALERT_TYPE_LICENSE_EXPIRATION];
export const ALERT_TYPES = [ALERT_TYPE_LICENSE_EXPIRATION, ALERT_TYPE_CLUSTER_STATE];

/**
* Matches the id for the built-in in email action type
Expand All @@ -254,7 +258,7 @@ export const ALERT_ACTION_TYPE_EMAIL = '.email';
/**
* The number of alerts that have been migrated
*/
export const NUMBER_OF_MIGRATED_ALERTS = 1;
export const NUMBER_OF_MIGRATED_ALERTS = 2;

/**
* The advanced settings config name for the email address
Expand Down
44 changes: 27 additions & 17 deletions x-pack/legacy/plugins/monitoring/public/components/alerts/alerts.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,15 @@

import React from 'react';
import chrome from '../../np_imports/ui/chrome';
import { capitalize } from 'lodash';
import { capitalize, get } from 'lodash';
import { formatDateTimeLocal } from '../../../common/formatting';
import { formatTimestampToDuration } from '../../../common';
import { CALCULATE_DURATION_SINCE, EUI_SORT_DESCENDING } from '../../../common/constants';
import {
CALCULATE_DURATION_SINCE,
EUI_SORT_DESCENDING,
ALERT_TYPE_LICENSE_EXPIRATION,
ALERT_TYPE_CLUSTER_STATE,
} from '../../../common/constants';
import { mapSeverity } from './map_severity';
import { FormattedAlert } from 'plugins/monitoring/components/alerts/formatted_alert';
import { EuiMonitoringTable } from 'plugins/monitoring/components/table';
Expand All @@ -21,6 +26,8 @@ const linkToCategories = {
'elasticsearch/indices': 'Elasticsearch Indices',
'kibana/instances': 'Kibana Instances',
'logstash/instances': 'Logstash Nodes',
[ALERT_TYPE_LICENSE_EXPIRATION]: 'License expiration',
[ALERT_TYPE_CLUSTER_STATE]: 'Cluster state',
};
const getColumns = (kbnUrl, scope, timezone) => [
{
Expand Down Expand Up @@ -94,19 +101,22 @@ const getColumns = (kbnUrl, scope, timezone) => [
}),
field: 'message',
sortable: true,
render: (message, alert) => (
<FormattedAlert
prefix={alert.prefix}
suffix={alert.suffix}
message={message}
metadata={alert.metadata}
changeUrl={target => {
scope.$evalAsync(() => {
kbnUrl.changePath(target);
});
}}
/>
),
render: (_message, alert) => {
const message = get(alert, 'message.text', get(alert, 'message', ''));
return (
<FormattedAlert
prefix={alert.prefix}
suffix={alert.suffix}
message={message}
metadata={alert.metadata}
changeUrl={target => {
scope.$evalAsync(() => {
kbnUrl.changePath(target);
});
}}
/>
);
},
},
{
name: i18n.translate('xpack.monitoring.alerts.categoryColumnTitle', {
Expand Down Expand Up @@ -148,8 +158,8 @@ const getColumns = (kbnUrl, scope, timezone) => [
export const Alerts = ({ alerts, angular, sorting, pagination, onTableChange }) => {
const alertsFlattened = alerts.map(alert => ({
...alert,
status: alert.metadata.severity,
category: alert.metadata.link,
status: get(alert, 'metadata.severity', get(alert, 'severity', 0)),
category: get(alert, 'metadata.link', get(alert, 'type', null)),
}));

const injector = chrome.dangerouslyGetActiveInjector();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import React from 'react';
import { shallow } from 'enzyme';
import { kfetch } from 'ui/kfetch';
import { AlertsStatus, AlertsStatusProps } from './status';
import { ALERT_TYPE_PREFIX } from '../../../common/constants';
import { ALERT_TYPES } from '../../../common/constants';
import { getSetupModeState } from '../../lib/setup_mode';
import { mockUseEffects } from '../../jest.helpers';

Expand Down Expand Up @@ -63,11 +63,7 @@ describe('Status', () => {

it('should render a success message if all alerts have been migrated and in setup mode', async () => {
(kfetch as jest.Mock).mockReturnValue({
data: [
{
alertTypeId: ALERT_TYPE_PREFIX,
},
],
data: ALERT_TYPES.map(type => ({ alertTypeId: type })),
});

(getSetupModeState as jest.Mock).mockReturnValue({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ export const AlertsStatus: React.FC<AlertsStatusProps> = (props: AlertsStatusPro
);
}

const allMigrated = kibanaAlerts.length === NUMBER_OF_MIGRATED_ALERTS;
const allMigrated = kibanaAlerts.length >= NUMBER_OF_MIGRATED_ALERTS;
if (allMigrated) {
if (setupModeEnabled) {
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@

import React, { Fragment } from 'react';
import moment from 'moment-timezone';
import chrome from '../../../np_imports/ui/chrome';
import { FormattedAlert } from 'plugins/monitoring/components/alerts/formatted_alert';
import { mapSeverity } from 'plugins/monitoring/components/alerts/map_severity';
import { formatTimestampToDuration } from '../../../../common/format_timestamp_to_duration';
import {
CALCULATE_DURATION_SINCE,
KIBANA_ALERTING_ENABLED,
ALERT_TYPE_LICENSE_EXPIRATION,
CALCULATE_DURATION_UNTIL,
} from '../../../../common/constants';
import { formatDateTimeLocal } from '../../../../common/formatting';
Expand All @@ -31,6 +29,37 @@ import {
EuiLink,
} from '@elastic/eui';

function replaceTokens(alert) {
if (!alert.message.tokens) {
return alert.message.text;
}

let text = alert.message.text;

for (const token of alert.message.tokens) {
if (token.type === 'time') {
text = text.replace(
token.startToken,
token.isRelative
? formatTimestampToDuration(alert.expirationTime, CALCULATE_DURATION_UNTIL)
: moment.tz(alert.expirationTime, moment.tz.guess()).format('LLL z')
);
} else if (token.type === 'link') {
const linkPart = new RegExp(`${token.startToken}(.+?)${token.endToken}`).exec(text);
// TODO: we assume this is at the end, which works for now but will not always work
const nonLinkText = text.replace(linkPart[0], '');
text = (
<Fragment>
{nonLinkText}
<EuiLink href={`#${token.url}`}>{linkPart[1]}</EuiLink>
</Fragment>
);
}
}

return text;
}

export function AlertsPanel({ alerts, changeUrl }) {
const goToAlerts = () => changeUrl('/alerts');

Expand Down Expand Up @@ -58,9 +87,6 @@ export function AlertsPanel({ alerts, changeUrl }) {
severityIcon.iconType = 'check';
}

const injector = chrome.dangerouslyGetActiveInjector();
const timezone = injector.get('config').get('dateFormat:tz');

return (
<EuiCallOut
key={`alert-item-${index}`}
Expand All @@ -83,7 +109,7 @@ export function AlertsPanel({ alerts, changeUrl }) {
id="xpack.monitoring.cluster.overview.alertsPanel.lastCheckedTimeText"
defaultMessage="Last checked {updateDateTime} (triggered {duration} ago)"
values={{
updateDateTime: formatDateTimeLocal(item.update_timestamp, timezone),
updateDateTime: formatDateTimeLocal(item.update_timestamp),
duration: formatTimestampToDuration(item.timestamp, CALCULATE_DURATION_SINCE),
}}
/>
Expand All @@ -96,14 +122,7 @@ export function AlertsPanel({ alerts, changeUrl }) {
const alertsList = KIBANA_ALERTING_ENABLED
? alerts.map((alert, idx) => {
const callOutProps = mapSeverity(alert.severity);
let message = alert.message
// scan message prefix and replace relative times
// \w: Matches any alphanumeric character from the basic Latin alphabet, including the underscore. Equivalent to [A-Za-z0-9_].
.replace(
'#relative',
formatTimestampToDuration(alert.expirationTime, CALCULATE_DURATION_UNTIL)
)
.replace('#absolute', moment.tz(alert.expirationTime, moment.tz.guess()).format('LLL z'));
const message = replaceTokens(alert);

if (!alert.isFiring) {
callOutProps.title = i18n.translate(
Expand All @@ -118,22 +137,30 @@ export function AlertsPanel({ alerts, changeUrl }) {
);
callOutProps.color = 'success';
callOutProps.iconType = 'check';
} else {
if (alert.type === ALERT_TYPE_LICENSE_EXPIRATION) {
message = (
<Fragment>
{message}
&nbsp;
<EuiLink href="#license">Please update your license</EuiLink>
</Fragment>
);
}
}

return (
<EuiCallOut key={idx} {...callOutProps}>
<p>{message}</p>
</EuiCallOut>
<Fragment key={idx}>
<EuiCallOut {...callOutProps}>
<p>{message}</p>
<EuiText size="xs">
<p data-test-subj="alertMeta" className="monCallout--meta">
<FormattedMessage
id="xpack.monitoring.cluster.overview.alertsPanel.lastCheckedTimeText"
defaultMessage="Last checked {updateDateTime} (triggered {duration} ago)"
values={{
updateDateTime: formatDateTimeLocal(alert.lastCheckedMS),
duration: formatTimestampToDuration(
alert.triggeredMS,
CALCULATE_DURATION_SINCE
),
}}
/>
</p>
</EuiText>
</EuiCallOut>
<EuiSpacer />
</Fragment>
);
})
: alerts.map((item, index) => (
Expand Down
30 changes: 21 additions & 9 deletions x-pack/legacy/plugins/monitoring/public/views/alerts/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,37 @@ import { Alerts } from '../../components/alerts';
import { MonitoringViewBaseEuiTableController } from '../base_eui_table_controller';
import { FormattedMessage } from '@kbn/i18n/react';
import { EuiPage, EuiPageBody, EuiPageContent, EuiSpacer, EuiLink } from '@elastic/eui';
import { CODE_PATH_ALERTS } from '../../../common/constants';
import { CODE_PATH_ALERTS, KIBANA_ALERTING_ENABLED } from '../../../common/constants';

function getPageData($injector) {
const globalState = $injector.get('globalState');
const $http = $injector.get('$http');
const Private = $injector.get('Private');
const url = `../api/monitoring/v1/clusters/${globalState.cluster_uuid}/legacy_alerts`;
const url = KIBANA_ALERTING_ENABLED
? `../api/monitoring/v1/alert_status`
: `../api/monitoring/v1/clusters/${globalState.cluster_uuid}/legacy_alerts`;

const timeBounds = timefilter.getBounds();
const data = {
timeRange: {
min: timeBounds.min.toISOString(),
max: timeBounds.max.toISOString(),
},
};

if (!KIBANA_ALERTING_ENABLED) {
data.ccs = globalState.ccs;
}

return $http
.post(url, {
ccs: globalState.ccs,
timeRange: {
min: timeBounds.min.toISOString(),
max: timeBounds.max.toISOString(),
},
.post(url, data)
.then(response => {
const result = get(response, 'data', []);
if (KIBANA_ALERTING_ENABLED) {
return result.alerts;
}
return result;
})
.then(response => get(response, 'data', []))
.catch(err => {
const ajaxErrorHandlers = Private(ajaxErrorHandlersProvider);
return ajaxErrorHandlers(err);
Expand Down
8 changes: 6 additions & 2 deletions x-pack/plugins/monitoring/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,11 +239,15 @@ export const ALERT_TYPE_PREFIX = 'monitoring_';
* This is the alert type id for the license expiration alert
*/
export const ALERT_TYPE_LICENSE_EXPIRATION = `${ALERT_TYPE_PREFIX}alert_type_license_expiration`;
/**
* This is the alert type id for the cluster state alert
*/
export const ALERT_TYPE_CLUSTER_STATE = `${ALERT_TYPE_PREFIX}alert_type_cluster_state`;

/**
* A listing of all alert types
*/
export const ALERT_TYPES = [ALERT_TYPE_LICENSE_EXPIRATION];
export const ALERT_TYPES = [ALERT_TYPE_LICENSE_EXPIRATION, ALERT_TYPE_CLUSTER_STATE];

/**
* Matches the id for the built-in in email action type
Expand All @@ -254,7 +258,7 @@ export const ALERT_ACTION_TYPE_EMAIL = '.email';
/**
* The number of alerts that have been migrated
*/
export const NUMBER_OF_MIGRATED_ALERTS = 1;
export const NUMBER_OF_MIGRATED_ALERTS = 2;

/**
* The advanced settings config name for the email address
Expand Down
Loading

0 comments on commit c00e33f

Please sign in to comment.