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

[Monitoring] Disk usage alerting #75419

Merged
merged 28 commits into from
Sep 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
795218e
Disk usage alert draft
igoristic Aug 19, 2020
2e306fe
Merge branch 'master' of https://github.com/elastic/kibana into disk-…
igoristic Aug 21, 2020
3e8a441
Merge branch 'master' of https://github.com/elastic/kibana into disk-…
igoristic Aug 24, 2020
e46f3db
Merge branch 'master' of https://github.com/elastic/kibana into disk-…
igoristic Aug 25, 2020
065c669
Merge branch 'master' of https://github.com/elastic/kibana into disk-…
igoristic Sep 2, 2020
98ad58d
Fixed typings and defaults
igoristic Sep 2, 2020
a2e5e69
Merge branch 'master' of https://github.com/elastic/kibana into disk-…
igoristic Sep 2, 2020
26e1f84
Fixed tests
igoristic Sep 2, 2020
d7bca1c
Fixed tests
igoristic Sep 2, 2020
2ba9fbe
Merge branch 'master' of https://github.com/elastic/kibana into disk-…
igoristic Sep 2, 2020
6f0007f
Merge branch 'master' of https://github.com/elastic/kibana into disk-…
igoristic Sep 4, 2020
6f3e35f
Merge branch 'master' of https://github.com/elastic/kibana into disk-…
igoristic Sep 4, 2020
add24ff
Addressed code feedback
igoristic Sep 4, 2020
fd594c7
Merge branch 'master' of https://github.com/elastic/kibana into disk-…
igoristic Sep 9, 2020
bc5622e
Merge branch 'master' of https://github.com/elastic/kibana into disk-…
igoristic Sep 14, 2020
ce2656c
Resolved conflicts
igoristic Sep 16, 2020
724eedb
Merge branch 'master' of https://github.com/elastic/kibana into disk-…
igoristic Sep 17, 2020
f030b10
Merge branch 'master' of https://github.com/elastic/kibana into disk-…
igoristic Sep 17, 2020
7bb5c06
Fixed disk and cpu usage states
igoristic Sep 17, 2020
481f144
Merge branch 'master' of https://github.com/elastic/kibana into disk-…
igoristic Sep 17, 2020
663e7dd
Merge branch 'master' of https://github.com/elastic/kibana into disk-…
igoristic Sep 22, 2020
b32226a
Fixed resolve state and throttle
igoristic Sep 22, 2020
327db89
Merge branch 'master' of https://github.com/elastic/kibana into disk-…
igoristic Sep 23, 2020
d164b33
Merge branch 'master' of https://github.com/elastic/kibana into disk-…
igoristic Sep 28, 2020
c65b7b5
Merge branch 'master' of https://github.com/elastic/kibana into disk-…
igoristic Sep 29, 2020
47711db
CR feedback
igoristic Sep 29, 2020
8693ed7
Fixed links
igoristic Sep 30, 2020
e56ea3e
Merge branch 'master' of https://github.com/elastic/kibana into disk-…
igoristic Sep 30, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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