Skip to content

Commit

Permalink
[Monitoring] Disk usage alerting (#75419)
Browse files Browse the repository at this point in the history
* Disk usage alert draft

* Fixed typings and defaults

* Fixed tests

* Fixed tests

* Addressed code feedback

* Fixed disk and cpu usage states

* Fixed resolve state and throttle

* CR feedback

* Fixed links
  • Loading branch information
igoristic authored Sep 30, 2020
1 parent b6db62e commit c49d546
Show file tree
Hide file tree
Showing 39 changed files with 1,076 additions and 706 deletions.
2 changes: 2 additions & 0 deletions x-pack/plugins/monitoring/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ export const ALERT_PREFIX = 'monitoring_';
export const ALERT_LICENSE_EXPIRATION = `${ALERT_PREFIX}alert_license_expiration`;
export const ALERT_CLUSTER_HEALTH = `${ALERT_PREFIX}alert_cluster_health`;
export const ALERT_CPU_USAGE = `${ALERT_PREFIX}alert_cpu_usage`;
export const ALERT_DISK_USAGE = `${ALERT_PREFIX}alert_disk_usage`;
export const ALERT_NODES_CHANGED = `${ALERT_PREFIX}alert_nodes_changed`;
export const ALERT_ELASTICSEARCH_VERSION_MISMATCH = `${ALERT_PREFIX}alert_elasticsearch_version_mismatch`;
export const ALERT_KIBANA_VERSION_MISMATCH = `${ALERT_PREFIX}alert_kibana_version_mismatch`;
Expand All @@ -243,6 +244,7 @@ export const ALERTS = [
ALERT_LICENSE_EXPIRATION,
ALERT_CLUSTER_HEALTH,
ALERT_CPU_USAGE,
ALERT_DISK_USAGE,
ALERT_NODES_CHANGED,
ALERT_ELASTICSEARCH_VERSION_MISMATCH,
ALERT_KIBANA_VERSION_MISMATCH,
Expand Down
5 changes: 3 additions & 2 deletions x-pack/plugins/monitoring/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ export interface CommonAlertState {
meta: any;
}

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface CommonAlertFilter {}
export interface CommonAlertFilter {
nodeUuid?: string;
}

export interface CommonAlertCpuUsageFilter extends CommonAlertFilter {
nodeUuid: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@

import React, { Fragment } from 'react';
import { EuiForm, EuiSpacer } from '@elastic/eui';
import { CommonAlertParamDetails } from '../../../common/types';
import { AlertParamDuration } from '../flyout_expressions/alert_param_duration';
import { AlertParamType } from '../../../common/enums';
import { AlertParamPercentage } from '../flyout_expressions/alert_param_percentage';
import { CommonAlertParamDetails } from '../../../../common/types';
import { AlertParamDuration } from '../../flyout_expressions/alert_param_duration';
import { AlertParamType } from '../../../../common/enums';
import { AlertParamPercentage } from '../../flyout_expressions/alert_param_percentage';

export interface Props {
alertParams: { [property: string]: any };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,30 @@

import { i18n } from '@kbn/i18n';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { ValidationResult } from '../../../../triggers_actions_ui/public/types';
import { ValidationResult } from '../../../../../triggers_actions_ui/public/types';

export function validate(opts: any): ValidationResult {
interface ValidateOptions {
duration: string;
threshold: number;
}

export function validate(inputValues: ValidateOptions): ValidationResult {
const validationResult = { errors: {} };

const errors: { [key: string]: string[] } = {
duration: [],
threshold: [],
};
if (!opts.duration) {
if (!inputValues.duration) {
errors.duration.push(
i18n.translate('xpack.monitoring.alerts.cpuUsage.validation.duration', {
i18n.translate('xpack.monitoring.alerts.validation.duration', {
defaultMessage: 'A valid duration is required.',
})
);
}
if (isNaN(opts.threshold)) {
if (isNaN(inputValues.threshold)) {
errors.threshold.push(
i18n.translate('xpack.monitoring.alerts.cpuUsage.validation.threshold', {
i18n.translate('xpack.monitoring.alerts.validation.threshold', {
defaultMessage: 'A valid number is required.',
})
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
import React from 'react';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { AlertTypeModel } from '../../../../triggers_actions_ui/public/types';
import { validate } from './validation';
import { ALERT_CPU_USAGE } from '../../../common/constants';
import { Expression } from './expression';
import { validate } from '../components/duration/validation';
import { Expression, Props } from '../components/duration/expression';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { CpuUsageAlert } from '../../../server/alerts';

Expand All @@ -18,7 +18,7 @@ export function createCpuUsageAlertType(): AlertTypeModel {
id: ALERT_CPU_USAGE,
name: alert.label,
iconClass: 'bell',
alertParamsExpression: (props: any) => (
alertParamsExpression: (props: Props) => (
<Expression {...props} paramDetails={CpuUsageAlert.paramDetails} />
),
validate,
Expand Down
29 changes: 29 additions & 0 deletions x-pack/plugins/monitoring/public/alerts/disk_usage_alert/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React from 'react';
import { validate } from '../components/duration/validation';
import { Expression, Props } from '../components/duration/expression';

// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { AlertTypeModel } from '../../../../triggers_actions_ui/public/types';

// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { DiskUsageAlert } from '../../../server/alerts';

export function createDiskUsageAlertType(): AlertTypeModel {
return {
id: DiskUsageAlert.TYPE,
name: DiskUsageAlert.LABEL,
iconClass: 'bell',
alertParamsExpression: (props: Props) => (
<Expression {...props} paramDetails={DiskUsageAlert.PARAM_DETAILS} />
),
validate,
defaultActionMessage: '{{context.internalFullMessage}}',
requiresAppContext: true,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { formatTimestampToDuration } from '../../../common';
import { CALCULATE_DURATION_UNTIL } from '../../../common/constants';
import { AlertMessageTokenType } from '../../../common/enums';
import { Legacy } from '../../legacy_shims';
import { getSafeForExternalLink } from '../../lib/get_safe_for_external_link';

export function replaceTokens(alertMessage: AlertMessage): JSX.Element | string | null {
if (!alertMessage) {
Expand Down Expand Up @@ -58,10 +59,11 @@ export function replaceTokens(alertMessage: AlertMessage): JSX.Element | string
const index = text.indexOf(linkPart[0]);
const preString = text.substring(0, index);
const postString = text.substring(index + linkPart[0].length);
const safeLink = getSafeForExternalLink(`#/${linkToken.url}`);
element = (
<Fragment>
{preString}
<EuiLink href={`#${linkToken.url}`}>{linkPart[1]}</EuiLink>
<EuiLink href={safeLink}>{linkPart[1]}</EuiLink>
{postString}
</Fragment>
);
Expand All @@ -83,7 +85,9 @@ export function replaceTokens(alertMessage: AlertMessage): JSX.Element | string
element = (
<Fragment>
{preString}
<EuiLink href={url}>{linkPart[1]}</EuiLink>
<EuiLink href={url} target="_blank" external>
{linkPart[1]}
</EuiLink>
{postString}
</Fragment>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
ALERT_LICENSE_EXPIRATION,
ALERT_CLUSTER_HEALTH,
ALERT_CPU_USAGE,
ALERT_DISK_USAGE,
ALERT_NODES_CHANGED,
ALERT_ELASTICSEARCH_VERSION_MISMATCH,
} from '../../../../common/constants';
Expand Down Expand Up @@ -157,6 +158,7 @@ const OVERVIEW_PANEL_ALERTS = [ALERT_CLUSTER_HEALTH, ALERT_LICENSE_EXPIRATION];

const NODES_PANEL_ALERTS = [
ALERT_CPU_USAGE,
ALERT_DISK_USAGE,
ALERT_NODES_CHANGED,
ALERT_ELASTICSEARCH_VERSION_MISMATCH,
];
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/monitoring/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { MonitoringStartPluginDependencies, MonitoringConfig } from './types';
import { TriggersAndActionsUIPublicPluginSetup } from '../../triggers_actions_ui/public';
import { createCpuUsageAlertType } from './alerts/cpu_usage_alert';
import { createLegacyAlertTypes } from './alerts/legacy_alert';
import { createDiskUsageAlertType } from './alerts/disk_usage_alert';

interface MonitoringSetupPluginDependencies {
home?: HomePublicPluginSetup;
Expand Down Expand Up @@ -71,6 +72,7 @@ export class MonitoringPlugin
}

plugins.triggers_actions_ui.alertTypeRegistry.register(createCpuUsageAlertType());
plugins.triggers_actions_ui.alertTypeRegistry.register(createDiskUsageAlertType());
const legacyAlertTypes = createLegacyAlertTypes();
for (const legacyAlertType of legacyAlertTypes) {
plugins.triggers_actions_ui.alertTypeRegistry.register(legacyAlertType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ import template from './index.html';
import { Legacy } from '../../../../legacy_shims';
import { AdvancedNode } from '../../../../components/elasticsearch/node/advanced';
import { MonitoringViewBaseController } from '../../../base_controller';
import { CODE_PATH_ELASTICSEARCH, ALERT_CPU_USAGE } from '../../../../../common/constants';
import {
CODE_PATH_ELASTICSEARCH,
ALERT_CPU_USAGE,
ALERT_DISK_USAGE,
} from '../../../../../common/constants';

function getPageData($injector) {
const $http = $injector.get('$http');
Expand Down Expand Up @@ -67,7 +71,7 @@ uiRoutes.when('/elasticsearch/nodes/:node/advanced', {
alerts: {
shouldFetch: true,
options: {
alertTypeIds: [ALERT_CPU_USAGE],
alertTypeIds: [ALERT_CPU_USAGE, ALERT_DISK_USAGE],
filters: [
{
nodeUuid: nodeName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ import { Node } from '../../../components/elasticsearch/node/node';
import { labels } from '../../../components/elasticsearch/shard_allocation/lib/labels';
import { nodesByIndices } from '../../../components/elasticsearch/shard_allocation/transformers/nodes_by_indices';
import { MonitoringViewBaseController } from '../../base_controller';
import { CODE_PATH_ELASTICSEARCH, ALERT_CPU_USAGE } from '../../../../common/constants';
import {
CODE_PATH_ELASTICSEARCH,
ALERT_CPU_USAGE,
ALERT_DISK_USAGE,
} from '../../../../common/constants';

uiRoutes.when('/elasticsearch/nodes/:node', {
template,
Expand Down Expand Up @@ -51,7 +55,7 @@ uiRoutes.when('/elasticsearch/nodes/:node', {
alerts: {
shouldFetch: true,
options: {
alertTypeIds: [ALERT_CPU_USAGE],
alertTypeIds: [ALERT_CPU_USAGE, ALERT_DISK_USAGE],
filters: [
{
nodeUuid: nodeName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
ELASTICSEARCH_SYSTEM_ID,
CODE_PATH_ELASTICSEARCH,
ALERT_CPU_USAGE,
ALERT_DISK_USAGE,
} from '../../../../common/constants';

uiRoutes.when('/elasticsearch/nodes', {
Expand Down Expand Up @@ -86,7 +87,7 @@ uiRoutes.when('/elasticsearch/nodes', {
alerts: {
shouldFetch: true,
options: {
alertTypeIds: [ALERT_CPU_USAGE],
alertTypeIds: [ALERT_CPU_USAGE, ALERT_DISK_USAGE],
},
},
});
Expand Down
82 changes: 82 additions & 0 deletions x-pack/plugins/monitoring/server/alerts/alerts_common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { i18n } from '@kbn/i18n';
import { AlertMessageDocLinkToken } from './types';
import { AlertMessageTokenType } from '../../common/enums';

export class AlertingDefaults {
public static readonly ALERT_STATE = {
resolved: i18n.translate('xpack.monitoring.alerts.state.resolved', {
defaultMessage: 'resolved',
}),
firing: i18n.translate('xpack.monitoring.alerts.state.firing', {
defaultMessage: 'firing',
}),
};
public static readonly ALERT_TYPE = {
context: {
internalShortMessage: {
name: 'internalShortMessage',
description: i18n.translate(
'xpack.monitoring.alerts.actionVariables.internalShortMessage',
{
defaultMessage: 'The short internal message generated by Elastic.',
}
),
},
internalFullMessage: {
name: 'internalFullMessage',
description: i18n.translate('xpack.monitoring.alerts.actionVariables.internalFullMessage', {
defaultMessage: 'The full internal message generated by Elastic.',
}),
},
state: {
name: 'state',
description: i18n.translate('xpack.monitoring.alerts.actionVariables.state', {
defaultMessage: 'The current state of the alert.',
}),
},
clusterName: {
name: 'clusterName',
description: i18n.translate('xpack.monitoring.alerts.actionVariables.clusterName', {
defaultMessage: 'The cluster to which the nodes belong.',
}),
},
action: {
name: 'action',
description: i18n.translate('xpack.monitoring.alerts.actionVariables.action', {
defaultMessage: 'The recommended action for this alert.',
}),
},
actionPlain: {
name: 'actionPlain',
description: i18n.translate('xpack.monitoring.alerts.actionVariables.actionPlain', {
defaultMessage: 'The recommended action for this alert, without any markdown.',
}),
},
},
};
}

export const createLink = (
linkText: string,
linkURL: string,
type: AlertMessageTokenType = AlertMessageTokenType.DocLink
) => {
const link = type === AlertMessageTokenType.DocLink ? { partialUrl: linkURL } : { url: linkURL };
return {
text: linkText,
tokens: [
{
...link,
startToken: '#start_link',
endToken: '#end_link',
type,
} as AlertMessageDocLinkToken,
],
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,6 @@ describe('AlertsFactory', () => {

it('should get all', () => {
const alerts = AlertsFactory.getAll();
expect(alerts.length).toBe(7);
expect(alerts.length).toBe(8);
});
});
3 changes: 3 additions & 0 deletions x-pack/plugins/monitoring/server/alerts/alerts_factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import {
CpuUsageAlert,
DiskUsageAlert,
NodesChangedAlert,
ClusterHealthAlert,
LicenseExpirationAlert,
Expand All @@ -18,6 +19,7 @@ import {
ALERT_CLUSTER_HEALTH,
ALERT_LICENSE_EXPIRATION,
ALERT_CPU_USAGE,
ALERT_DISK_USAGE,
ALERT_NODES_CHANGED,
ALERT_LOGSTASH_VERSION_MISMATCH,
ALERT_KIBANA_VERSION_MISMATCH,
Expand All @@ -29,6 +31,7 @@ export const BY_TYPE = {
[ALERT_CLUSTER_HEALTH]: ClusterHealthAlert,
[ALERT_LICENSE_EXPIRATION]: LicenseExpirationAlert,
[ALERT_CPU_USAGE]: CpuUsageAlert,
[ALERT_DISK_USAGE]: DiskUsageAlert,
[ALERT_NODES_CHANGED]: NodesChangedAlert,
[ALERT_LOGSTASH_VERSION_MISMATCH]: LogstashVersionMismatchAlert,
[ALERT_KIBANA_VERSION_MISMATCH]: KibanaVersionMismatchAlert,
Expand Down
9 changes: 5 additions & 4 deletions x-pack/plugins/monitoring/server/alerts/base_alert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ export class BaseAlert {
);

const data = await this.fetchData(params, callCluster, clusters, uiSettings, availableCcs);
this.processData(data, clusters, services, logger);
return await this.processData(data, clusters, services, logger, state);
}

protected async fetchData(
Expand All @@ -252,12 +252,13 @@ export class BaseAlert {
throw new Error('Child classes must implement `fetchData`');
}

protected processData(
protected async processData(
data: AlertData[],
clusters: AlertCluster[],
services: AlertServices,
logger: Logger
) {
logger: Logger,
instanceState: unknown
): Promise<void | Record<string, any>> {
for (const item of data) {
const cluster = clusters.find((c: AlertCluster) => c.clusterUuid === item.clusterUuid);
if (!cluster) {
Expand Down
Loading

0 comments on commit c49d546

Please sign in to comment.