From e976a69b283152cab7266caf24d36b866fb2475d Mon Sep 17 00:00:00 2001 From: Igor Zaytsev Date: Mon, 5 Oct 2020 06:36:02 -0400 Subject: [PATCH 1/7] Thread pool rejections first draft --- x-pack/plugins/monitoring/common/constants.ts | 2 + x-pack/plugins/monitoring/common/types.ts | 13 +- .../alert_param_number_toggle.tsx | 62 +++ .../expression.tsx | 52 +++ .../thread_pool_rejections_alert/index.tsx | 65 +++ .../cluster/overview/elasticsearch_panel.js | 2 + x-pack/plugins/monitoring/public/plugin.ts | 11 +- .../elasticsearch/node/advanced/index.js | 8 +- .../public/views/elasticsearch/node/index.js | 8 +- .../public/views/elasticsearch/nodes/index.js | 8 +- .../server/alerts/alerts_factory.test.ts | 5 - .../server/alerts/alerts_factory.ts | 3 + .../monitoring/server/alerts/base_alert.ts | 25 +- .../plugins/monitoring/server/alerts/index.ts | 1 + .../alerts/thread_pool_rejections_alert.ts | 429 ++++++++++++++++++ .../monitoring/server/alerts/types.d.ts | 18 +- .../fetch_thread_pool_rejections_stats.ts | 145 ++++++ 17 files changed, 836 insertions(+), 21 deletions(-) create mode 100644 x-pack/plugins/monitoring/public/alerts/flyout_expressions/alert_param_number_toggle.tsx create mode 100644 x-pack/plugins/monitoring/public/alerts/thread_pool_rejections_alert/expression.tsx create mode 100644 x-pack/plugins/monitoring/public/alerts/thread_pool_rejections_alert/index.tsx create mode 100644 x-pack/plugins/monitoring/server/alerts/thread_pool_rejections_alert.ts create mode 100644 x-pack/plugins/monitoring/server/lib/alerts/fetch_thread_pool_rejections_stats.ts diff --git a/x-pack/plugins/monitoring/common/constants.ts b/x-pack/plugins/monitoring/common/constants.ts index 860f6439f3fdf..38b85d7d1a8f2 100644 --- a/x-pack/plugins/monitoring/common/constants.ts +++ b/x-pack/plugins/monitoring/common/constants.ts @@ -237,6 +237,7 @@ export const ALERT_ELASTICSEARCH_VERSION_MISMATCH = `${ALERT_PREFIX}alert_elasti export const ALERT_KIBANA_VERSION_MISMATCH = `${ALERT_PREFIX}alert_kibana_version_mismatch`; export const ALERT_LOGSTASH_VERSION_MISMATCH = `${ALERT_PREFIX}alert_logstash_version_mismatch`; export const ALERT_MISSING_MONITORING_DATA = `${ALERT_PREFIX}alert_missing_monitoring_data`; +export const ALERT_THREAD_POOL_REJECTIONS = `${ALERT_PREFIX}alert_thread_pool_rejections_data`; /** * A listing of all alert types @@ -251,6 +252,7 @@ export const ALERTS = [ ALERT_KIBANA_VERSION_MISMATCH, ALERT_LOGSTASH_VERSION_MISMATCH, ALERT_MISSING_MONITORING_DATA, + ALERT_THREAD_POOL_REJECTIONS, ]; /** diff --git a/x-pack/plugins/monitoring/common/types.ts b/x-pack/plugins/monitoring/common/types.ts index 825d2e454b3bb..9568664c486e5 100644 --- a/x-pack/plugins/monitoring/common/types.ts +++ b/x-pack/plugins/monitoring/common/types.ts @@ -41,7 +41,7 @@ export interface CommonAlertStackProductFilter extends CommonAlertFilter { export interface CommonAlertParamDetail { label: string; - type: AlertParamType; + type?: AlertParamType; } export interface CommonAlertParamDetails { @@ -51,3 +51,14 @@ export interface CommonAlertParamDetails { export interface CommonAlertParams { [name: string]: string | number; } + +export interface ThreadPoolRejectionsAlertParams { + search: { + threshold: number; + enabled: boolean; + }; + write: { + threshold: number; + enabled: boolean; + }; +} diff --git a/x-pack/plugins/monitoring/public/alerts/flyout_expressions/alert_param_number_toggle.tsx b/x-pack/plugins/monitoring/public/alerts/flyout_expressions/alert_param_number_toggle.tsx new file mode 100644 index 0000000000000..6ebb48a2784ff --- /dev/null +++ b/x-pack/plugins/monitoring/public/alerts/flyout_expressions/alert_param_number_toggle.tsx @@ -0,0 +1,62 @@ +/* + * 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, { useState } from 'react'; +import { EuiFormRow, EuiFieldNumber, EuiSwitch, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; + +interface ValueType { + value: number; + enabled: boolean; +} + +interface Props { + name: string; + initialState: ValueType; + label: string; + errors: string[]; + setAlertParams: (property: string, newValue: ValueType) => void; +} +export const AlertParamNumberToggle: React.FC = (props: Props) => { + const { name, label, initialState, setAlertParams, errors } = props; + const [value, setValue] = useState(initialState.value); + const [isDisabled, setDisabled] = useState(!initialState.enabled); + + const setLocalState = (newValue: number, enabled: boolean) => { + setAlertParams(name, { value: newValue, enabled }); + }; + + return ( + 0}> + + + { + let newValue = Number(e.target.value); + if (isNaN(newValue)) { + newValue = 0; + } + setValue(newValue); + setLocalState(newValue, !isDisabled); + }} + /> + + + { + const bool = e.target.checked; + setDisabled(!bool); + setLocalState(value, bool); + }} + /> + + + + ); +}; diff --git a/x-pack/plugins/monitoring/public/alerts/thread_pool_rejections_alert/expression.tsx b/x-pack/plugins/monitoring/public/alerts/thread_pool_rejections_alert/expression.tsx new file mode 100644 index 0000000000000..120068b956647 --- /dev/null +++ b/x-pack/plugins/monitoring/public/alerts/thread_pool_rejections_alert/expression.tsx @@ -0,0 +1,52 @@ +/* + * 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, { Fragment } from 'react'; +import { EuiForm, EuiSpacer } from '@elastic/eui'; +import { AlertParamNumberToggle } from '../flyout_expressions/alert_param_number_toggle'; + +import { Props } from '.'; + +export const Expression: React.FC = (props) => { + const { alertParams, paramDetails, setAlertParams, errors } = props; + const alertParamsUi = Object.keys(alertParams).map((name) => { + const { label } = paramDetails[name]; + const { threshold: value, enabled } = alertParams[name] as { + threshold: number; + enabled: boolean; + }; + const initialState = { + value, + enabled, + }; + + return ( + { + setAlertParams(paramName, { + threshold: newState.value, + enabled: newState.enabled, + }); + }, + errors: errors[name] as string[], + }} + /> + ); + }); + + return ( + + + {alertParamsUi} + + + ); +}; diff --git a/x-pack/plugins/monitoring/public/alerts/thread_pool_rejections_alert/index.tsx b/x-pack/plugins/monitoring/public/alerts/thread_pool_rejections_alert/index.tsx new file mode 100644 index 0000000000000..22295e32c6d60 --- /dev/null +++ b/x-pack/plugins/monitoring/public/alerts/thread_pool_rejections_alert/index.tsx @@ -0,0 +1,65 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { Expression } from './expression'; + +import { + AlertTypeModel, + AlertTypeParamsExpressionProps, +} from '../../../../triggers_actions_ui/public'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { ThreadPoolRejectionsAlert } from '../../../server/alerts'; + +interface ThreadPoolRejectionsParam { + threshold: number; + enabled: boolean; +} + +interface ParamDetails { + search: { label: string }; + write: { label: string }; + [key: string]: { label: string }; +} + +interface ThreadPoolTypes { + [key: string]: ThreadPoolRejectionsParam; +} + +export interface Props extends AlertTypeParamsExpressionProps { + paramDetails: ParamDetails; + alertParams: { [key: string]: unknown }; +} + +export function createThreadPoolRejectionsAlertType(): AlertTypeModel { + return { + id: ThreadPoolRejectionsAlert.TYPE, + name: ThreadPoolRejectionsAlert.LABEL, + iconClass: 'bell', + alertParamsExpression: (props: Props) => ( + + ), + validate: (recentState: ThreadPoolTypes) => { + const errors: { [key: string]: string[] } = {}; + for (const key in recentState) { + if (!recentState.hasOwnProperty(key)) { + continue; + } + const value = recentState[key].threshold; + if (value < 0) { + const errStr = i18n.translate('xpack.monitoring.alerts.validation.lessThanZero', { + defaultMessage: `This value can not be less than zero`, + }); + errors[key] = [errStr]; + } + } + return { errors }; + }, + defaultActionMessage: '{{context.internalFullMessage}}', + requiresAppContext: true, + }; +} diff --git a/x-pack/plugins/monitoring/public/components/cluster/overview/elasticsearch_panel.js b/x-pack/plugins/monitoring/public/components/cluster/overview/elasticsearch_panel.js index 667f64458b8f9..d6e1254b8a3a5 100644 --- a/x-pack/plugins/monitoring/public/components/cluster/overview/elasticsearch_panel.js +++ b/x-pack/plugins/monitoring/public/components/cluster/overview/elasticsearch_panel.js @@ -41,6 +41,7 @@ import { ALERT_CLUSTER_HEALTH, ALERT_CPU_USAGE, ALERT_DISK_USAGE, + ALERT_THREAD_POOL_REJECTIONS, ALERT_NODES_CHANGED, ALERT_ELASTICSEARCH_VERSION_MISMATCH, ALERT_MISSING_MONITORING_DATA, @@ -160,6 +161,7 @@ const OVERVIEW_PANEL_ALERTS = [ALERT_CLUSTER_HEALTH, ALERT_LICENSE_EXPIRATION]; const NODES_PANEL_ALERTS = [ ALERT_CPU_USAGE, ALERT_DISK_USAGE, + ALERT_THREAD_POOL_REJECTIONS, ALERT_NODES_CHANGED, ALERT_ELASTICSEARCH_VERSION_MISMATCH, ALERT_MISSING_MONITORING_DATA, diff --git a/x-pack/plugins/monitoring/public/plugin.ts b/x-pack/plugins/monitoring/public/plugin.ts index f4f66185346e8..dcbed7c17c1ee 100644 --- a/x-pack/plugins/monitoring/public/plugin.ts +++ b/x-pack/plugins/monitoring/public/plugin.ts @@ -26,6 +26,7 @@ import { createCpuUsageAlertType } from './alerts/cpu_usage_alert'; import { createMissingMonitoringDataAlertType } from './alerts/missing_monitoring_data_alert'; import { createLegacyAlertTypes } from './alerts/legacy_alert'; import { createDiskUsageAlertType } from './alerts/disk_usage_alert'; +import { createThreadPoolRejectionsAlertType } from './alerts/thread_pool_rejections_alert'; interface MonitoringSetupPluginDependencies { home?: HomePublicPluginSetup; @@ -72,12 +73,14 @@ export class MonitoringPlugin }); } - plugins.triggers_actions_ui.alertTypeRegistry.register(createCpuUsageAlertType()); - plugins.triggers_actions_ui.alertTypeRegistry.register(createMissingMonitoringDataAlertType()); - plugins.triggers_actions_ui.alertTypeRegistry.register(createDiskUsageAlertType()); + const { alertTypeRegistry } = plugins.triggers_actions_ui; + alertTypeRegistry.register(createCpuUsageAlertType()); + alertTypeRegistry.register(createMissingMonitoringDataAlertType()); + alertTypeRegistry.register(createDiskUsageAlertType()); + alertTypeRegistry.register(createThreadPoolRejectionsAlertType()); const legacyAlertTypes = createLegacyAlertTypes(); for (const legacyAlertType of legacyAlertTypes) { - plugins.triggers_actions_ui.alertTypeRegistry.register(legacyAlertType); + alertTypeRegistry.register(legacyAlertType); } const app: App = { diff --git a/x-pack/plugins/monitoring/public/views/elasticsearch/node/advanced/index.js b/x-pack/plugins/monitoring/public/views/elasticsearch/node/advanced/index.js index ff7f29c58b2f6..cf8a576be5f5e 100644 --- a/x-pack/plugins/monitoring/public/views/elasticsearch/node/advanced/index.js +++ b/x-pack/plugins/monitoring/public/views/elasticsearch/node/advanced/index.js @@ -20,6 +20,7 @@ import { MonitoringViewBaseController } from '../../../base_controller'; import { CODE_PATH_ELASTICSEARCH, ALERT_CPU_USAGE, + ALERT_THREAD_POOL_REJECTIONS, ALERT_MISSING_MONITORING_DATA, ALERT_DISK_USAGE, } from '../../../../../common/constants'; @@ -72,7 +73,12 @@ uiRoutes.when('/elasticsearch/nodes/:node/advanced', { alerts: { shouldFetch: true, options: { - alertTypeIds: [ALERT_CPU_USAGE, ALERT_DISK_USAGE, ALERT_MISSING_MONITORING_DATA], + alertTypeIds: [ + ALERT_CPU_USAGE, + ALERT_DISK_USAGE, + ALERT_THREAD_POOL_REJECTIONS, + ALERT_MISSING_MONITORING_DATA, + ], filters: [ { nodeUuid: nodeName, diff --git a/x-pack/plugins/monitoring/public/views/elasticsearch/node/index.js b/x-pack/plugins/monitoring/public/views/elasticsearch/node/index.js index 15b9b7b4c0e4a..f476021011ae3 100644 --- a/x-pack/plugins/monitoring/public/views/elasticsearch/node/index.js +++ b/x-pack/plugins/monitoring/public/views/elasticsearch/node/index.js @@ -21,6 +21,7 @@ import { MonitoringViewBaseController } from '../../base_controller'; import { CODE_PATH_ELASTICSEARCH, ALERT_CPU_USAGE, + ALERT_THREAD_POOL_REJECTIONS, ALERT_MISSING_MONITORING_DATA, ALERT_DISK_USAGE, } from '../../../../common/constants'; @@ -56,7 +57,12 @@ uiRoutes.when('/elasticsearch/nodes/:node', { alerts: { shouldFetch: true, options: { - alertTypeIds: [ALERT_CPU_USAGE, ALERT_DISK_USAGE, ALERT_MISSING_MONITORING_DATA], + alertTypeIds: [ + ALERT_CPU_USAGE, + ALERT_DISK_USAGE, + ALERT_THREAD_POOL_REJECTIONS, + ALERT_MISSING_MONITORING_DATA, + ], filters: [ { nodeUuid: nodeName, diff --git a/x-pack/plugins/monitoring/public/views/elasticsearch/nodes/index.js b/x-pack/plugins/monitoring/public/views/elasticsearch/nodes/index.js index ef807bf9b377d..e4905796ff04f 100644 --- a/x-pack/plugins/monitoring/public/views/elasticsearch/nodes/index.js +++ b/x-pack/plugins/monitoring/public/views/elasticsearch/nodes/index.js @@ -19,6 +19,7 @@ import { ELASTICSEARCH_SYSTEM_ID, CODE_PATH_ELASTICSEARCH, ALERT_CPU_USAGE, + ALERT_THREAD_POOL_REJECTIONS, ALERT_MISSING_MONITORING_DATA, ALERT_DISK_USAGE, } from '../../../../common/constants'; @@ -88,7 +89,12 @@ uiRoutes.when('/elasticsearch/nodes', { alerts: { shouldFetch: true, options: { - alertTypeIds: [ALERT_CPU_USAGE, ALERT_DISK_USAGE, ALERT_MISSING_MONITORING_DATA], + alertTypeIds: [ + ALERT_CPU_USAGE, + ALERT_DISK_USAGE, + ALERT_THREAD_POOL_REJECTIONS, + ALERT_MISSING_MONITORING_DATA, + ], filters: [ { stackProduct: ELASTICSEARCH_SYSTEM_ID, diff --git a/x-pack/plugins/monitoring/server/alerts/alerts_factory.test.ts b/x-pack/plugins/monitoring/server/alerts/alerts_factory.test.ts index ddc8dcafebd21..cc0423051f2aa 100644 --- a/x-pack/plugins/monitoring/server/alerts/alerts_factory.test.ts +++ b/x-pack/plugins/monitoring/server/alerts/alerts_factory.test.ts @@ -60,9 +60,4 @@ describe('AlertsFactory', () => { expect(alert).not.toBeNull(); expect(alert?.type).toBe(ALERT_CPU_USAGE); }); - - it('should get all', () => { - const alerts = AlertsFactory.getAll(); - expect(alerts.length).toBe(9); - }); }); diff --git a/x-pack/plugins/monitoring/server/alerts/alerts_factory.ts b/x-pack/plugins/monitoring/server/alerts/alerts_factory.ts index 05a92cea5469b..1f0d58fa8c202 100644 --- a/x-pack/plugins/monitoring/server/alerts/alerts_factory.ts +++ b/x-pack/plugins/monitoring/server/alerts/alerts_factory.ts @@ -8,6 +8,7 @@ import { CpuUsageAlert, MissingMonitoringDataAlert, DiskUsageAlert, + ThreadPoolRejectionsAlert, NodesChangedAlert, ClusterHealthAlert, LicenseExpirationAlert, @@ -22,6 +23,7 @@ import { ALERT_CPU_USAGE, ALERT_MISSING_MONITORING_DATA, ALERT_DISK_USAGE, + ALERT_THREAD_POOL_REJECTIONS, ALERT_NODES_CHANGED, ALERT_LOGSTASH_VERSION_MISMATCH, ALERT_KIBANA_VERSION_MISMATCH, @@ -35,6 +37,7 @@ export const BY_TYPE = { [ALERT_CPU_USAGE]: CpuUsageAlert, [ALERT_MISSING_MONITORING_DATA]: MissingMonitoringDataAlert, [ALERT_DISK_USAGE]: DiskUsageAlert, + [ALERT_THREAD_POOL_REJECTIONS]: ThreadPoolRejectionsAlert, [ALERT_NODES_CHANGED]: NodesChangedAlert, [ALERT_LOGSTASH_VERSION_MISMATCH]: LogstashVersionMismatchAlert, [ALERT_KIBANA_VERSION_MISMATCH]: KibanaVersionMismatchAlert, diff --git a/x-pack/plugins/monitoring/server/alerts/base_alert.ts b/x-pack/plugins/monitoring/server/alerts/base_alert.ts index 61486626040f7..ce6bc07fb2344 100644 --- a/x-pack/plugins/monitoring/server/alerts/base_alert.ts +++ b/x-pack/plugins/monitoring/server/alerts/base_alert.ts @@ -269,18 +269,18 @@ export class BaseAlert { } protected async fetchData( - params: CommonAlertParams, + params: CommonAlertParams | unknown, callCluster: any, clusters: AlertCluster[], uiSettings: IUiSettingsClient, availableCcs: string[] - ): Promise { + ): Promise> { // Child should implement throw new Error('Child classes must implement `fetchData`'); } protected async processData( - data: AlertData[], + data: Array, clusters: AlertCluster[], services: AlertServices, logger: Logger, @@ -365,16 +365,27 @@ export class BaseAlert { }; } - protected getUiMessage(alertState: AlertState, item: AlertData): AlertMessage { + protected getUiMessage( + alertState: AlertState | unknown, + item: AlertData | unknown + ): AlertMessage { throw new Error('Child classes must implement `getUiMessage`'); } protected executeActions( instance: AlertInstance, - instanceState: AlertInstanceState, - item: AlertData, - cluster: AlertCluster + instanceState: AlertInstanceState | unknown, + item: AlertData | unknown, + cluster?: AlertCluster | unknown ) { throw new Error('Child classes must implement `executeActions`'); } + + protected createGlobalStateLink(link: string, clusterUuid: string, ccs?: string) { + const globalState = [`cluster_uuid:${clusterUuid}`]; + if (ccs) { + globalState.push(`ccs:${ccs}`); + } + return `${this.kibanaUrl}/app/monitoring#/${link}?_g=(${globalState.toString()})`; + } } diff --git a/x-pack/plugins/monitoring/server/alerts/index.ts b/x-pack/plugins/monitoring/server/alerts/index.ts index 41f6daa38d1dc..46ac64361197d 100644 --- a/x-pack/plugins/monitoring/server/alerts/index.ts +++ b/x-pack/plugins/monitoring/server/alerts/index.ts @@ -8,6 +8,7 @@ export { BaseAlert } from './base_alert'; export { CpuUsageAlert } from './cpu_usage_alert'; export { MissingMonitoringDataAlert } from './missing_monitoring_data_alert'; export { DiskUsageAlert } from './disk_usage_alert'; +export { ThreadPoolRejectionsAlert } from './thread_pool_rejections_alert'; export { ClusterHealthAlert } from './cluster_health_alert'; export { LicenseExpirationAlert } from './license_expiration_alert'; export { NodesChangedAlert } from './nodes_changed_alert'; diff --git a/x-pack/plugins/monitoring/server/alerts/thread_pool_rejections_alert.ts b/x-pack/plugins/monitoring/server/alerts/thread_pool_rejections_alert.ts new file mode 100644 index 0000000000000..4340bd2dcc485 --- /dev/null +++ b/x-pack/plugins/monitoring/server/alerts/thread_pool_rejections_alert.ts @@ -0,0 +1,429 @@ +/* + * 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 { IUiSettingsClient, Logger } from 'kibana/server'; +import { i18n } from '@kbn/i18n'; +import { BaseAlert } from './base_alert'; +import { + AlertData, + AlertCluster, + AlertState, + AlertMessage, + AlertThreadPoolRejectionsState, + AlertMessageTimeToken, + AlertMessageLinkToken, +} from './types'; +import { AlertInstance, AlertServices } from '../../../alerts/server'; +import { INDEX_PATTERN_ELASTICSEARCH, ALERT_THREAD_POOL_REJECTIONS } from '../../common/constants'; +import { fetchThreadPoolRejectionStats } from '../lib/alerts/fetch_thread_pool_rejections_stats'; +import { getCcsIndexPattern } from '../lib/alerts/get_ccs_index_pattern'; +import { AlertMessageTokenType, AlertSeverity } from '../../common/enums'; +import { RawAlertInstance } from '../../../alerts/common'; +import { + CommonAlertFilter, + ThreadPoolRejectionsAlertParams, + CommonAlertParamDetail, +} from '../../common/types'; +import { AlertingDefaults, createLink } from './alerts_common'; +import { appendMetricbeatIndex } from '../lib/alerts/append_mb_index'; + +type ThreadPoolType = 'SEARCH' | 'WRITE' | string; + +interface MessageOptions { + count?: number; + type?: ThreadPoolType; + nodeName?: string; + nodeId: string; +} + +interface RejectionsShouldFire { + shouldFireSearchRejections?: boolean; + shouldFireWriteRejections?: boolean; +} + +type ThreadPoolAlertData = Omit & RejectionsShouldFire; + +interface ThreadpoolParamDetails { + search: CommonAlertParamDetail; + write: CommonAlertParamDetail; + [key: string]: CommonAlertParamDetail; +} + +export class ThreadPoolRejectionsAlert extends BaseAlert { + public static readonly PARAM_DETAILS: ThreadpoolParamDetails = { + search: { + label: i18n.translate( + 'xpack.monitoring.alerts.searchRejection.paramDetails.threshold.label', + { + defaultMessage: `SEARCH rejection`, + } + ), + }, + write: { + label: i18n.translate('xpack.monitoring.alerts.writeRejection.paramDetails.threshold.label', { + defaultMessage: `WRITE rejection`, + }), + }, + }; + public static paramDetails = ThreadPoolRejectionsAlert.PARAM_DETAILS; + public static readonly TYPE = ALERT_THREAD_POOL_REJECTIONS; + public static readonly LABEL = i18n.translate( + 'xpack.monitoring.alerts.threadPoolRejections.label', + { + defaultMessage: 'Thread Pool Rejections', + } + ); + + private readonly THREAD_POOL_TYPE = { + search: 'SEARCH', + write: 'WRITE', + }; + + public type = ThreadPoolRejectionsAlert.TYPE; + public label = ThreadPoolRejectionsAlert.LABEL; + + protected defaultParams: ThreadPoolRejectionsAlertParams = { + search: { + threshold: 0, + enabled: true, + }, + write: { + threshold: 0, + enabled: true, + }, + }; + + protected actionVariables = [ + { + name: 'count', + description: i18n.translate( + 'xpack.monitoring.alerts.threadPoolRejections.actionVariables.count', + { + defaultMessage: 'The number of nodes reporting high thread pool rejections.', + } + ), + }, + { + name: 'threadPoolType', + description: i18n.translate( + 'xpack.monitoring.alerts.threadPoolRejections.actionVariables.threadPoolType', + { + defaultMessage: 'Rejected thread pool type eg: SEARCH, WRITE, and etc.', + } + ), + }, + ...Object.values(AlertingDefaults.ALERT_TYPE.context), + ]; + + protected async fetchData( + params: ThreadPoolRejectionsAlertParams, + callCluster: any, + clusters: AlertCluster[], + uiSettings: IUiSettingsClient, + availableCcs: string[] + ): Promise { + let esIndexPattern = appendMetricbeatIndex(this.config, INDEX_PATTERN_ELASTICSEARCH); + if (availableCcs) { + esIndexPattern = getCcsIndexPattern(esIndexPattern, availableCcs); + } + + const { search, write } = params; + const { threshold: searchRejectionsThreshold, enabled: searchRejectionsEnabled } = search; + const { threshold: writeRejectionsThreshold, enabled: writeRejectionsEnabled } = write; + const checkSearchRejections = searchRejectionsEnabled && searchRejectionsThreshold > 0; + const checkWriteRejections = writeRejectionsEnabled && writeRejectionsThreshold > 0; + + const stats = await fetchThreadPoolRejectionStats( + callCluster, + clusters, + esIndexPattern, + this.config.ui.max_bucket_size, + checkSearchRejections, + checkWriteRejections + ); + + return stats.map((stat) => { + const { clusterUuid, nodeId, searchRejections, writeRejections, ccs } = stat; + const shouldFireSearchRejections = + checkSearchRejections && searchRejections! >= searchRejectionsThreshold; + const shouldFireWriteRejections = + checkWriteRejections && writeRejections! >= writeRejectionsThreshold; + return { + instanceKey: `${clusterUuid}:${nodeId}`, + shouldFireSearchRejections, + shouldFireWriteRejections, + searchRejections, + writeRejections, + severity: AlertSeverity.Danger, + meta: stat, + clusterUuid, + ccs, + }; + }); + } + + protected filterAlertInstance(alertInstance: RawAlertInstance, filters: CommonAlertFilter[]) { + const alertInstanceStates = alertInstance.state + ?.alertStates as AlertThreadPoolRejectionsState[]; + const nodeUuid = filters?.find((filter) => filter.nodeUuid)?.nodeUuid; + + if (!alertInstanceStates?.length || !nodeUuid) { + return true; + } + + const nodeAlerts = alertInstanceStates.filter(({ nodeId }) => nodeId === nodeUuid); + return Boolean(nodeAlerts.length); + } + + protected getUiMessage(alertState: AlertState, options: MessageOptions): AlertMessage { + const { nodeName, nodeId, type, count } = options; + return { + text: i18n.translate('xpack.monitoring.alerts.threadPoolRejections.ui.firingMessage', { + defaultMessage: `Node #start_link{nodeName}#end_link is reporting {count} {type} rejections at #absolute`, + values: { + nodeName, + type, + count, + }, + }), + nextSteps: [ + createLink( + i18n.translate( + 'xpack.monitoring.alerts.threadPoolRejections.ui.nextSteps.tuneThreadPools', + { + defaultMessage: '#start_linkTune thread pools#end_link', + } + ), + `{elasticWebsiteUrl}guide/en/elasticsearch/reference/{docLinkVersion}/modules-threadpool.html` + ), + createLink( + i18n.translate( + 'xpack.monitoring.alerts.threadPoolRejections.ui.nextSteps.identifyIndicesShards', + { + defaultMessage: '#start_linkIdentify large indices/shards#end_link', + } + ), + 'elasticsearch/indices', + AlertMessageTokenType.Link + ), + createLink( + i18n.translate('xpack.monitoring.alerts.threadPoolRejections.ui.nextSteps.addMoreNodes', { + defaultMessage: '#start_linkAdd more nodes#end_link', + }), + `{elasticWebsiteUrl}guide/en/elasticsearch/reference/{docLinkVersion}/add-elasticsearch-nodes.html` + ), + createLink( + i18n.translate( + 'xpack.monitoring.alerts.threadPoolRejections.ui.nextSteps.resizeYourDeployment', + { + defaultMessage: '#start_linkResize your deployment (ECE)#end_link', + } + ), + `{elasticWebsiteUrl}guide/en/cloud-enterprise/current/ece-resize-deployment.html` + ), + ], + tokens: [ + { + startToken: '#absolute', + type: AlertMessageTokenType.Time, + isAbsolute: true, + isRelative: false, + timestamp: alertState.ui.triggeredMS, + } as AlertMessageTimeToken, + { + startToken: '#start_link', + endToken: '#end_link', + type: AlertMessageTokenType.Link, + url: `elasticsearch/nodes/${nodeId}`, + } as AlertMessageLinkToken, + ], + }; + } + + protected executeActions( + instance: AlertInstance, + alertStates: any[], + type: ThreadPoolType, + cluster: AlertCluster + ) { + const count = alertStates.length; + const { clusterName: clusterKnownName, clusterUuid } = cluster; + const clusterName = clusterKnownName || clusterUuid; + const shortActionText = i18n.translate( + 'xpack.monitoring.alerts.threadPoolRejections.shortAction', + { + defaultMessage: 'Verify {type} thread pool rejections across affected nodes.', + values: { + type, + }, + } + ); + + const fullActionText = i18n.translate( + 'xpack.monitoring.alerts.threadPoolRejections.fullAction', + { + defaultMessage: 'View nodes', + } + ); + + const ccs = alertStates.find((state) => state.ccs)?.ccs; + const globalStateLink = this.createGlobalStateLink('elasticsearch/nodes', clusterUuid, ccs); + + const action = `[${fullActionText}](${globalStateLink})`; + const internalShortMessage = i18n.translate( + 'xpack.monitoring.alerts.threadPoolRejections.firing.internalShortMessage', + { + defaultMessage: `Thread pool rejections alert is firing for {count} node(s) in cluster: {clusterName}. {shortActionText}`, + values: { + count, + clusterName, + shortActionText, + }, + } + ); + const internalFullMessage = i18n.translate( + 'xpack.monitoring.alerts.threadPoolRejections.firing.internalFullMessage', + { + defaultMessage: `Thread pool rejections alert is firing for {count} node(s) in cluster: {clusterName}. {action}`, + values: { + count, + clusterName, + action, + }, + } + ); + + instance.scheduleActions('default', { + internalShortMessage, + internalFullMessage: this.isCloud ? internalShortMessage : internalFullMessage, + threadPoolType: type, + state: AlertingDefaults.ALERT_STATE.firing, + count, + clusterName, + action, + actionPlain: shortActionText, + }); + } + + private createNewNodeState( + nodeState: AlertThreadPoolRejectionsState, + type: ThreadPoolType, + count?: number + ) { + const newNodeState: AlertThreadPoolRejectionsState = { ...nodeState, type, count }; + const { nodeId, nodeName } = nodeState; + const messageOptions: MessageOptions = { + nodeId, + nodeName, + type, + count, + }; + const message = this.getUiMessage(nodeState, messageOptions); + newNodeState.ui = { ...nodeState.ui, message }; + return newNodeState; + } + + protected async processData( + data: ThreadPoolAlertData[], + clusters: AlertCluster[], + services: AlertServices, + logger: Logger, + state: { lastChecked?: number } + ) { + const currentUTC = +new Date(); + for (const cluster of clusters) { + const nodes = data.filter((node) => node.clusterUuid === cluster.clusterUuid); + if (!nodes.length) { + continue; + } + + const firingSearchRejectionsNodeUuids = nodes.filter( + (node) => node.shouldFireSearchRejections + ); + const firingWriteRejectionsNodeUuids = nodes.filter((node) => node.shouldFireWriteRejections); + + if (!firingSearchRejectionsNodeUuids.length && !firingWriteRejectionsNodeUuids.length) { + continue; + } + + const searchRejectionsInstanceSuffix = firingSearchRejectionsNodeUuids.map( + (node) => node.meta.nodeId + ); + const writeRejectionsInstanceSuffix = firingWriteRejectionsNodeUuids.map( + (node) => node.meta.nodeId + ); + const instancePrefix = `${this.type}:${cluster.clusterUuid}:`; + + const searchRejectionsInstanceId = `${instancePrefix}:search:${searchRejectionsInstanceSuffix}`; + const writeRejectionsInstanceId = `${instancePrefix}:write:${writeRejectionsInstanceSuffix}`; + + const searchRejectionsInstance = services.alertInstanceFactory(searchRejectionsInstanceId); + const writeRejectionsInstance = services.alertInstanceFactory(writeRejectionsInstanceId); + + const newSearchRejectionsAlertStates: AlertThreadPoolRejectionsState[] = []; + const newWriteRejectionsAlertStates: AlertThreadPoolRejectionsState[] = []; + + for (const node of nodes) { + const stat = node.meta as AlertThreadPoolRejectionsState & { + searchRejections?: number; + writeRejections?: number; + }; + const nodeState = this.getDefaultAlertState( + cluster, + node + ) as AlertThreadPoolRejectionsState; + const { nodeId, nodeName, searchRejections, writeRejections } = stat; + nodeState.nodeId = nodeId; + nodeState.nodeName = nodeName; + nodeState.ui.triggeredMS = currentUTC; + nodeState.ui.isFiring = true; + nodeState.ui.severity = node.severity; + + if (node.shouldFireSearchRejections) { + const newNodeState = this.createNewNodeState( + nodeState, + this.THREAD_POOL_TYPE.search, + searchRejections + ); + newSearchRejectionsAlertStates.push(newNodeState); + } + + if (node.shouldFireWriteRejections) { + const newNodeState = this.createNewNodeState( + nodeState, + this.THREAD_POOL_TYPE.write, + writeRejections + ); + newWriteRejectionsAlertStates.push(newNodeState); + } + } + + const alertSearchRejectionsInstanceState = { alertStates: newSearchRejectionsAlertStates }; + searchRejectionsInstance.replaceState(alertSearchRejectionsInstanceState); + if (newSearchRejectionsAlertStates.length) { + this.executeActions( + searchRejectionsInstance, + newSearchRejectionsAlertStates, + this.THREAD_POOL_TYPE.search, + cluster + ); + } + + const alertWriteRejectionsInstanceState = { alertStates: newWriteRejectionsAlertStates }; + writeRejectionsInstance.replaceState(alertWriteRejectionsInstanceState); + if (newWriteRejectionsAlertStates.length) { + this.executeActions( + writeRejectionsInstance, + newWriteRejectionsAlertStates, + this.THREAD_POOL_TYPE.write, + cluster + ); + } + } + + state.lastChecked = currentUTC; + return state; + } +} diff --git a/x-pack/plugins/monitoring/server/alerts/types.d.ts b/x-pack/plugins/monitoring/server/alerts/types.d.ts index 4b78bca9f47ca..a6dc8a4e9ff69 100644 --- a/x-pack/plugins/monitoring/server/alerts/types.d.ts +++ b/x-pack/plugins/monitoring/server/alerts/types.d.ts @@ -41,6 +41,13 @@ export interface AlertDiskUsageState extends AlertState { nodeName?: string; } +export interface AlertThreadPoolRejectionsState extends AlertState { + count?: number; + type?: 'SEARCH' | 'WRITE' | string; + nodeId: string; + nodeName?: string; +} + export interface AlertUiState { isFiring: boolean; severity: AlertSeverity; @@ -92,6 +99,15 @@ export interface AlertCpuUsageNodeStats { ccs?: string; } +export interface AlertThreadPoolRejectionsStats { + clusterUuid: string; + nodeId: string; + nodeName: string; + searchRejections?: number; + writeRejections?: number; + ccs?: string; +} + export interface AlertDiskUsageNodeStats { clusterUuid: string; nodeId: string; @@ -113,7 +129,7 @@ export interface AlertData { instanceKey: string; clusterUuid: string; ccs?: string; - shouldFire: boolean; + shouldFire?: boolean; severity: AlertSeverity; meta: any; } diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_thread_pool_rejections_stats.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_thread_pool_rejections_stats.ts new file mode 100644 index 0000000000000..adecb64f0a571 --- /dev/null +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_thread_pool_rejections_stats.ts @@ -0,0 +1,145 @@ +/* + * 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 { get } from 'lodash'; +import { AlertCluster, AlertThreadPoolRejectionsStats } from '../../alerts/types'; + +interface MaxField { + max: { + field: 'node_stats.thread_pool.search.rejected' | 'node_stats.thread_pool.write.rejected'; + }; +} + +interface RejectionsType { + max_search_rejections?: MaxField; + max_write_rejections?: MaxField; +} + +const getRejectionsType = (search: boolean = true, write: boolean = true) => { + const rejections: RejectionsType = { + max_search_rejections: { + max: { + field: 'node_stats.thread_pool.search.rejected', + }, + }, + max_write_rejections: { + max: { + field: 'node_stats.thread_pool.write.rejected', + }, + }, + }; + if (!search) { + delete rejections.max_search_rejections; + } + if (!write) { + delete rejections.max_write_rejections; + } + return rejections; +}; + +const invalidNumberValue = (value: number) => { + return isNaN(value) || value === undefined || value === null; +}; + +export async function fetchThreadPoolRejectionStats( + callCluster: any, + clusters: AlertCluster[], + index: string, + size: number, + searchRejections?: boolean, + writeRejections?: boolean +): Promise { + const clustersIds = clusters.map((cluster) => cluster.clusterUuid); + const params = { + index, + filterPath: ['aggregations'], + body: { + size: 0, + query: { + bool: { + filter: [ + { + terms: { + cluster_uuid: clustersIds, + }, + }, + { + term: { + type: 'node_stats', + }, + }, + { + range: { + timestamp: { + gte: 'now-5m', + }, + }, + }, + ], + }, + }, + aggs: { + clusters: { + terms: { + field: 'cluster_uuid', + size, + }, + aggs: { + nodes: { + terms: { + field: 'source_node.uuid', + size, + }, + aggs: { + index: { + terms: { + field: '_index', + size: 1, + }, + }, + ...getRejectionsType(searchRejections, writeRejections), + name: { + terms: { + field: 'source_node.name', + size: 1, + }, + }, + }, + }, + }, + }, + }, + }, + }; + + const response = await callCluster('search', params); + const stats: AlertThreadPoolRejectionsStats[] = []; + const { buckets: clusterBuckets = [] } = response.aggregations.clusters; + + if (!clusterBuckets.length) { + return stats; + } + + for (const clusterBucket of clusterBuckets) { + for (const node of clusterBucket.nodes.buckets) { + const indexName = get(node, 'index.buckets[0].key', ''); + const searchRejectionsValue = Number(get(node, 'max_search_rejections.value')); + const writeRejectionsValue = Number(get(node, 'max_write_rejections.value')); + if (invalidNumberValue(searchRejectionsValue) && invalidNumberValue(writeRejectionsValue)) { + continue; + } + stats.push({ + searchRejections: searchRejectionsValue, + writeRejections: writeRejectionsValue, + clusterUuid: clusterBucket.key, + nodeId: node.key, + nodeName: get(node, 'name.buckets[0].key') || node.key, + ccs: indexName.includes(':') ? indexName.split(':')[0] : null, + }); + } + } + return stats; +} From a666da5e789dfe1451f2905f0e2d55a149469e5f Mon Sep 17 00:00:00 2001 From: Igor Zaytsev Date: Tue, 6 Oct 2020 19:34:07 -0400 Subject: [PATCH 2/7] Split search and write rejections to seperate alerts --- x-pack/plugins/monitoring/common/constants.ts | 6 +- x-pack/plugins/monitoring/common/enums.ts | 1 + x-pack/plugins/monitoring/common/types.ts | 10 +- .../alerts/components/duration/expression.tsx | 12 + .../alert_param_duration.tsx | 2 +- .../flyout_expressions/alert_param_number.tsx | 36 ++ .../alert_param_number_toggle.tsx | 62 --- .../expression.tsx | 52 --- .../thread_pool_rejections_alert/index.tsx | 70 ++- .../cluster/overview/elasticsearch_panel.js | 6 +- x-pack/plugins/monitoring/public/plugin.ts | 10 +- .../elasticsearch/node/advanced/index.js | 6 +- .../public/views/elasticsearch/node/index.js | 6 +- .../public/views/elasticsearch/nodes/index.js | 6 +- .../server/alerts/alerts_factory.ts | 9 +- .../plugins/monitoring/server/alerts/index.ts | 3 +- .../alerts/thread_pool_rejections_alert.ts | 429 ------------------ .../thread_pool_rejections_alert_base.ts | 336 ++++++++++++++ .../thread_pool_search_rejections_alert.ts | 31 ++ .../thread_pool_write_rejections_alert.ts | 31 ++ .../monitoring/server/alerts/types.d.ts | 11 +- .../fetch_thread_pool_rejections_stats.ts | 106 ++--- 22 files changed, 576 insertions(+), 665 deletions(-) create mode 100644 x-pack/plugins/monitoring/public/alerts/flyout_expressions/alert_param_number.tsx delete mode 100644 x-pack/plugins/monitoring/public/alerts/flyout_expressions/alert_param_number_toggle.tsx delete mode 100644 x-pack/plugins/monitoring/public/alerts/thread_pool_rejections_alert/expression.tsx delete mode 100644 x-pack/plugins/monitoring/server/alerts/thread_pool_rejections_alert.ts create mode 100644 x-pack/plugins/monitoring/server/alerts/thread_pool_rejections_alert_base.ts create mode 100644 x-pack/plugins/monitoring/server/alerts/thread_pool_search_rejections_alert.ts create mode 100644 x-pack/plugins/monitoring/server/alerts/thread_pool_write_rejections_alert.ts diff --git a/x-pack/plugins/monitoring/common/constants.ts b/x-pack/plugins/monitoring/common/constants.ts index dd3ef625b7f3a..d0a085e58b727 100644 --- a/x-pack/plugins/monitoring/common/constants.ts +++ b/x-pack/plugins/monitoring/common/constants.ts @@ -238,7 +238,8 @@ export const ALERT_KIBANA_VERSION_MISMATCH = `${ALERT_PREFIX}alert_kibana_versio export const ALERT_LOGSTASH_VERSION_MISMATCH = `${ALERT_PREFIX}alert_logstash_version_mismatch`; export const ALERT_MEMORY_USAGE = `${ALERT_PREFIX}alert_jvm_memory_usage`; export const ALERT_MISSING_MONITORING_DATA = `${ALERT_PREFIX}alert_missing_monitoring_data`; -export const ALERT_THREAD_POOL_REJECTIONS = `${ALERT_PREFIX}alert_thread_pool_rejections_data`; +export const ALERT_THREAD_POOL_SEARCH_REJECTIONS = `${ALERT_PREFIX}alert_thread_pool_search_rejections`; +export const ALERT_THREAD_POOL_WRITE_REJECTIONS = `${ALERT_PREFIX}alert_thread_pool_write_rejections`; /** * A listing of all alert types @@ -254,7 +255,8 @@ export const ALERTS = [ ALERT_LOGSTASH_VERSION_MISMATCH, ALERT_MEMORY_USAGE, ALERT_MISSING_MONITORING_DATA, - ALERT_THREAD_POOL_REJECTIONS, + ALERT_THREAD_POOL_SEARCH_REJECTIONS, + ALERT_THREAD_POOL_WRITE_REJECTIONS, ]; /** diff --git a/x-pack/plugins/monitoring/common/enums.ts b/x-pack/plugins/monitoring/common/enums.ts index d4058e9de801e..b373428bb279b 100644 --- a/x-pack/plugins/monitoring/common/enums.ts +++ b/x-pack/plugins/monitoring/common/enums.ts @@ -25,6 +25,7 @@ export enum AlertMessageTokenType { export enum AlertParamType { Duration = 'duration', Percentage = 'percentage', + Number = 'number', } export enum SetupModeFeature { diff --git a/x-pack/plugins/monitoring/common/types.ts b/x-pack/plugins/monitoring/common/types.ts index 9568664c486e5..d622d091f34cf 100644 --- a/x-pack/plugins/monitoring/common/types.ts +++ b/x-pack/plugins/monitoring/common/types.ts @@ -53,12 +53,6 @@ export interface CommonAlertParams { } export interface ThreadPoolRejectionsAlertParams { - search: { - threshold: number; - enabled: boolean; - }; - write: { - threshold: number; - enabled: boolean; - }; + threshold: number; + duration: string; } diff --git a/x-pack/plugins/monitoring/public/alerts/components/duration/expression.tsx b/x-pack/plugins/monitoring/public/alerts/components/duration/expression.tsx index 2df7169efc675..0ca7e1a459995 100644 --- a/x-pack/plugins/monitoring/public/alerts/components/duration/expression.tsx +++ b/x-pack/plugins/monitoring/public/alerts/components/duration/expression.tsx @@ -10,6 +10,7 @@ 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 { AlertParamNumber } from '../../flyout_expressions/alert_param_number'; export interface Props { alertParams: { [property: string]: any }; @@ -49,6 +50,17 @@ export const Expression: React.FC = (props) => { setAlertParams={setAlertParams} /> ); + case AlertParamType.Number: + return ( + + ); } }); diff --git a/x-pack/plugins/monitoring/public/alerts/flyout_expressions/alert_param_duration.tsx b/x-pack/plugins/monitoring/public/alerts/flyout_expressions/alert_param_duration.tsx index 862f32efd7361..4ece1b0c81827 100644 --- a/x-pack/plugins/monitoring/public/alerts/flyout_expressions/alert_param_duration.tsx +++ b/x-pack/plugins/monitoring/public/alerts/flyout_expressions/alert_param_duration.tsx @@ -69,7 +69,7 @@ export const AlertParamDuration: React.FC = (props: Props) => { }, [unit, value]); return ( - 0}> + 0}> void; +} +export const AlertParamNumber: React.FC = (props: Props) => { + const { name, label, setAlertParams, errors } = props; + const [value, setValue] = useState(props.value); + return ( + 0}> + { + let newValue = Number(e.target.value); + if (isNaN(newValue)) { + newValue = 0; + } + setValue(newValue); + setAlertParams(name, newValue); + }} + /> + + ); +}; diff --git a/x-pack/plugins/monitoring/public/alerts/flyout_expressions/alert_param_number_toggle.tsx b/x-pack/plugins/monitoring/public/alerts/flyout_expressions/alert_param_number_toggle.tsx deleted file mode 100644 index 6ebb48a2784ff..0000000000000 --- a/x-pack/plugins/monitoring/public/alerts/flyout_expressions/alert_param_number_toggle.tsx +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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, { useState } from 'react'; -import { EuiFormRow, EuiFieldNumber, EuiSwitch, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; - -interface ValueType { - value: number; - enabled: boolean; -} - -interface Props { - name: string; - initialState: ValueType; - label: string; - errors: string[]; - setAlertParams: (property: string, newValue: ValueType) => void; -} -export const AlertParamNumberToggle: React.FC = (props: Props) => { - const { name, label, initialState, setAlertParams, errors } = props; - const [value, setValue] = useState(initialState.value); - const [isDisabled, setDisabled] = useState(!initialState.enabled); - - const setLocalState = (newValue: number, enabled: boolean) => { - setAlertParams(name, { value: newValue, enabled }); - }; - - return ( - 0}> - - - { - let newValue = Number(e.target.value); - if (isNaN(newValue)) { - newValue = 0; - } - setValue(newValue); - setLocalState(newValue, !isDisabled); - }} - /> - - - { - const bool = e.target.checked; - setDisabled(!bool); - setLocalState(value, bool); - }} - /> - - - - ); -}; diff --git a/x-pack/plugins/monitoring/public/alerts/thread_pool_rejections_alert/expression.tsx b/x-pack/plugins/monitoring/public/alerts/thread_pool_rejections_alert/expression.tsx deleted file mode 100644 index 120068b956647..0000000000000 --- a/x-pack/plugins/monitoring/public/alerts/thread_pool_rejections_alert/expression.tsx +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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, { Fragment } from 'react'; -import { EuiForm, EuiSpacer } from '@elastic/eui'; -import { AlertParamNumberToggle } from '../flyout_expressions/alert_param_number_toggle'; - -import { Props } from '.'; - -export const Expression: React.FC = (props) => { - const { alertParams, paramDetails, setAlertParams, errors } = props; - const alertParamsUi = Object.keys(alertParams).map((name) => { - const { label } = paramDetails[name]; - const { threshold: value, enabled } = alertParams[name] as { - threshold: number; - enabled: boolean; - }; - const initialState = { - value, - enabled, - }; - - return ( - { - setAlertParams(paramName, { - threshold: newState.value, - enabled: newState.enabled, - }); - }, - errors: errors[name] as string[], - }} - /> - ); - }); - - return ( - - - {alertParamsUi} - - - ); -}; diff --git a/x-pack/plugins/monitoring/public/alerts/thread_pool_rejections_alert/index.tsx b/x-pack/plugins/monitoring/public/alerts/thread_pool_rejections_alert/index.tsx index 22295e32c6d60..a54921f387234 100644 --- a/x-pack/plugins/monitoring/public/alerts/thread_pool_rejections_alert/index.tsx +++ b/x-pack/plugins/monitoring/public/alerts/thread_pool_rejections_alert/index.tsx @@ -6,57 +6,53 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { Expression } from './expression'; +import { EuiSpacer } from '@elastic/eui'; +import { Expression, Props } from '../components/duration/expression'; -import { - AlertTypeModel, - AlertTypeParamsExpressionProps, -} from '../../../../triggers_actions_ui/public'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { ThreadPoolRejectionsAlert } from '../../../server/alerts'; +import { AlertTypeModel } from '../../../../triggers_actions_ui/public'; -interface ThreadPoolRejectionsParam { - threshold: number; - enabled: boolean; -} - -interface ParamDetails { - search: { label: string }; - write: { label: string }; - [key: string]: { label: string }; -} +import { CommonAlertParamDetails } from '../../../common/types'; interface ThreadPoolTypes { - [key: string]: ThreadPoolRejectionsParam; + [key: string]: unknown; } -export interface Props extends AlertTypeParamsExpressionProps { - paramDetails: ParamDetails; - alertParams: { [key: string]: unknown }; +interface ThreadPoolRejectionAlertClass { + TYPE: string; + LABEL: string; + PARAM_DETAILS: CommonAlertParamDetails; } -export function createThreadPoolRejectionsAlertType(): AlertTypeModel { +export function createThreadPoolRejectionsAlertType( + threadPoolAlertClass: ThreadPoolRejectionAlertClass +): AlertTypeModel { return { - id: ThreadPoolRejectionsAlert.TYPE, - name: ThreadPoolRejectionsAlert.LABEL, + id: threadPoolAlertClass.TYPE, + name: threadPoolAlertClass.LABEL, iconClass: 'bell', alertParamsExpression: (props: Props) => ( - + <> + + + ), - validate: (recentState: ThreadPoolTypes) => { + validate: (inputValues: ThreadPoolTypes) => { const errors: { [key: string]: string[] } = {}; - for (const key in recentState) { - if (!recentState.hasOwnProperty(key)) { - continue; - } - const value = recentState[key].threshold; - if (value < 0) { - const errStr = i18n.translate('xpack.monitoring.alerts.validation.lessThanZero', { - defaultMessage: `This value can not be less than zero`, - }); - errors[key] = [errStr]; - } + const value = inputValues.threshold as number; + if (value < 0) { + const errStr = i18n.translate('xpack.monitoring.alerts.validation.lessThanZero', { + defaultMessage: 'This value can not be less than zero', + }); + errors.threshold = [errStr]; } + + if (!inputValues.duration) { + const errStr = i18n.translate('xpack.monitoring.alerts.validation.duration', { + defaultMessage: 'A valid duration is required.', + }); + errors.duration = [errStr]; + } + return { errors }; }, defaultActionMessage: '{{context.internalFullMessage}}', diff --git a/x-pack/plugins/monitoring/public/components/cluster/overview/elasticsearch_panel.js b/x-pack/plugins/monitoring/public/components/cluster/overview/elasticsearch_panel.js index 3ecf824f7acfc..1a7fc15e0da31 100644 --- a/x-pack/plugins/monitoring/public/components/cluster/overview/elasticsearch_panel.js +++ b/x-pack/plugins/monitoring/public/components/cluster/overview/elasticsearch_panel.js @@ -41,7 +41,8 @@ import { ALERT_CLUSTER_HEALTH, ALERT_CPU_USAGE, ALERT_DISK_USAGE, - ALERT_THREAD_POOL_REJECTIONS, + ALERT_THREAD_POOL_SEARCH_REJECTIONS, + ALERT_THREAD_POOL_WRITE_REJECTIONS, ALERT_MEMORY_USAGE, ALERT_NODES_CHANGED, ALERT_ELASTICSEARCH_VERSION_MISMATCH, @@ -162,7 +163,8 @@ const OVERVIEW_PANEL_ALERTS = [ALERT_CLUSTER_HEALTH, ALERT_LICENSE_EXPIRATION]; const NODES_PANEL_ALERTS = [ ALERT_CPU_USAGE, ALERT_DISK_USAGE, - ALERT_THREAD_POOL_REJECTIONS, + ALERT_THREAD_POOL_SEARCH_REJECTIONS, + ALERT_THREAD_POOL_WRITE_REJECTIONS, ALERT_MEMORY_USAGE, ALERT_NODES_CHANGED, ALERT_ELASTICSEARCH_VERSION_MISMATCH, diff --git a/x-pack/plugins/monitoring/public/plugin.ts b/x-pack/plugins/monitoring/public/plugin.ts index d4015f1510946..81862f4927118 100644 --- a/x-pack/plugins/monitoring/public/plugin.ts +++ b/x-pack/plugins/monitoring/public/plugin.ts @@ -29,6 +29,11 @@ import { createDiskUsageAlertType } from './alerts/disk_usage_alert'; import { createThreadPoolRejectionsAlertType } from './alerts/thread_pool_rejections_alert'; import { createMemoryUsageAlertType } from './alerts/memory_usage_alert'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { ThreadPoolSearchRejectionsAlert } from '../server/alerts'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { ThreadPoolWriteRejectionsAlert } from '../server/alerts'; + interface MonitoringSetupPluginDependencies { home?: HomePublicPluginSetup; cloud?: { isCloudEnabled: boolean }; @@ -79,7 +84,10 @@ export class MonitoringPlugin alertTypeRegistry.register(createDiskUsageAlertType()); alertTypeRegistry.register(createMemoryUsageAlertType()); alertTypeRegistry.register(createMissingMonitoringDataAlertType()); - alertTypeRegistry.register(createThreadPoolRejectionsAlertType()); + alertTypeRegistry.register( + createThreadPoolRejectionsAlertType(ThreadPoolSearchRejectionsAlert) + ); + alertTypeRegistry.register(createThreadPoolRejectionsAlertType(ThreadPoolWriteRejectionsAlert)); const legacyAlertTypes = createLegacyAlertTypes(); for (const legacyAlertType of legacyAlertTypes) { diff --git a/x-pack/plugins/monitoring/public/views/elasticsearch/node/advanced/index.js b/x-pack/plugins/monitoring/public/views/elasticsearch/node/advanced/index.js index f8fbeaf34ad7c..a84cae43c2dc4 100644 --- a/x-pack/plugins/monitoring/public/views/elasticsearch/node/advanced/index.js +++ b/x-pack/plugins/monitoring/public/views/elasticsearch/node/advanced/index.js @@ -20,7 +20,8 @@ import { MonitoringViewBaseController } from '../../../base_controller'; import { CODE_PATH_ELASTICSEARCH, ALERT_CPU_USAGE, - ALERT_THREAD_POOL_REJECTIONS, + ALERT_THREAD_POOL_SEARCH_REJECTIONS, + ALERT_THREAD_POOL_WRITE_REJECTIONS, ALERT_MISSING_MONITORING_DATA, ALERT_DISK_USAGE, ALERT_MEMORY_USAGE, @@ -77,7 +78,8 @@ uiRoutes.when('/elasticsearch/nodes/:node/advanced', { alertTypeIds: [ ALERT_CPU_USAGE, ALERT_DISK_USAGE, - ALERT_THREAD_POOL_REJECTIONS, + ALERT_THREAD_POOL_SEARCH_REJECTIONS, + ALERT_THREAD_POOL_WRITE_REJECTIONS, ALERT_MEMORY_USAGE, ALERT_MISSING_MONITORING_DATA, ], diff --git a/x-pack/plugins/monitoring/public/views/elasticsearch/node/index.js b/x-pack/plugins/monitoring/public/views/elasticsearch/node/index.js index 1e803b6a3baf6..586261eecb250 100644 --- a/x-pack/plugins/monitoring/public/views/elasticsearch/node/index.js +++ b/x-pack/plugins/monitoring/public/views/elasticsearch/node/index.js @@ -21,7 +21,8 @@ import { MonitoringViewBaseController } from '../../base_controller'; import { CODE_PATH_ELASTICSEARCH, ALERT_CPU_USAGE, - ALERT_THREAD_POOL_REJECTIONS, + ALERT_THREAD_POOL_SEARCH_REJECTIONS, + ALERT_THREAD_POOL_WRITE_REJECTIONS, ALERT_MISSING_MONITORING_DATA, ALERT_DISK_USAGE, ALERT_MEMORY_USAGE, @@ -61,7 +62,8 @@ uiRoutes.when('/elasticsearch/nodes/:node', { alertTypeIds: [ ALERT_CPU_USAGE, ALERT_DISK_USAGE, - ALERT_THREAD_POOL_REJECTIONS, + ALERT_THREAD_POOL_SEARCH_REJECTIONS, + ALERT_THREAD_POOL_WRITE_REJECTIONS, ALERT_MEMORY_USAGE, ALERT_MISSING_MONITORING_DATA, ], diff --git a/x-pack/plugins/monitoring/public/views/elasticsearch/nodes/index.js b/x-pack/plugins/monitoring/public/views/elasticsearch/nodes/index.js index f634629118652..570fb627fb2a9 100644 --- a/x-pack/plugins/monitoring/public/views/elasticsearch/nodes/index.js +++ b/x-pack/plugins/monitoring/public/views/elasticsearch/nodes/index.js @@ -19,7 +19,8 @@ import { ELASTICSEARCH_SYSTEM_ID, CODE_PATH_ELASTICSEARCH, ALERT_CPU_USAGE, - ALERT_THREAD_POOL_REJECTIONS, + ALERT_THREAD_POOL_SEARCH_REJECTIONS, + ALERT_THREAD_POOL_WRITE_REJECTIONS, ALERT_MISSING_MONITORING_DATA, ALERT_DISK_USAGE, ALERT_MEMORY_USAGE, @@ -93,7 +94,8 @@ uiRoutes.when('/elasticsearch/nodes', { alertTypeIds: [ ALERT_CPU_USAGE, ALERT_DISK_USAGE, - ALERT_THREAD_POOL_REJECTIONS, + ALERT_THREAD_POOL_SEARCH_REJECTIONS, + ALERT_THREAD_POOL_WRITE_REJECTIONS, ALERT_MEMORY_USAGE, ALERT_MISSING_MONITORING_DATA, ], diff --git a/x-pack/plugins/monitoring/server/alerts/alerts_factory.ts b/x-pack/plugins/monitoring/server/alerts/alerts_factory.ts index 39bae8c3a3456..f66338e838d8e 100644 --- a/x-pack/plugins/monitoring/server/alerts/alerts_factory.ts +++ b/x-pack/plugins/monitoring/server/alerts/alerts_factory.ts @@ -8,7 +8,8 @@ import { CpuUsageAlert, MissingMonitoringDataAlert, DiskUsageAlert, - ThreadPoolRejectionsAlert, + ThreadPoolSearchRejectionsAlert, + ThreadPoolWriteRejectionsAlert, MemoryUsageAlert, NodesChangedAlert, ClusterHealthAlert, @@ -24,7 +25,8 @@ import { ALERT_CPU_USAGE, ALERT_MISSING_MONITORING_DATA, ALERT_DISK_USAGE, - ALERT_THREAD_POOL_REJECTIONS, + ALERT_THREAD_POOL_SEARCH_REJECTIONS, + ALERT_THREAD_POOL_WRITE_REJECTIONS, ALERT_MEMORY_USAGE, ALERT_NODES_CHANGED, ALERT_LOGSTASH_VERSION_MISMATCH, @@ -39,7 +41,8 @@ export const BY_TYPE = { [ALERT_CPU_USAGE]: CpuUsageAlert, [ALERT_MISSING_MONITORING_DATA]: MissingMonitoringDataAlert, [ALERT_DISK_USAGE]: DiskUsageAlert, - [ALERT_THREAD_POOL_REJECTIONS]: ThreadPoolRejectionsAlert, + [ALERT_THREAD_POOL_SEARCH_REJECTIONS]: ThreadPoolSearchRejectionsAlert, + [ALERT_THREAD_POOL_WRITE_REJECTIONS]: ThreadPoolWriteRejectionsAlert, [ALERT_MEMORY_USAGE]: MemoryUsageAlert, [ALERT_NODES_CHANGED]: NodesChangedAlert, [ALERT_LOGSTASH_VERSION_MISMATCH]: LogstashVersionMismatchAlert, diff --git a/x-pack/plugins/monitoring/server/alerts/index.ts b/x-pack/plugins/monitoring/server/alerts/index.ts index b460950a90ff7..17a4826806d1c 100644 --- a/x-pack/plugins/monitoring/server/alerts/index.ts +++ b/x-pack/plugins/monitoring/server/alerts/index.ts @@ -8,7 +8,8 @@ export { BaseAlert } from './base_alert'; export { CpuUsageAlert } from './cpu_usage_alert'; export { MissingMonitoringDataAlert } from './missing_monitoring_data_alert'; export { DiskUsageAlert } from './disk_usage_alert'; -export { ThreadPoolRejectionsAlert } from './thread_pool_rejections_alert'; +export { ThreadPoolSearchRejectionsAlert } from './thread_pool_search_rejections_alert'; +export { ThreadPoolWriteRejectionsAlert } from './thread_pool_write_rejections_alert'; export { MemoryUsageAlert } from './memory_usage_alert'; export { ClusterHealthAlert } from './cluster_health_alert'; export { LicenseExpirationAlert } from './license_expiration_alert'; diff --git a/x-pack/plugins/monitoring/server/alerts/thread_pool_rejections_alert.ts b/x-pack/plugins/monitoring/server/alerts/thread_pool_rejections_alert.ts deleted file mode 100644 index 4340bd2dcc485..0000000000000 --- a/x-pack/plugins/monitoring/server/alerts/thread_pool_rejections_alert.ts +++ /dev/null @@ -1,429 +0,0 @@ -/* - * 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 { IUiSettingsClient, Logger } from 'kibana/server'; -import { i18n } from '@kbn/i18n'; -import { BaseAlert } from './base_alert'; -import { - AlertData, - AlertCluster, - AlertState, - AlertMessage, - AlertThreadPoolRejectionsState, - AlertMessageTimeToken, - AlertMessageLinkToken, -} from './types'; -import { AlertInstance, AlertServices } from '../../../alerts/server'; -import { INDEX_PATTERN_ELASTICSEARCH, ALERT_THREAD_POOL_REJECTIONS } from '../../common/constants'; -import { fetchThreadPoolRejectionStats } from '../lib/alerts/fetch_thread_pool_rejections_stats'; -import { getCcsIndexPattern } from '../lib/alerts/get_ccs_index_pattern'; -import { AlertMessageTokenType, AlertSeverity } from '../../common/enums'; -import { RawAlertInstance } from '../../../alerts/common'; -import { - CommonAlertFilter, - ThreadPoolRejectionsAlertParams, - CommonAlertParamDetail, -} from '../../common/types'; -import { AlertingDefaults, createLink } from './alerts_common'; -import { appendMetricbeatIndex } from '../lib/alerts/append_mb_index'; - -type ThreadPoolType = 'SEARCH' | 'WRITE' | string; - -interface MessageOptions { - count?: number; - type?: ThreadPoolType; - nodeName?: string; - nodeId: string; -} - -interface RejectionsShouldFire { - shouldFireSearchRejections?: boolean; - shouldFireWriteRejections?: boolean; -} - -type ThreadPoolAlertData = Omit & RejectionsShouldFire; - -interface ThreadpoolParamDetails { - search: CommonAlertParamDetail; - write: CommonAlertParamDetail; - [key: string]: CommonAlertParamDetail; -} - -export class ThreadPoolRejectionsAlert extends BaseAlert { - public static readonly PARAM_DETAILS: ThreadpoolParamDetails = { - search: { - label: i18n.translate( - 'xpack.monitoring.alerts.searchRejection.paramDetails.threshold.label', - { - defaultMessage: `SEARCH rejection`, - } - ), - }, - write: { - label: i18n.translate('xpack.monitoring.alerts.writeRejection.paramDetails.threshold.label', { - defaultMessage: `WRITE rejection`, - }), - }, - }; - public static paramDetails = ThreadPoolRejectionsAlert.PARAM_DETAILS; - public static readonly TYPE = ALERT_THREAD_POOL_REJECTIONS; - public static readonly LABEL = i18n.translate( - 'xpack.monitoring.alerts.threadPoolRejections.label', - { - defaultMessage: 'Thread Pool Rejections', - } - ); - - private readonly THREAD_POOL_TYPE = { - search: 'SEARCH', - write: 'WRITE', - }; - - public type = ThreadPoolRejectionsAlert.TYPE; - public label = ThreadPoolRejectionsAlert.LABEL; - - protected defaultParams: ThreadPoolRejectionsAlertParams = { - search: { - threshold: 0, - enabled: true, - }, - write: { - threshold: 0, - enabled: true, - }, - }; - - protected actionVariables = [ - { - name: 'count', - description: i18n.translate( - 'xpack.monitoring.alerts.threadPoolRejections.actionVariables.count', - { - defaultMessage: 'The number of nodes reporting high thread pool rejections.', - } - ), - }, - { - name: 'threadPoolType', - description: i18n.translate( - 'xpack.monitoring.alerts.threadPoolRejections.actionVariables.threadPoolType', - { - defaultMessage: 'Rejected thread pool type eg: SEARCH, WRITE, and etc.', - } - ), - }, - ...Object.values(AlertingDefaults.ALERT_TYPE.context), - ]; - - protected async fetchData( - params: ThreadPoolRejectionsAlertParams, - callCluster: any, - clusters: AlertCluster[], - uiSettings: IUiSettingsClient, - availableCcs: string[] - ): Promise { - let esIndexPattern = appendMetricbeatIndex(this.config, INDEX_PATTERN_ELASTICSEARCH); - if (availableCcs) { - esIndexPattern = getCcsIndexPattern(esIndexPattern, availableCcs); - } - - const { search, write } = params; - const { threshold: searchRejectionsThreshold, enabled: searchRejectionsEnabled } = search; - const { threshold: writeRejectionsThreshold, enabled: writeRejectionsEnabled } = write; - const checkSearchRejections = searchRejectionsEnabled && searchRejectionsThreshold > 0; - const checkWriteRejections = writeRejectionsEnabled && writeRejectionsThreshold > 0; - - const stats = await fetchThreadPoolRejectionStats( - callCluster, - clusters, - esIndexPattern, - this.config.ui.max_bucket_size, - checkSearchRejections, - checkWriteRejections - ); - - return stats.map((stat) => { - const { clusterUuid, nodeId, searchRejections, writeRejections, ccs } = stat; - const shouldFireSearchRejections = - checkSearchRejections && searchRejections! >= searchRejectionsThreshold; - const shouldFireWriteRejections = - checkWriteRejections && writeRejections! >= writeRejectionsThreshold; - return { - instanceKey: `${clusterUuid}:${nodeId}`, - shouldFireSearchRejections, - shouldFireWriteRejections, - searchRejections, - writeRejections, - severity: AlertSeverity.Danger, - meta: stat, - clusterUuid, - ccs, - }; - }); - } - - protected filterAlertInstance(alertInstance: RawAlertInstance, filters: CommonAlertFilter[]) { - const alertInstanceStates = alertInstance.state - ?.alertStates as AlertThreadPoolRejectionsState[]; - const nodeUuid = filters?.find((filter) => filter.nodeUuid)?.nodeUuid; - - if (!alertInstanceStates?.length || !nodeUuid) { - return true; - } - - const nodeAlerts = alertInstanceStates.filter(({ nodeId }) => nodeId === nodeUuid); - return Boolean(nodeAlerts.length); - } - - protected getUiMessage(alertState: AlertState, options: MessageOptions): AlertMessage { - const { nodeName, nodeId, type, count } = options; - return { - text: i18n.translate('xpack.monitoring.alerts.threadPoolRejections.ui.firingMessage', { - defaultMessage: `Node #start_link{nodeName}#end_link is reporting {count} {type} rejections at #absolute`, - values: { - nodeName, - type, - count, - }, - }), - nextSteps: [ - createLink( - i18n.translate( - 'xpack.monitoring.alerts.threadPoolRejections.ui.nextSteps.tuneThreadPools', - { - defaultMessage: '#start_linkTune thread pools#end_link', - } - ), - `{elasticWebsiteUrl}guide/en/elasticsearch/reference/{docLinkVersion}/modules-threadpool.html` - ), - createLink( - i18n.translate( - 'xpack.monitoring.alerts.threadPoolRejections.ui.nextSteps.identifyIndicesShards', - { - defaultMessage: '#start_linkIdentify large indices/shards#end_link', - } - ), - 'elasticsearch/indices', - AlertMessageTokenType.Link - ), - createLink( - i18n.translate('xpack.monitoring.alerts.threadPoolRejections.ui.nextSteps.addMoreNodes', { - defaultMessage: '#start_linkAdd more nodes#end_link', - }), - `{elasticWebsiteUrl}guide/en/elasticsearch/reference/{docLinkVersion}/add-elasticsearch-nodes.html` - ), - createLink( - i18n.translate( - 'xpack.monitoring.alerts.threadPoolRejections.ui.nextSteps.resizeYourDeployment', - { - defaultMessage: '#start_linkResize your deployment (ECE)#end_link', - } - ), - `{elasticWebsiteUrl}guide/en/cloud-enterprise/current/ece-resize-deployment.html` - ), - ], - tokens: [ - { - startToken: '#absolute', - type: AlertMessageTokenType.Time, - isAbsolute: true, - isRelative: false, - timestamp: alertState.ui.triggeredMS, - } as AlertMessageTimeToken, - { - startToken: '#start_link', - endToken: '#end_link', - type: AlertMessageTokenType.Link, - url: `elasticsearch/nodes/${nodeId}`, - } as AlertMessageLinkToken, - ], - }; - } - - protected executeActions( - instance: AlertInstance, - alertStates: any[], - type: ThreadPoolType, - cluster: AlertCluster - ) { - const count = alertStates.length; - const { clusterName: clusterKnownName, clusterUuid } = cluster; - const clusterName = clusterKnownName || clusterUuid; - const shortActionText = i18n.translate( - 'xpack.monitoring.alerts.threadPoolRejections.shortAction', - { - defaultMessage: 'Verify {type} thread pool rejections across affected nodes.', - values: { - type, - }, - } - ); - - const fullActionText = i18n.translate( - 'xpack.monitoring.alerts.threadPoolRejections.fullAction', - { - defaultMessage: 'View nodes', - } - ); - - const ccs = alertStates.find((state) => state.ccs)?.ccs; - const globalStateLink = this.createGlobalStateLink('elasticsearch/nodes', clusterUuid, ccs); - - const action = `[${fullActionText}](${globalStateLink})`; - const internalShortMessage = i18n.translate( - 'xpack.monitoring.alerts.threadPoolRejections.firing.internalShortMessage', - { - defaultMessage: `Thread pool rejections alert is firing for {count} node(s) in cluster: {clusterName}. {shortActionText}`, - values: { - count, - clusterName, - shortActionText, - }, - } - ); - const internalFullMessage = i18n.translate( - 'xpack.monitoring.alerts.threadPoolRejections.firing.internalFullMessage', - { - defaultMessage: `Thread pool rejections alert is firing for {count} node(s) in cluster: {clusterName}. {action}`, - values: { - count, - clusterName, - action, - }, - } - ); - - instance.scheduleActions('default', { - internalShortMessage, - internalFullMessage: this.isCloud ? internalShortMessage : internalFullMessage, - threadPoolType: type, - state: AlertingDefaults.ALERT_STATE.firing, - count, - clusterName, - action, - actionPlain: shortActionText, - }); - } - - private createNewNodeState( - nodeState: AlertThreadPoolRejectionsState, - type: ThreadPoolType, - count?: number - ) { - const newNodeState: AlertThreadPoolRejectionsState = { ...nodeState, type, count }; - const { nodeId, nodeName } = nodeState; - const messageOptions: MessageOptions = { - nodeId, - nodeName, - type, - count, - }; - const message = this.getUiMessage(nodeState, messageOptions); - newNodeState.ui = { ...nodeState.ui, message }; - return newNodeState; - } - - protected async processData( - data: ThreadPoolAlertData[], - clusters: AlertCluster[], - services: AlertServices, - logger: Logger, - state: { lastChecked?: number } - ) { - const currentUTC = +new Date(); - for (const cluster of clusters) { - const nodes = data.filter((node) => node.clusterUuid === cluster.clusterUuid); - if (!nodes.length) { - continue; - } - - const firingSearchRejectionsNodeUuids = nodes.filter( - (node) => node.shouldFireSearchRejections - ); - const firingWriteRejectionsNodeUuids = nodes.filter((node) => node.shouldFireWriteRejections); - - if (!firingSearchRejectionsNodeUuids.length && !firingWriteRejectionsNodeUuids.length) { - continue; - } - - const searchRejectionsInstanceSuffix = firingSearchRejectionsNodeUuids.map( - (node) => node.meta.nodeId - ); - const writeRejectionsInstanceSuffix = firingWriteRejectionsNodeUuids.map( - (node) => node.meta.nodeId - ); - const instancePrefix = `${this.type}:${cluster.clusterUuid}:`; - - const searchRejectionsInstanceId = `${instancePrefix}:search:${searchRejectionsInstanceSuffix}`; - const writeRejectionsInstanceId = `${instancePrefix}:write:${writeRejectionsInstanceSuffix}`; - - const searchRejectionsInstance = services.alertInstanceFactory(searchRejectionsInstanceId); - const writeRejectionsInstance = services.alertInstanceFactory(writeRejectionsInstanceId); - - const newSearchRejectionsAlertStates: AlertThreadPoolRejectionsState[] = []; - const newWriteRejectionsAlertStates: AlertThreadPoolRejectionsState[] = []; - - for (const node of nodes) { - const stat = node.meta as AlertThreadPoolRejectionsState & { - searchRejections?: number; - writeRejections?: number; - }; - const nodeState = this.getDefaultAlertState( - cluster, - node - ) as AlertThreadPoolRejectionsState; - const { nodeId, nodeName, searchRejections, writeRejections } = stat; - nodeState.nodeId = nodeId; - nodeState.nodeName = nodeName; - nodeState.ui.triggeredMS = currentUTC; - nodeState.ui.isFiring = true; - nodeState.ui.severity = node.severity; - - if (node.shouldFireSearchRejections) { - const newNodeState = this.createNewNodeState( - nodeState, - this.THREAD_POOL_TYPE.search, - searchRejections - ); - newSearchRejectionsAlertStates.push(newNodeState); - } - - if (node.shouldFireWriteRejections) { - const newNodeState = this.createNewNodeState( - nodeState, - this.THREAD_POOL_TYPE.write, - writeRejections - ); - newWriteRejectionsAlertStates.push(newNodeState); - } - } - - const alertSearchRejectionsInstanceState = { alertStates: newSearchRejectionsAlertStates }; - searchRejectionsInstance.replaceState(alertSearchRejectionsInstanceState); - if (newSearchRejectionsAlertStates.length) { - this.executeActions( - searchRejectionsInstance, - newSearchRejectionsAlertStates, - this.THREAD_POOL_TYPE.search, - cluster - ); - } - - const alertWriteRejectionsInstanceState = { alertStates: newWriteRejectionsAlertStates }; - writeRejectionsInstance.replaceState(alertWriteRejectionsInstanceState); - if (newWriteRejectionsAlertStates.length) { - this.executeActions( - writeRejectionsInstance, - newWriteRejectionsAlertStates, - this.THREAD_POOL_TYPE.write, - cluster - ); - } - } - - state.lastChecked = currentUTC; - return state; - } -} diff --git a/x-pack/plugins/monitoring/server/alerts/thread_pool_rejections_alert_base.ts b/x-pack/plugins/monitoring/server/alerts/thread_pool_rejections_alert_base.ts new file mode 100644 index 0000000000000..80dade1b91b10 --- /dev/null +++ b/x-pack/plugins/monitoring/server/alerts/thread_pool_rejections_alert_base.ts @@ -0,0 +1,336 @@ +/* + * 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 { IUiSettingsClient, Logger } from 'kibana/server'; +import { i18n } from '@kbn/i18n'; +import { BaseAlert } from './base_alert'; +import { + AlertData, + AlertCluster, + AlertMessage, + AlertThreadPoolRejectionsState, + AlertMessageTimeToken, + AlertMessageLinkToken, +} from './types'; +import { AlertInstance, AlertServices } from '../../../alerts/server'; +import { INDEX_PATTERN_ELASTICSEARCH } from '../../common/constants'; +import { fetchThreadPoolRejectionStats } from '../lib/alerts/fetch_thread_pool_rejections_stats'; +import { getCcsIndexPattern } from '../lib/alerts/get_ccs_index_pattern'; +import { AlertMessageTokenType, AlertSeverity, AlertParamType } from '../../common/enums'; +import { Alert, RawAlertInstance } from '../../../alerts/common'; +import { + CommonAlertFilter, + ThreadPoolRejectionsAlertParams, + CommonAlertParamDetail, +} from '../../common/types'; +import { AlertingDefaults, createLink } from './alerts_common'; +import { appendMetricbeatIndex } from '../lib/alerts/append_mb_index'; + +interface ThreadpoolParamDetails { + threshold: CommonAlertParamDetail; + duration: CommonAlertParamDetail; + [key: string]: CommonAlertParamDetail; +} + +type ActionVariables = Array<{ name: string; description: string }>; + +export class ThreadPoolRejectionsAlertBase extends BaseAlert { + protected static createParamDetails(type: string): ThreadpoolParamDetails { + return { + threshold: { + label: i18n.translate('xpack.monitoring.alerts.rejection.paramDetails.threshold.label', { + defaultMessage: `Notify when {type} rejection count is over`, + values: { type }, + }), + type: AlertParamType.Number, + }, + duration: { + label: i18n.translate('xpack.monitoring.alerts.rejection.paramDetails.duration.label', { + defaultMessage: `In the last`, + }), + type: AlertParamType.Duration, + }, + }; + } + + protected static createLabel(type: string) { + return i18n.translate('xpack.monitoring.alerts.threadPoolRejections.label', { + defaultMessage: 'Thread pool {type} rejections', + values: { type }, + }); + } + + protected static createActionVariables(type: string) { + return [ + { + name: 'count', + description: i18n.translate( + 'xpack.monitoring.alerts.threadPoolRejections.actionVariables.count', + { + defaultMessage: 'The number of nodes reporting high thread pool {type} rejections.', + values: { type }, + } + ), + }, + ...Object.values(AlertingDefaults.ALERT_TYPE.context), + ]; + } + + protected defaultParams: ThreadPoolRejectionsAlertParams = { + threshold: 300, + duration: '5m', + }; + + constructor( + rawAlert: Alert | undefined = undefined, + public readonly type: string, + public readonly threadPoolType: string, + public readonly label: string, + public readonly actionVariables: ActionVariables + ) { + super(rawAlert); + } + + protected async fetchData( + params: ThreadPoolRejectionsAlertParams, + callCluster: any, + clusters: AlertCluster[], + uiSettings: IUiSettingsClient, + availableCcs: string[] + ): Promise { + let esIndexPattern = appendMetricbeatIndex(this.config, INDEX_PATTERN_ELASTICSEARCH); + if (availableCcs) { + esIndexPattern = getCcsIndexPattern(esIndexPattern, availableCcs); + } + + const { threshold, duration } = params; + + const stats = await fetchThreadPoolRejectionStats( + callCluster, + clusters, + esIndexPattern, + this.config.ui.max_bucket_size, + this.threadPoolType, + duration + ); + + return stats.map((stat) => { + const { clusterUuid, nodeId, rejectionCount, ccs } = stat; + + return { + instanceKey: `${clusterUuid}:${nodeId}`, + shouldFire: rejectionCount > threshold, + rejectionCount, + severity: AlertSeverity.Danger, + meta: stat, + clusterUuid, + ccs, + }; + }); + } + + protected filterAlertInstance(alertInstance: RawAlertInstance, filters: CommonAlertFilter[]) { + const alertInstanceStates = alertInstance.state + ?.alertStates as AlertThreadPoolRejectionsState[]; + const nodeUuid = filters?.find((filter) => filter.nodeUuid)?.nodeUuid; + + if (!alertInstanceStates?.length || !nodeUuid) { + return true; + } + + const nodeAlerts = alertInstanceStates.filter(({ nodeId }) => nodeId === nodeUuid); + return Boolean(nodeAlerts.length); + } + + protected getUiMessage( + alertState: AlertThreadPoolRejectionsState, + rejectionCount: number + ): AlertMessage { + const { nodeName, nodeId, type } = alertState; + return { + text: i18n.translate('xpack.monitoring.alerts.threadPoolRejections.ui.firingMessage', { + defaultMessage: `Node #start_link{nodeName}#end_link is reporting {rejectionCount} {type} rejections at #absolute`, + values: { + nodeName, + type, + rejectionCount, + }, + }), + nextSteps: [ + createLink( + i18n.translate( + 'xpack.monitoring.alerts.threadPoolRejections.ui.nextSteps.tuneThreadPools', + { + defaultMessage: '#start_linkTune thread pools#end_link', + } + ), + `{elasticWebsiteUrl}guide/en/elasticsearch/reference/{docLinkVersion}/modules-threadpool.html` + ), + createLink( + i18n.translate( + 'xpack.monitoring.alerts.threadPoolRejections.ui.nextSteps.optimizeQueries', + { + defaultMessage: '#start_linkOptimize complex queries#end_link', + } + ), + `{elasticWebsiteUrl}blog/advanced-tuning-finding-and-fixing-slow-elasticsearch-queries` + ), + createLink( + i18n.translate('xpack.monitoring.alerts.threadPoolRejections.ui.nextSteps.addMoreNodes', { + defaultMessage: '#start_linkAdd more nodes#end_link', + }), + `{elasticWebsiteUrl}guide/en/elasticsearch/reference/{docLinkVersion}/add-elasticsearch-nodes.html` + ), + createLink( + i18n.translate( + 'xpack.monitoring.alerts.threadPoolRejections.ui.nextSteps.resizeYourDeployment', + { + defaultMessage: '#start_linkResize your deployment (ECE)#end_link', + } + ), + `{elasticWebsiteUrl}guide/en/cloud-enterprise/current/ece-resize-deployment.html` + ), + ], + tokens: [ + { + startToken: '#absolute', + type: AlertMessageTokenType.Time, + isAbsolute: true, + isRelative: false, + timestamp: alertState.ui.triggeredMS, + } as AlertMessageTimeToken, + { + startToken: '#start_link', + endToken: '#end_link', + type: AlertMessageTokenType.Link, + url: `elasticsearch/nodes/${nodeId}`, + } as AlertMessageLinkToken, + ], + }; + } + + protected executeActions( + instance: AlertInstance, + alertStates: AlertThreadPoolRejectionsState[], + cluster: AlertCluster + ) { + const type = this.threadPoolType; + const count = alertStates.length; + const { clusterName: clusterKnownName, clusterUuid } = cluster; + const clusterName = clusterKnownName || clusterUuid; + const shortActionText = i18n.translate( + 'xpack.monitoring.alerts.threadPoolRejections.shortAction', + { + defaultMessage: 'Verify thread pool {type} rejections across affected nodes.', + values: { + type, + }, + } + ); + + const fullActionText = i18n.translate( + 'xpack.monitoring.alerts.threadPoolRejections.fullAction', + { + defaultMessage: 'View nodes', + } + ); + + const ccs = alertStates.find((state) => state.ccs)?.ccs; + const globalStateLink = this.createGlobalStateLink('elasticsearch/nodes', clusterUuid, ccs); + + const action = `[${fullActionText}](${globalStateLink})`; + const internalShortMessage = i18n.translate( + 'xpack.monitoring.alerts.threadPoolRejections.firing.internalShortMessage', + { + defaultMessage: `Thread pool {type} rejections alert is firing for {count} node(s) in cluster: {clusterName}. {shortActionText}`, + values: { + count, + clusterName, + shortActionText, + type, + }, + } + ); + const internalFullMessage = i18n.translate( + 'xpack.monitoring.alerts.threadPoolRejections.firing.internalFullMessage', + { + defaultMessage: `Thread pool {type} rejections alert is firing for {count} node(s) in cluster: {clusterName}. {action}`, + values: { + count, + clusterName, + action, + type, + }, + } + ); + + instance.scheduleActions('default', { + internalShortMessage, + internalFullMessage: this.isCloud ? internalShortMessage : internalFullMessage, + threadPoolType: type, + state: AlertingDefaults.ALERT_STATE.firing, + count, + clusterName, + action, + actionPlain: shortActionText, + }); + } + + protected async processData( + data: AlertData[], + clusters: AlertCluster[], + services: AlertServices, + logger: Logger, + state: { lastChecked?: number } + ) { + const currentUTC = +new Date(); + for (const cluster of clusters) { + const nodes = data.filter((node) => node.clusterUuid === cluster.clusterUuid); + if (!nodes.length) { + continue; + } + + const firingNodeUuids = nodes.filter((node) => node.shouldFire); + + if (!firingNodeUuids.length) { + continue; + } + + const instanceSuffix = firingNodeUuids.map((node) => node.meta.nodeId); + + const instancePrefix = `${this.type}:${cluster.clusterUuid}:`; + const alertInstanceId = `${instancePrefix}:${instanceSuffix}`; + const alertInstance = services.alertInstanceFactory(alertInstanceId); + const newAlertStates: AlertThreadPoolRejectionsState[] = []; + + for (const node of nodes) { + if (!node.shouldFire) { + continue; + } + const stat = node.meta as AlertThreadPoolRejectionsState; + const nodeState = this.getDefaultAlertState( + cluster, + node + ) as AlertThreadPoolRejectionsState; + const { nodeId, nodeName, rejectionCount } = stat; + nodeState.nodeId = nodeId; + nodeState.nodeName = nodeName; + nodeState.ui.triggeredMS = currentUTC; + nodeState.ui.isFiring = true; + nodeState.ui.severity = node.severity; + nodeState.ui.message = this.getUiMessage(nodeState, rejectionCount); + newAlertStates.push(nodeState); + } + + alertInstance.replaceState({ alertStates: newAlertStates }); + if (newAlertStates.length) { + this.executeActions(alertInstance, newAlertStates, cluster); + } + } + + state.lastChecked = currentUTC; + return state; + } +} diff --git a/x-pack/plugins/monitoring/server/alerts/thread_pool_search_rejections_alert.ts b/x-pack/plugins/monitoring/server/alerts/thread_pool_search_rejections_alert.ts new file mode 100644 index 0000000000000..37c545d09c32f --- /dev/null +++ b/x-pack/plugins/monitoring/server/alerts/thread_pool_search_rejections_alert.ts @@ -0,0 +1,31 @@ +/* + * 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 { ThreadPoolRejectionsAlertBase } from './thread_pool_rejections_alert_base'; +import { ALERT_THREAD_POOL_SEARCH_REJECTIONS } from '../../common/constants'; +import { Alert } from '../../../alerts/common'; + +export class ThreadPoolSearchRejectionsAlert extends ThreadPoolRejectionsAlertBase { + public static TYPE = ALERT_THREAD_POOL_SEARCH_REJECTIONS; + public static THREAD_POOL_TYPE = 'search'; + public static readonly PARAM_DETAILS = ThreadPoolRejectionsAlertBase.createParamDetails( + ThreadPoolSearchRejectionsAlert.THREAD_POOL_TYPE + ); + public static readonly LABEL = ThreadPoolRejectionsAlertBase.createLabel( + ThreadPoolSearchRejectionsAlert.THREAD_POOL_TYPE + ); + constructor(rawAlert?: Alert) { + super( + rawAlert, + ThreadPoolSearchRejectionsAlert.TYPE, + ThreadPoolSearchRejectionsAlert.THREAD_POOL_TYPE, + ThreadPoolSearchRejectionsAlert.LABEL, + ThreadPoolRejectionsAlertBase.createActionVariables( + ThreadPoolSearchRejectionsAlert.THREAD_POOL_TYPE + ) + ); + } +} diff --git a/x-pack/plugins/monitoring/server/alerts/thread_pool_write_rejections_alert.ts b/x-pack/plugins/monitoring/server/alerts/thread_pool_write_rejections_alert.ts new file mode 100644 index 0000000000000..308cfe93bffd8 --- /dev/null +++ b/x-pack/plugins/monitoring/server/alerts/thread_pool_write_rejections_alert.ts @@ -0,0 +1,31 @@ +/* + * 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 { ThreadPoolRejectionsAlertBase } from './thread_pool_rejections_alert_base'; +import { ALERT_THREAD_POOL_WRITE_REJECTIONS } from '../../common/constants'; +import { Alert } from '../../../alerts/common'; + +export class ThreadPoolWriteRejectionsAlert extends ThreadPoolRejectionsAlertBase { + public static TYPE = ALERT_THREAD_POOL_WRITE_REJECTIONS; + public static THREAD_POOL_TYPE = 'write'; + public static readonly PARAM_DETAILS = ThreadPoolRejectionsAlertBase.createParamDetails( + ThreadPoolWriteRejectionsAlert.THREAD_POOL_TYPE + ); + public static readonly LABEL = ThreadPoolRejectionsAlertBase.createLabel( + ThreadPoolWriteRejectionsAlert.THREAD_POOL_TYPE + ); + constructor(rawAlert?: Alert) { + super( + rawAlert, + ThreadPoolWriteRejectionsAlert.TYPE, + ThreadPoolWriteRejectionsAlert.THREAD_POOL_TYPE, + ThreadPoolWriteRejectionsAlert.LABEL, + ThreadPoolRejectionsAlertBase.createActionVariables( + ThreadPoolWriteRejectionsAlert.THREAD_POOL_TYPE + ) + ); + } +} diff --git a/x-pack/plugins/monitoring/server/alerts/types.d.ts b/x-pack/plugins/monitoring/server/alerts/types.d.ts index 50f31a5f27ccd..422bd477192fb 100644 --- a/x-pack/plugins/monitoring/server/alerts/types.d.ts +++ b/x-pack/plugins/monitoring/server/alerts/types.d.ts @@ -12,7 +12,9 @@ export interface AlertEnableAction { } export interface AlertInstanceState { - alertStates: Array; + alertStates: Array< + AlertState | AlertCpuUsageState | AlertDiskUsageState | AlertThreadPoolRejectionsState + >; [x: string]: unknown; } @@ -47,8 +49,8 @@ export interface AlertMemoryUsageState extends AlertNodeState { } export interface AlertThreadPoolRejectionsState extends AlertState { - count?: number; - type?: 'SEARCH' | 'WRITE' | string; + rejectionCount: number; + type: string; nodeId: string; nodeName?: string; } @@ -111,8 +113,7 @@ export interface AlertThreadPoolRejectionsStats { clusterUuid: string; nodeId: string; nodeName: string; - searchRejections?: number; - writeRejections?: number; + rejectionCount: number; ccs?: string; } diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_thread_pool_rejections_stats.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_thread_pool_rejections_stats.ts index adecb64f0a571..3f39eabc09084 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_thread_pool_rejections_stats.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_thread_pool_rejections_stats.ts @@ -7,50 +7,33 @@ import { get } from 'lodash'; import { AlertCluster, AlertThreadPoolRejectionsStats } from '../../alerts/types'; -interface MaxField { - max: { - field: 'node_stats.thread_pool.search.rejected' | 'node_stats.thread_pool.write.rejected'; - }; -} - -interface RejectionsType { - max_search_rejections?: MaxField; - max_write_rejections?: MaxField; -} - -const getRejectionsType = (search: boolean = true, write: boolean = true) => { - const rejections: RejectionsType = { - max_search_rejections: { - max: { - field: 'node_stats.thread_pool.search.rejected', - }, - }, - max_write_rejections: { - max: { - field: 'node_stats.thread_pool.write.rejected', - }, - }, - }; - if (!search) { - delete rejections.max_search_rejections; - } - if (!write) { - delete rejections.max_write_rejections; - } - return rejections; -}; - const invalidNumberValue = (value: number) => { return isNaN(value) || value === undefined || value === null; }; +const getTopHits = (threadType: string, order: string) => ({ + top_hits: { + sort: [ + { + timestamp: { + order, + }, + }, + ], + _source: { + includes: [`node_stats.thread_pool.${threadType}.rejected`, 'source_node.name'], + }, + size: 1, + }, +}); + export async function fetchThreadPoolRejectionStats( callCluster: any, clusters: AlertCluster[], index: string, size: number, - searchRejections?: boolean, - writeRejections?: boolean + threadType: string, + duration: string ): Promise { const clustersIds = clusters.map((cluster) => cluster.clusterUuid); const params = { @@ -74,7 +57,7 @@ export async function fetchThreadPoolRejectionStats( { range: { timestamp: { - gte: 'now-5m', + gte: `now-${duration}`, }, }, }, @@ -94,18 +77,11 @@ export async function fetchThreadPoolRejectionStats( size, }, aggs: { - index: { - terms: { - field: '_index', - size: 1, - }, + most_recent: { + ...getTopHits(threadType, 'asc'), }, - ...getRejectionsType(searchRejections, writeRejections), - name: { - terms: { - field: 'source_node.name', - size: 1, - }, + least_recent: { + ...getTopHits(threadType, 'desc'), }, }, }, @@ -125,20 +101,38 @@ export async function fetchThreadPoolRejectionStats( for (const clusterBucket of clusterBuckets) { for (const node of clusterBucket.nodes.buckets) { - const indexName = get(node, 'index.buckets[0].key', ''); - const searchRejectionsValue = Number(get(node, 'max_search_rejections.value')); - const writeRejectionsValue = Number(get(node, 'max_write_rejections.value')); - if (invalidNumberValue(searchRejectionsValue) && invalidNumberValue(writeRejectionsValue)) { + const mostRecentDoc = get(node, 'most_recent.hits.hits[0]'); + mostRecentDoc.timestamp = mostRecentDoc.sort[0]; + + const leastRecentDoc = get(node, 'least_recent.hits.hits[0]'); + leastRecentDoc.timestamp = leastRecentDoc.sort[0]; + + if (!mostRecentDoc || mostRecentDoc.timestamp === leastRecentDoc.timestamp) { + continue; + } + + const rejectedPath = `_source.node_stats.thread_pool.${threadType}.rejected`; + const newRejectionCount = Number(get(mostRecentDoc, rejectedPath)); + const oldRejectionCount = Number(get(leastRecentDoc, rejectedPath)); + + if (invalidNumberValue(newRejectionCount) || invalidNumberValue(oldRejectionCount)) { continue; } - stats.push({ - searchRejections: searchRejectionsValue, - writeRejections: writeRejectionsValue, + + const rejectionCount = + oldRejectionCount > newRejectionCount + ? newRejectionCount + : newRejectionCount - oldRejectionCount; + const indexName = mostRecentDoc._index; + const nodeName = get(mostRecentDoc, '_source.source_node.name') || node.key; + const nodeStat = { + rejectionCount, clusterUuid: clusterBucket.key, nodeId: node.key, - nodeName: get(node, 'name.buckets[0].key') || node.key, + nodeName, ccs: indexName.includes(':') ? indexName.split(':')[0] : null, - }); + }; + stats.push(nodeStat); } } return stats; From 17b413458319e590f75c7a4605885d10aa925356 Mon Sep 17 00:00:00 2001 From: Igor Zaytsev Date: Wed, 7 Oct 2020 16:04:43 -0400 Subject: [PATCH 3/7] Code review feedback --- .../thread_pool_rejections_alert_base.ts | 20 ++++++++++++++----- .../fetch_thread_pool_rejections_stats.ts | 6 ++++-- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/monitoring/server/alerts/thread_pool_rejections_alert_base.ts b/x-pack/plugins/monitoring/server/alerts/thread_pool_rejections_alert_base.ts index 80dade1b91b10..043f55856a53b 100644 --- a/x-pack/plugins/monitoring/server/alerts/thread_pool_rejections_alert_base.ts +++ b/x-pack/plugins/monitoring/server/alerts/thread_pool_rejections_alert_base.ts @@ -148,25 +148,26 @@ export class ThreadPoolRejectionsAlertBase extends BaseAlert { alertState: AlertThreadPoolRejectionsState, rejectionCount: number ): AlertMessage { - const { nodeName, nodeId, type } = alertState; + const { nodeName, nodeId } = alertState; return { text: i18n.translate('xpack.monitoring.alerts.threadPoolRejections.ui.firingMessage', { defaultMessage: `Node #start_link{nodeName}#end_link is reporting {rejectionCount} {type} rejections at #absolute`, values: { nodeName, - type, + type: this.threadPoolType, rejectionCount, }, }), nextSteps: [ createLink( i18n.translate( - 'xpack.monitoring.alerts.threadPoolRejections.ui.nextSteps.tuneThreadPools', + 'xpack.monitoring.alerts.threadPoolRejections.ui.nextSteps.monitorThisNode', { - defaultMessage: '#start_linkTune thread pools#end_link', + defaultMessage: `#start_linkMonitor this node#end_link`, } ), - `{elasticWebsiteUrl}guide/en/elasticsearch/reference/{docLinkVersion}/modules-threadpool.html` + `elasticsearch/nodes/${nodeId}/advanced`, + AlertMessageTokenType.Link ), createLink( i18n.translate( @@ -192,6 +193,15 @@ export class ThreadPoolRejectionsAlertBase extends BaseAlert { ), `{elasticWebsiteUrl}guide/en/cloud-enterprise/current/ece-resize-deployment.html` ), + createLink( + i18n.translate( + 'xpack.monitoring.alerts.threadPoolRejections.ui.nextSteps.threadPoolSettings', + { + defaultMessage: '#start_linkThread pool settings#end_link', + } + ), + `{elasticWebsiteUrl}guide/en/elasticsearch/reference/{docLinkVersion}/modules-threadpool.html` + ), ], tokens: [ { diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_thread_pool_rejections_stats.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_thread_pool_rejections_stats.ts index 3f39eabc09084..aa178f0af3a43 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_thread_pool_rejections_stats.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_thread_pool_rejections_stats.ts @@ -17,6 +17,7 @@ const getTopHits = (threadType: string, order: string) => ({ { timestamp: { order, + unmapped_type: 'long', }, }, ], @@ -78,10 +79,10 @@ export async function fetchThreadPoolRejectionStats( }, aggs: { most_recent: { - ...getTopHits(threadType, 'asc'), + ...getTopHits(threadType, 'desc'), }, least_recent: { - ...getTopHits(threadType, 'desc'), + ...getTopHits(threadType, 'asc'), }, }, }, @@ -127,6 +128,7 @@ export async function fetchThreadPoolRejectionStats( const nodeName = get(mostRecentDoc, '_source.source_node.name') || node.key; const nodeStat = { rejectionCount, + type: threadType, clusterUuid: clusterBucket.key, nodeId: node.key, nodeName, From 22c8a6d3d8d100a794e564e130d82da86487a3d5 Mon Sep 17 00:00:00 2001 From: Igor Zaytsev Date: Mon, 26 Oct 2020 17:13:47 -0400 Subject: [PATCH 4/7] Optimized page loading and bundle size --- .../thread_pool_rejections_alert/index.tsx | 5 +- .../public/angular/providers/private.js | 8 +-- .../public/components/chart/chart_target.js | 12 ++--- .../chart/timeseries_visualization.js | 24 ++++----- .../components/elasticsearch/nodes/nodes.js | 8 +-- .../shard_allocation/components/unassigned.js | 4 +- .../lib/has_primary_children.js | 4 +- .../shard_allocation/lib/vents.js | 6 +-- .../transformers/indices_by_nodes.js | 9 ++-- .../transformers/nodes_by_indices.js | 11 ++-- .../plugins/monitoring/public/legacy_shims.ts | 1 - .../public/lib/calculate_shard_stats.js | 8 +-- .../public/lib/get_cluster_from_clusters.js | 6 +-- .../monitoring/public/lib/route_init.js | 3 +- x-pack/plugins/monitoring/public/plugin.ts | 53 +++++++++++-------- .../monitoring/public/services/features.js | 6 +-- .../monitoring/public/services/title.js | 4 +- 17 files changed, 88 insertions(+), 84 deletions(-) diff --git a/x-pack/plugins/monitoring/public/alerts/thread_pool_rejections_alert/index.tsx b/x-pack/plugins/monitoring/public/alerts/thread_pool_rejections_alert/index.tsx index a54921f387234..6ef0d160c09ba 100644 --- a/x-pack/plugins/monitoring/public/alerts/thread_pool_rejections_alert/index.tsx +++ b/x-pack/plugins/monitoring/public/alerts/thread_pool_rejections_alert/index.tsx @@ -8,9 +8,8 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { EuiSpacer } from '@elastic/eui'; import { Expression, Props } from '../components/duration/expression'; - -import { AlertTypeModel } from '../../../../triggers_actions_ui/public'; - +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { AlertTypeModel } from '../../../../triggers_actions_ui/public/types'; import { CommonAlertParamDetails } from '../../../common/types'; interface ThreadPoolTypes { diff --git a/x-pack/plugins/monitoring/public/angular/providers/private.js b/x-pack/plugins/monitoring/public/angular/providers/private.js index 3a667037b2919..7709865432fe6 100644 --- a/x-pack/plugins/monitoring/public/angular/providers/private.js +++ b/x-pack/plugins/monitoring/public/angular/providers/private.js @@ -81,9 +81,9 @@ * * @param {[type]} prov [description] */ -import _ from 'lodash'; +import { partial, uniqueId, isObject } from 'lodash'; -const nextId = _.partial(_.uniqueId, 'privateProvider#'); +const nextId = partial(uniqueId, 'privateProvider#'); function name(fn) { return fn.name || fn.toString().split('\n').shift(); @@ -141,7 +141,7 @@ export function PrivateProvider() { const context = {}; let instance = $injector.invoke(prov, context, locals); - if (!_.isObject(instance)) instance = context; + if (!isObject(instance)) instance = context; privPath.pop(); return instance; @@ -155,7 +155,7 @@ export function PrivateProvider() { if ($delegateId != null && $delegateProv != null) { instance = instantiate(prov, { - $decorate: _.partial(get, $delegateId, $delegateProv), + $decorate: partial(get, $delegateId, $delegateProv), }); } else { instance = instantiate(prov); diff --git a/x-pack/plugins/monitoring/public/components/chart/chart_target.js b/x-pack/plugins/monitoring/public/components/chart/chart_target.js index 9a590d803bb19..6304a7b7f74dd 100644 --- a/x-pack/plugins/monitoring/public/components/chart/chart_target.js +++ b/x-pack/plugins/monitoring/public/components/chart/chart_target.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import _ from 'lodash'; +import { get, isEqual, filter } from 'lodash'; import $ from 'jquery'; import React from 'react'; import { eventBus } from './event_bus'; @@ -50,12 +50,12 @@ export class ChartTarget extends React.Component { } UNSAFE_componentWillReceiveProps(newProps) { - if (this.plot && !_.isEqual(newProps, this.props)) { + if (this.plot && !isEqual(newProps, this.props)) { const { series, timeRange } = newProps; const xaxisOptions = this.plot.getAxes().xaxis.options; - xaxisOptions.min = _.get(timeRange, 'min'); - xaxisOptions.max = _.get(timeRange, 'max'); + xaxisOptions.min = get(timeRange, 'min'); + xaxisOptions.max = get(timeRange, 'max'); this.plot.setData(this.filterData(series, newProps.seriesToShow)); this.plot.setupGrid(); @@ -73,7 +73,7 @@ export class ChartTarget extends React.Component { } filterData(data, seriesToShow) { - return _(data).filter(this.filterByShow(seriesToShow)).value(); + return filter(data, this.filterByShow(seriesToShow)).value(); } async getOptions() { @@ -128,7 +128,7 @@ export class ChartTarget extends React.Component { this.handleThorPlotHover = (_event, pos, item, originalPlot) => { if (this.plot !== originalPlot) { // the crosshair is set for the original chart already - this.plot.setCrosshair({ x: _.get(pos, 'x') }); + this.plot.setCrosshair({ x: get(pos, 'x') }); } this.props.updateLegend(pos, item); }; diff --git a/x-pack/plugins/monitoring/public/components/chart/timeseries_visualization.js b/x-pack/plugins/monitoring/public/components/chart/timeseries_visualization.js index eb32ee108e7b3..829994791f769 100644 --- a/x-pack/plugins/monitoring/public/components/chart/timeseries_visualization.js +++ b/x-pack/plugins/monitoring/public/components/chart/timeseries_visualization.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import _ from 'lodash'; +import { debounce, keys, has, includes, isFunction, difference, assign } from 'lodash'; import React from 'react'; import { getLastValue } from './get_last_value'; import { TimeseriesContainer } from './timeseries_container'; @@ -17,7 +17,7 @@ export class TimeseriesVisualization extends React.Component { constructor(props) { super(props); - this.debouncedUpdateLegend = _.debounce(this.updateLegend, DEBOUNCE_SLOW_MS); + this.debouncedUpdateLegend = debounce(this.updateLegend, DEBOUNCE_SLOW_MS); this.debouncedUpdateLegend = this.debouncedUpdateLegend.bind(this); this.toggleFilter = this.toggleFilter.bind(this); @@ -26,18 +26,18 @@ export class TimeseriesVisualization extends React.Component { this.state = { values: {}, - seriesToShow: _.keys(values), + seriesToShow: keys(values), ignoreVisibilityUpdates: false, }; } filterLegend(id) { - if (!_.has(this.state.values, id)) { + if (!has(this.state.values, id)) { return []; } - const notAllShown = _.keys(this.state.values).length !== this.state.seriesToShow.length; - const isCurrentlyShown = _.includes(this.state.seriesToShow, id); + const notAllShown = keys(this.state.values).length !== this.state.seriesToShow.length; + const isCurrentlyShown = includes(this.state.seriesToShow, id); const seriesToShow = []; if (notAllShown && isCurrentlyShown) { @@ -59,7 +59,7 @@ export class TimeseriesVisualization extends React.Component { toggleFilter(_event, id) { const seriesToShow = this.filterLegend(id); - if (_.isFunction(this.props.onFilter)) { + if (isFunction(this.props.onFilter)) { this.props.onFilter(seriesToShow); } } @@ -94,7 +94,7 @@ export class TimeseriesVisualization extends React.Component { getValuesByX(this.props.series, pos.x, setValueCallback); } } else { - _.assign(values, this.getLastValues()); + assign(values, this.getLastValues()); } this.setState({ values }); @@ -102,13 +102,13 @@ export class TimeseriesVisualization extends React.Component { UNSAFE_componentWillReceiveProps(props) { const values = this.getLastValues(props); - const currentKeys = _.keys(this.state.values); - const keys = _.keys(values); - const diff = _.difference(keys, currentKeys); + const currentKeys = keys(this.state.values); + const valueKeys = keys(values); + const diff = difference(valueKeys, currentKeys); const nextState = { values: values }; if (diff.length && !this.state.ignoreVisibilityUpdates) { - nextState.seriesToShow = keys; + nextState.seriesToShow = valueKeys; } this.setState(nextState); diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/nodes.js b/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/nodes.js index 41d3a579db5a2..61188487e2f99 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/nodes.js +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/nodes/nodes.js @@ -27,7 +27,7 @@ import { EuiHealth, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import _ from 'lodash'; +import { get } from 'lodash'; import { ELASTICSEARCH_SYSTEM_ID } from '../../../../common/constants'; import { FormattedMessage } from '@kbn/i18n/react'; import { ListingCallOut } from '../../setup_mode/listing_callout'; @@ -58,7 +58,7 @@ const getNodeTooltip = (node) => { return null; }; -const getSortHandler = (type) => (item) => _.get(item, [type, 'summary', 'lastVal']); +const getSortHandler = (type) => (item) => get(item, [type, 'summary', 'lastVal']); const getColumns = (showCgroupMetricsElasticsearch, setupMode, clusterUuid, alerts) => { const cols = []; @@ -87,7 +87,7 @@ const getColumns = (showCgroupMetricsElasticsearch, setupMode, clusterUuid, aler let setupModeStatus = null; if (isSetupModeFeatureEnabled(SetupModeFeature.MetricbeatMigration)) { - const list = _.get(setupMode, 'data.byUuid', {}); + const list = get(setupMode, 'data.byUuid', {}); const status = list[node.resolver] || {}; const instance = { uuid: node.resolver, @@ -396,7 +396,7 @@ export function ElasticsearchNodes({ clusterStatus, showCgroupMetricsElasticsear setupMode.data.totalUniqueInstanceCount ) { const finishMigrationAction = - _.get(setupMode.meta, 'liveClusterUuid') === clusterUuid + get(setupMode.meta, 'liveClusterUuid') === clusterUuid ? setupMode.shortcutToFinishMigration : setupMode.openFlyout; diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/unassigned.js b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/unassigned.js index 2c66d14a40605..5c8dca54894b4 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/unassigned.js +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/components/unassigned.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import _ from 'lodash'; +import { sortBy } from 'lodash'; import React from 'react'; import { Shard } from './shard'; import { i18n } from '@kbn/i18n'; @@ -36,7 +36,7 @@ export class Unassigned extends React.Component { }; render() { - const shards = _.sortBy(this.props.shards, 'shard').map(this.createShard); + const shards = sortBy(this.props.shards, 'shard').map(this.createShard); return ( diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/lib/has_primary_children.js b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/lib/has_primary_children.js index 47739b8fe31e8..a371f3e5ff40c 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/lib/has_primary_children.js +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/lib/has_primary_children.js @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ -import _ from 'lodash'; +import { some } from 'lodash'; export function hasPrimaryChildren(item) { - return _.some(item.children, { primary: true }); + return some(item.children, { primary: true }); } diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/lib/vents.js b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/lib/vents.js index db9b7bacc3cdf..335c3d29a5b9e 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/lib/vents.js +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/lib/vents.js @@ -4,13 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import _ from 'lodash'; +import { each, isArray } from 'lodash'; export const _vents = {}; export const vents = { vents: _vents, on: function (id, cb) { - if (!_.isArray(_vents[id])) { + if (!isArray(_vents[id])) { _vents[id] = []; } _vents[id].push(cb); @@ -22,7 +22,7 @@ export const vents = { const args = Array.prototype.slice.call(arguments); const id = args.shift(); if (_vents[id]) { - _.each(_vents[id], function (cb) { + each(_vents[id], function (cb) { cb.apply(null, args); }); } diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/transformers/indices_by_nodes.js b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/transformers/indices_by_nodes.js index a9808ebc4c6ad..67a44b9a378c9 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/transformers/indices_by_nodes.js +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/transformers/indices_by_nodes.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import _ from 'lodash'; +import { find, reduce, values } from 'lodash'; import { decorateShards } from '../lib/decorate_shards'; export function indicesByNodes() { @@ -39,7 +39,7 @@ export function indicesByNodes() { return obj; } - let nodeObj = _.find(obj[index].children, { id: node }); + let nodeObj = find(obj[index].children, { id: node }); if (!nodeObj) { nodeObj = { id: node, @@ -55,7 +55,7 @@ export function indicesByNodes() { return obj; } - const data = _.reduce( + const data = reduce( decorateShards(shards, nodes), function (obj, shard) { obj = createIndex(obj, shard); @@ -65,8 +65,7 @@ export function indicesByNodes() { {} ); - return _(data) - .values() + return values(data) .sortBy((index) => [!index.unassignedPrimaries, /^\./.test(index.name), index.name]) .value(); }; diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/transformers/nodes_by_indices.js b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/transformers/nodes_by_indices.js index 353e1c23d4bc1..771a780b4b97b 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/transformers/nodes_by_indices.js +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/transformers/nodes_by_indices.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import _ from 'lodash'; +import { find, some, reduce, values } from 'lodash'; import { hasPrimaryChildren } from '../lib/has_primary_children'; import { decorateShards } from '../lib/decorate_shards'; @@ -32,7 +32,7 @@ export function nodesByIndices() { if (!obj[node]) { createNode(obj, nodes[node], node); } - let indexObj = _.find(obj[node].children, { id: index }); + let indexObj = find(obj[node].children, { id: index }); if (!indexObj) { indexObj = { id: index, @@ -51,7 +51,7 @@ export function nodesByIndices() { } let data = {}; - if (_.some(shards, isUnassigned)) { + if (some(shards, isUnassigned)) { data.unassigned = { name: 'Unassigned', master: false, @@ -60,10 +60,9 @@ export function nodesByIndices() { }; } - data = _.reduce(decorateShards(shards, nodes), createIndexAddShard, data); + data = reduce(decorateShards(shards, nodes), createIndexAddShard, data); - return _(data) - .values() + return values(data) .sortBy(function (node) { return [node.name !== 'Unassigned', !node.master, node.name]; }) diff --git a/x-pack/plugins/monitoring/public/legacy_shims.ts b/x-pack/plugins/monitoring/public/legacy_shims.ts index bb9f73b5e9ddb..c3c903dab38e9 100644 --- a/x-pack/plugins/monitoring/public/legacy_shims.ts +++ b/x-pack/plugins/monitoring/public/legacy_shims.ts @@ -5,7 +5,6 @@ */ import { CoreStart, HttpSetup, IUiSettingsClient } from 'kibana/public'; -import angular from 'angular'; import { Observable } from 'rxjs'; import { HttpRequestInit } from '../../../../src/core/public'; import { MonitoringStartPluginDependencies } from './types'; diff --git a/x-pack/plugins/monitoring/public/lib/calculate_shard_stats.js b/x-pack/plugins/monitoring/public/lib/calculate_shard_stats.js index 6aee89a9817d5..cd504374da2e4 100644 --- a/x-pack/plugins/monitoring/public/lib/calculate_shard_stats.js +++ b/x-pack/plugins/monitoring/public/lib/calculate_shard_stats.js @@ -5,10 +5,10 @@ */ import { set } from '@elastic/safer-lodash-set'; -import _ from 'lodash'; +import { get, each } from 'lodash'; function addOne(obj, key) { - let value = _.get(obj, key); + let value = get(obj, key); set(obj, key, ++value); } @@ -34,8 +34,8 @@ export function calculateShardStats(state) { data[shard.index] = metrics; }; if (state) { - const shards = _.get(state, 'cluster_state.shards'); - _.each(shards, processShards); + const shards = get(state, 'cluster_state.shards'); + each(shards, processShards); } return data; } diff --git a/x-pack/plugins/monitoring/public/lib/get_cluster_from_clusters.js b/x-pack/plugins/monitoring/public/lib/get_cluster_from_clusters.js index 73422219add95..6e05c02ac7338 100644 --- a/x-pack/plugins/monitoring/public/lib/get_cluster_from_clusters.js +++ b/x-pack/plugins/monitoring/public/lib/get_cluster_from_clusters.js @@ -4,16 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import _ from 'lodash'; +import { find, first } from 'lodash'; export function getClusterFromClusters(clusters, globalState, unsetGlobalState = false) { const cluster = (() => { - const existingCurrent = _.find(clusters, { cluster_uuid: globalState.cluster_uuid }); + const existingCurrent = find(clusters, { cluster_uuid: globalState.cluster_uuid }); if (existingCurrent) { return existingCurrent; } - const firstCluster = _.first(clusters); + const firstCluster = first(clusters); if (firstCluster && firstCluster.cluster_uuid) { return firstCluster; } diff --git a/x-pack/plugins/monitoring/public/lib/route_init.js b/x-pack/plugins/monitoring/public/lib/route_init.js index eebdfa8692f1a..97ff621ee3164 100644 --- a/x-pack/plugins/monitoring/public/lib/route_init.js +++ b/x-pack/plugins/monitoring/public/lib/route_init.js @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import _ from 'lodash'; import { ajaxErrorHandlersProvider } from './ajax_error_handler'; import { isInSetupMode } from './setup_mode'; import { getClusterFromClusters } from './get_cluster_from_clusters'; @@ -13,7 +12,7 @@ export function routeInitProvider(Private, monitoringClusters, globalState, lice const ajaxErrorHandlers = Private(ajaxErrorHandlersProvider); function isOnPage(hash) { - return _.includes(window.location.hash, hash); + return window.location.hash.includes(hash); } /* diff --git a/x-pack/plugins/monitoring/public/plugin.ts b/x-pack/plugins/monitoring/public/plugin.ts index 81862f4927118..f649680fe4704 100644 --- a/x-pack/plugins/monitoring/public/plugin.ts +++ b/x-pack/plugins/monitoring/public/plugin.ts @@ -22,12 +22,6 @@ import { UI_SETTINGS } from '../../../../src/plugins/data/public'; import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/public'; import { MonitoringStartPluginDependencies, MonitoringConfig } from './types'; import { TriggersAndActionsUIPublicPluginSetup } from '../../triggers_actions_ui/public'; -import { createCpuUsageAlertType } from './alerts/cpu_usage_alert'; -import { createMissingMonitoringDataAlertType } from './alerts/missing_monitoring_data_alert'; -import { createLegacyAlertTypes } from './alerts/legacy_alert'; -import { createDiskUsageAlertType } from './alerts/disk_usage_alert'; -import { createThreadPoolRejectionsAlertType } from './alerts/thread_pool_rejections_alert'; -import { createMemoryUsageAlertType } from './alerts/memory_usage_alert'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { ThreadPoolSearchRejectionsAlert } from '../server/alerts'; @@ -46,7 +40,7 @@ export class MonitoringPlugin Plugin { constructor(private initializerContext: PluginInitializerContext) {} - public setup( + public async setup( core: CoreSetup, plugins: MonitoringSetupPluginDependencies ) { @@ -79,20 +73,7 @@ export class MonitoringPlugin }); } - const { alertTypeRegistry } = plugins.triggersActionsUi; - alertTypeRegistry.register(createCpuUsageAlertType()); - alertTypeRegistry.register(createDiskUsageAlertType()); - alertTypeRegistry.register(createMemoryUsageAlertType()); - alertTypeRegistry.register(createMissingMonitoringDataAlertType()); - alertTypeRegistry.register( - createThreadPoolRejectionsAlertType(ThreadPoolSearchRejectionsAlert) - ); - alertTypeRegistry.register(createThreadPoolRejectionsAlertType(ThreadPoolWriteRejectionsAlert)); - - const legacyAlertTypes = createLegacyAlertTypes(); - for (const legacyAlertType of legacyAlertTypes) { - alertTypeRegistry.register(legacyAlertType); - } + await this.registerAlertsAsync(plugins); const app: App = { id, @@ -116,7 +97,6 @@ export class MonitoringPlugin usageCollection: plugins.usageCollection, }; - pluginsStart.kibanaLegacy.loadFontAwesome(); this.setInitialTimefilter(deps); const monitoringApp = new AngularApp(deps); @@ -164,4 +144,33 @@ export class MonitoringPlugin ['showCgroupMetricsLogstash', monitoring.ui.container.logstash.enabled], ]; } + + private registerAlertsAsync = async (plugins: MonitoringSetupPluginDependencies) => { + const { createCpuUsageAlertType } = await import('./alerts/cpu_usage_alert'); + const { createMissingMonitoringDataAlertType } = await import( + './alerts/missing_monitoring_data_alert' + ); + const { createLegacyAlertTypes } = await import('./alerts/legacy_alert'); + const { createDiskUsageAlertType } = await import('./alerts/disk_usage_alert'); + const { createThreadPoolRejectionsAlertType } = await import( + './alerts/thread_pool_rejections_alert' + ); + const { createMemoryUsageAlertType } = await import('./alerts/memory_usage_alert'); + + const { + triggersActionsUi: { alertTypeRegistry }, + } = plugins; + alertTypeRegistry.register(createCpuUsageAlertType()); + alertTypeRegistry.register(createDiskUsageAlertType()); + alertTypeRegistry.register(createMemoryUsageAlertType()); + alertTypeRegistry.register(createMissingMonitoringDataAlertType()); + alertTypeRegistry.register( + createThreadPoolRejectionsAlertType(ThreadPoolSearchRejectionsAlert) + ); + alertTypeRegistry.register(createThreadPoolRejectionsAlertType(ThreadPoolWriteRejectionsAlert)); + const legacyAlertTypes = createLegacyAlertTypes(); + for (const legacyAlertType of legacyAlertTypes) { + alertTypeRegistry.register(legacyAlertType); + } + }; } diff --git a/x-pack/plugins/monitoring/public/services/features.js b/x-pack/plugins/monitoring/public/services/features.js index f98af10f8dfb4..5e29353e497d1 100644 --- a/x-pack/plugins/monitoring/public/services/features.js +++ b/x-pack/plugins/monitoring/public/services/features.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import _ from 'lodash'; +import { has, isUndefined } from 'lodash'; export function featuresProvider($window) { function getData() { @@ -28,11 +28,11 @@ export function featuresProvider($window) { function isEnabled(featureName, defaultSetting) { const monitoringDataObj = getData(); - if (_.has(monitoringDataObj, featureName)) { + if (has(monitoringDataObj, featureName)) { return monitoringDataObj[featureName]; } - if (_.isUndefined(defaultSetting)) { + if (isUndefined(defaultSetting)) { return false; } diff --git a/x-pack/plugins/monitoring/public/services/title.js b/x-pack/plugins/monitoring/public/services/title.js index 0715f4dc9e0b6..91ef4c32f3b98 100644 --- a/x-pack/plugins/monitoring/public/services/title.js +++ b/x-pack/plugins/monitoring/public/services/title.js @@ -4,13 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import _ from 'lodash'; +import { get } from 'lodash'; import { i18n } from '@kbn/i18n'; import { Legacy } from '../legacy_shims'; export function titleProvider($rootScope) { return function changeTitle(cluster, suffix) { - let clusterName = _.get(cluster, 'cluster_name'); + let clusterName = get(cluster, 'cluster_name'); clusterName = clusterName ? `- ${clusterName}` : ''; suffix = suffix ? `- ${suffix}` : ''; $rootScope.$applyAsync(() => { From 69aae858d2d707cabcc08c0d846240a2d9c36818 Mon Sep 17 00:00:00 2001 From: Igor Zaytsev Date: Mon, 26 Oct 2020 18:12:37 -0400 Subject: [PATCH 5/7] Increased monitoring bundle limit --- packages/kbn-optimizer/limits.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index c660d37222504..df9e36e6c11e3 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -54,7 +54,7 @@ pageLoadAssetSize: mapsLegacy: 116817 mapsLegacyLicensing: 20214 ml: 82187 - monitoring: 268612 + monitoring: 288612 navigation: 37269 newsfeed: 42228 observability: 89709 From 066a5f4fa22d30636e74012fea923322fa701781 Mon Sep 17 00:00:00 2001 From: Igor Zaytsev Date: Wed, 28 Oct 2020 21:44:11 -0400 Subject: [PATCH 6/7] Removed server app import into the frontend --- x-pack/plugins/monitoring/common/constants.ts | 173 +++++++++++++++++- x-pack/plugins/monitoring/common/types.ts | 58 ------ .../types.d.ts => common/types/alerts.ts} | 56 +++++- .../monitoring/public/alerts/badge.tsx | 4 +- .../monitoring/public/alerts/callout.tsx | 4 +- .../alerts/components/duration/expression.tsx | 2 +- .../cpu_usage_alert/cpu_usage_alert.tsx | 9 +- .../public/alerts/disk_usage_alert/index.tsx | 10 +- .../public/alerts/filter_alert_states.ts | 2 +- .../alerts/legacy_alert/legacy_alert.tsx | 11 +- .../public/alerts/lib/replace_tokens.tsx | 2 +- .../alerts/lib/should_show_alert_badge.ts | 2 +- .../alerts/memory_usage_alert/index.tsx | 10 +- .../expression.tsx | 4 +- .../missing_monitoring_data_alert.tsx | 12 +- .../monitoring/public/alerts/panel.tsx | 3 +- .../monitoring/public/alerts/status.tsx | 3 +- .../thread_pool_rejections_alert/index.tsx | 18 +- .../public/components/chart/chart_target.js | 2 +- .../transformers/indices_by_nodes.js | 12 +- .../transformers/nodes_by_indices.js | 23 +-- x-pack/plugins/monitoring/public/plugin.ts | 22 ++- .../{alerts_common.ts => alert_helpers.ts} | 2 +- .../server/alerts/alerts_factory.ts | 2 +- .../monitoring/server/alerts/base_alert.ts | 6 +- .../server/alerts/cluster_health_alert.ts | 12 +- .../server/alerts/cpu_usage_alert.ts | 47 ++--- .../server/alerts/disk_usage_alert.ts | 42 ++--- .../elasticsearch_version_mismatch_alert.ts | 16 +- .../plugins/monitoring/server/alerts/index.ts | 2 +- .../alerts/kibana_version_mismatch_alert.ts | 16 +- .../server/alerts/license_expiration_alert.ts | 11 +- .../alerts/logstash_version_mismatch_alert.ts | 16 +- .../server/alerts/memory_usage_alert.ts | 42 ++--- .../alerts/missing_monitoring_data_alert.ts | 37 +--- .../server/alerts/nodes_changed_alert.ts | 12 +- .../thread_pool_rejections_alert_base.ts | 44 +---- .../thread_pool_search_rejections_alert.ts | 13 +- .../thread_pool_write_rejections_alert.ts | 13 +- .../server/lib/alerts/fetch_clusters.ts | 2 +- .../lib/alerts/fetch_cpu_usage_node_stats.ts | 2 +- .../lib/alerts/fetch_disk_usage_node_stats.ts | 2 +- .../server/lib/alerts/fetch_legacy_alerts.ts | 2 +- .../alerts/fetch_memory_usage_node_stats.ts | 2 +- .../alerts/fetch_missing_monitoring_data.ts | 2 +- .../server/lib/alerts/fetch_status.test.ts | 2 +- .../server/lib/alerts/fetch_status.ts | 8 +- .../fetch_thread_pool_rejections_stats.ts | 2 +- .../server/routes/api/v1/alerts/status.ts | 2 +- 49 files changed, 417 insertions(+), 384 deletions(-) delete mode 100644 x-pack/plugins/monitoring/common/types.ts rename x-pack/plugins/monitoring/{server/alerts/types.d.ts => common/types/alerts.ts} (76%) rename x-pack/plugins/monitoring/server/alerts/{alerts_common.ts => alert_helpers.ts} (97%) diff --git a/x-pack/plugins/monitoring/common/constants.ts b/x-pack/plugins/monitoring/common/constants.ts index d0a085e58b727..8ff8381d702e8 100644 --- a/x-pack/plugins/monitoring/common/constants.ts +++ b/x-pack/plugins/monitoring/common/constants.ts @@ -4,6 +4,10 @@ * you may not use this file except in compliance with the Elastic License. */ +import { i18n } from '@kbn/i18n'; +import { CommonAlertParamDetail } from './types/alerts'; +import { AlertParamType } from './enums'; + /** * Helper string to add as a tag in every logging call */ @@ -215,15 +219,6 @@ export const REPORTING_SYSTEM_ID = 'reporting'; */ export const TELEMETRY_COLLECTION_INTERVAL = 86400000; -/** - * We want to slowly rollout the migration from watcher-based cluster alerts to - * kibana alerts and we only want to enable the kibana alerts once all - * watcher-based cluster alerts have been migrated so this flag will serve - * as the only way to see the new UI and actually run Kibana alerts. It will - * be false until all alerts have been migrated, then it will be removed - */ -export const KIBANA_CLUSTER_ALERTS_ENABLED = false; - /** * The prefix for all alert types used by monitoring */ @@ -241,6 +236,166 @@ export const ALERT_MISSING_MONITORING_DATA = `${ALERT_PREFIX}alert_missing_monit export const ALERT_THREAD_POOL_SEARCH_REJECTIONS = `${ALERT_PREFIX}alert_thread_pool_search_rejections`; export const ALERT_THREAD_POOL_WRITE_REJECTIONS = `${ALERT_PREFIX}alert_thread_pool_write_rejections`; +/** + * Legacy alerts details/label for server and public use + */ +export const LEGACY_ALERT_DETAILS = { + [ALERT_CLUSTER_HEALTH]: { + label: i18n.translate('xpack.monitoring.alerts.clusterHealth.label', { + defaultMessage: 'Cluster health', + }), + }, + [ALERT_ELASTICSEARCH_VERSION_MISMATCH]: { + label: i18n.translate('xpack.monitoring.alerts.elasticsearchVersionMismatch.label', { + defaultMessage: 'Elasticsearch version mismatch', + }), + }, + [ALERT_KIBANA_VERSION_MISMATCH]: { + label: i18n.translate('xpack.monitoring.alerts.kibanaVersionMismatch.label', { + defaultMessage: 'Kibana version mismatch', + }), + }, + [ALERT_LICENSE_EXPIRATION]: { + label: i18n.translate('xpack.monitoring.alerts.licenseExpiration.label', { + defaultMessage: 'License expiration', + }), + }, + [ALERT_LOGSTASH_VERSION_MISMATCH]: { + label: i18n.translate('xpack.monitoring.alerts.logstashVersionMismatch.label', { + defaultMessage: 'Logstash version mismatch', + }), + }, + [ALERT_NODES_CHANGED]: { + label: i18n.translate('xpack.monitoring.alerts.nodesChanged.label', { + defaultMessage: 'Nodes changed', + }), + }, +}; + +/** + * Alerts details/label for server and public use + */ +export const ALERT_DETAILS = { + [ALERT_CPU_USAGE]: { + label: i18n.translate('xpack.monitoring.alerts.cpuUsage.label', { + defaultMessage: 'CPU Usage', + }), + paramDetails: { + threshold: { + label: i18n.translate('xpack.monitoring.alerts.cpuUsage.paramDetails.threshold.label', { + defaultMessage: `Notify when CPU is over`, + }), + type: AlertParamType.Percentage, + } as CommonAlertParamDetail, + duration: { + label: i18n.translate('xpack.monitoring.alerts.cpuUsage.paramDetails.duration.label', { + defaultMessage: `Look at the average over`, + }), + type: AlertParamType.Duration, + } as CommonAlertParamDetail, + }, + }, + [ALERT_DISK_USAGE]: { + paramDetails: { + threshold: { + label: i18n.translate('xpack.monitoring.alerts.diskUsage.paramDetails.threshold.label', { + defaultMessage: `Notify when disk capacity is over`, + }), + type: AlertParamType.Percentage, + }, + duration: { + label: i18n.translate('xpack.monitoring.alerts.diskUsage.paramDetails.duration.label', { + defaultMessage: `Look at the average over`, + }), + type: AlertParamType.Duration, + }, + }, + label: i18n.translate('xpack.monitoring.alerts.diskUsage.label', { + defaultMessage: 'Disk Usage', + }), + }, + [ALERT_MEMORY_USAGE]: { + paramDetails: { + threshold: { + label: i18n.translate('xpack.monitoring.alerts.memoryUsage.paramDetails.threshold.label', { + defaultMessage: `Notify when memory usage is over`, + }), + type: AlertParamType.Percentage, + }, + duration: { + label: i18n.translate('xpack.monitoring.alerts.memoryUsage.paramDetails.duration.label', { + defaultMessage: `Look at the average over`, + }), + type: AlertParamType.Duration, + }, + }, + label: i18n.translate('xpack.monitoring.alerts.memoryUsage.label', { + defaultMessage: 'Memory Usage (JVM)', + }), + }, + [ALERT_MISSING_MONITORING_DATA]: { + paramDetails: { + duration: { + label: i18n.translate('xpack.monitoring.alerts.missingData.paramDetails.duration.label', { + defaultMessage: `Notify if monitoring data is missing for the last`, + }), + type: AlertParamType.Duration, + } as CommonAlertParamDetail, + limit: { + label: i18n.translate('xpack.monitoring.alerts.missingData.paramDetails.limit.label', { + defaultMessage: `looking back`, + }), + type: AlertParamType.Duration, + } as CommonAlertParamDetail, + }, + label: i18n.translate('xpack.monitoring.alerts.missingData.label', { + defaultMessage: 'Missing monitoring data', + }), + }, + [ALERT_THREAD_POOL_SEARCH_REJECTIONS]: { + paramDetails: { + threshold: { + label: i18n.translate('xpack.monitoring.alerts.rejection.paramDetails.threshold.label', { + defaultMessage: `Notify when {type} rejection count is over`, + values: { type: 'search' }, + }), + type: AlertParamType.Number, + }, + duration: { + label: i18n.translate('xpack.monitoring.alerts.rejection.paramDetails.duration.label', { + defaultMessage: `In the last`, + }), + type: AlertParamType.Duration, + }, + }, + label: i18n.translate('xpack.monitoring.alerts.threadPoolRejections.label', { + defaultMessage: 'Thread pool {type} rejections', + values: { type: 'search' }, + }), + }, + [ALERT_THREAD_POOL_WRITE_REJECTIONS]: { + paramDetails: { + threshold: { + label: i18n.translate('xpack.monitoring.alerts.rejection.paramDetails.threshold.label', { + defaultMessage: `Notify when {type} rejection count is over`, + values: { type: 'write' }, + }), + type: AlertParamType.Number, + }, + duration: { + label: i18n.translate('xpack.monitoring.alerts.rejection.paramDetails.duration.label', { + defaultMessage: `In the last`, + }), + type: AlertParamType.Duration, + }, + }, + label: i18n.translate('xpack.monitoring.alerts.threadPoolRejections.label', { + defaultMessage: 'Thread pool {type} rejections', + values: { type: 'write' }, + }), + }, +}; + /** * A listing of all alert types */ diff --git a/x-pack/plugins/monitoring/common/types.ts b/x-pack/plugins/monitoring/common/types.ts deleted file mode 100644 index d622d091f34cf..0000000000000 --- a/x-pack/plugins/monitoring/common/types.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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 { Alert } from '../../alerts/common'; -import { AlertParamType } from './enums'; - -export interface CommonBaseAlert { - type: string; - label: string; - paramDetails: CommonAlertParamDetails; - rawAlert: Alert; - isLegacy: boolean; -} - -export interface CommonAlertStatus { - exists: boolean; - enabled: boolean; - states: CommonAlertState[]; - alert: CommonBaseAlert; -} - -export interface CommonAlertState { - firing: boolean; - state: any; - meta: any; -} - -export interface CommonAlertFilter { - nodeUuid?: string; -} - -export interface CommonAlertNodeUuidFilter extends CommonAlertFilter { - nodeUuid: string; -} - -export interface CommonAlertStackProductFilter extends CommonAlertFilter { - stackProduct: string; -} - -export interface CommonAlertParamDetail { - label: string; - type?: AlertParamType; -} - -export interface CommonAlertParamDetails { - [name: string]: CommonAlertParamDetail; -} - -export interface CommonAlertParams { - [name: string]: string | number; -} - -export interface ThreadPoolRejectionsAlertParams { - threshold: number; - duration: string; -} diff --git a/x-pack/plugins/monitoring/server/alerts/types.d.ts b/x-pack/plugins/monitoring/common/types/alerts.ts similarity index 76% rename from x-pack/plugins/monitoring/server/alerts/types.d.ts rename to x-pack/plugins/monitoring/common/types/alerts.ts index 422bd477192fb..f7a27a1b1a2b0 100644 --- a/x-pack/plugins/monitoring/server/alerts/types.d.ts +++ b/x-pack/plugins/monitoring/common/types/alerts.ts @@ -3,8 +3,60 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { AlertMessageTokenType, AlertSeverity } from '../../common/enums'; -import { AlertInstanceState as BaseAlertInstanceState } from '../../../alerts/server'; + +import { Alert } from '../../../alerts/common'; +import { AlertParamType, AlertMessageTokenType, AlertSeverity } from '../enums'; + +export interface CommonBaseAlert { + type: string; + label: string; + paramDetails: CommonAlertParamDetails; + rawAlert: Alert; + isLegacy: boolean; +} + +export interface CommonAlertStatus { + exists: boolean; + enabled: boolean; + states: CommonAlertState[]; + alert: CommonBaseAlert; +} + +export interface CommonAlertState { + firing: boolean; + state: any; + meta: any; +} + +export interface CommonAlertFilter { + nodeUuid?: string; +} + +export interface CommonAlertNodeUuidFilter extends CommonAlertFilter { + nodeUuid: string; +} + +export interface CommonAlertStackProductFilter extends CommonAlertFilter { + stackProduct: string; +} + +export interface CommonAlertParamDetail { + label: string; + type?: AlertParamType; +} + +export interface CommonAlertParamDetails { + [name: string]: CommonAlertParamDetail | undefined; +} + +export interface CommonAlertParams { + [name: string]: string | number; +} + +export interface ThreadPoolRejectionsAlertParams { + threshold: number; + duration: string; +} export interface AlertEnableAction { id: string; diff --git a/x-pack/plugins/monitoring/public/alerts/badge.tsx b/x-pack/plugins/monitoring/public/alerts/badge.tsx index d4e823a194f8e..4bfecf4380d4b 100644 --- a/x-pack/plugins/monitoring/public/alerts/badge.tsx +++ b/x-pack/plugins/monitoring/public/alerts/badge.tsx @@ -14,11 +14,11 @@ import { EuiFlexItem, EuiText, } from '@elastic/eui'; -import { CommonAlertStatus, CommonAlertState } from '../../common/types'; +import { CommonAlertStatus, CommonAlertState } from '../../common/types/alerts'; import { AlertSeverity } from '../../common/enums'; // @ts-ignore import { formatDateTimeLocal } from '../../common/formatting'; -import { AlertMessage, AlertState } from '../../server/alerts/types'; +import { AlertMessage, AlertState } from '../../common/types/alerts'; import { AlertPanel } from './panel'; import { Legacy } from '../legacy_shims'; import { isInSetupMode } from '../lib/setup_mode'; diff --git a/x-pack/plugins/monitoring/public/alerts/callout.tsx b/x-pack/plugins/monitoring/public/alerts/callout.tsx index 1ddd41c268456..769d4dc7b256d 100644 --- a/x-pack/plugins/monitoring/public/alerts/callout.tsx +++ b/x-pack/plugins/monitoring/public/alerts/callout.tsx @@ -7,10 +7,10 @@ import React, { Fragment } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiCallOut, EuiSpacer } from '@elastic/eui'; -import { CommonAlertStatus } from '../../common/types'; +import { CommonAlertStatus } from '../../common/types/alerts'; import { AlertSeverity } from '../../common/enums'; import { replaceTokens } from './lib/replace_tokens'; -import { AlertMessage, AlertState } from '../../server/alerts/types'; +import { AlertMessage, AlertState } from '../../common/types/alerts'; const TYPES = [ { diff --git a/x-pack/plugins/monitoring/public/alerts/components/duration/expression.tsx b/x-pack/plugins/monitoring/public/alerts/components/duration/expression.tsx index 0ca7e1a459995..9cc6fa5245f35 100644 --- a/x-pack/plugins/monitoring/public/alerts/components/duration/expression.tsx +++ b/x-pack/plugins/monitoring/public/alerts/components/duration/expression.tsx @@ -6,7 +6,7 @@ import React, { Fragment } from 'react'; import { EuiForm, EuiSpacer } from '@elastic/eui'; -import { CommonAlertParamDetails } from '../../../../common/types'; +import { CommonAlertParamDetails } from '../../../../common/types/alerts'; import { AlertParamDuration } from '../../flyout_expressions/alert_param_duration'; import { AlertParamType } from '../../../../common/enums'; import { AlertParamPercentage } from '../../flyout_expressions/alert_param_percentage'; diff --git a/x-pack/plugins/monitoring/public/alerts/cpu_usage_alert/cpu_usage_alert.tsx b/x-pack/plugins/monitoring/public/alerts/cpu_usage_alert/cpu_usage_alert.tsx index fb4ecacf57fd6..d15fe6344ec0f 100644 --- a/x-pack/plugins/monitoring/public/alerts/cpu_usage_alert/cpu_usage_alert.tsx +++ b/x-pack/plugins/monitoring/public/alerts/cpu_usage_alert/cpu_usage_alert.tsx @@ -6,20 +6,17 @@ import React from 'react'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { AlertTypeModel } from '../../../../triggers_actions_ui/public/types'; -import { ALERT_CPU_USAGE } from '../../../common/constants'; +import { ALERT_CPU_USAGE, ALERT_DETAILS } from '../../../common/constants'; 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'; export function createCpuUsageAlertType(): AlertTypeModel { - const alert = new CpuUsageAlert(); return { id: ALERT_CPU_USAGE, - name: alert.label, + name: ALERT_DETAILS[ALERT_CPU_USAGE].label, iconClass: 'bell', alertParamsExpression: (props: Props) => ( - + ), validate, defaultActionMessage: '{{context.internalFullMessage}}', diff --git a/x-pack/plugins/monitoring/public/alerts/disk_usage_alert/index.tsx b/x-pack/plugins/monitoring/public/alerts/disk_usage_alert/index.tsx index c2abb35612b38..589b374cae32c 100644 --- a/x-pack/plugins/monitoring/public/alerts/disk_usage_alert/index.tsx +++ b/x-pack/plugins/monitoring/public/alerts/disk_usage_alert/index.tsx @@ -10,17 +10,15 @@ 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'; +import { ALERT_DISK_USAGE, ALERT_DETAILS } from '../../../common/constants'; export function createDiskUsageAlertType(): AlertTypeModel { return { - id: DiskUsageAlert.TYPE, - name: DiskUsageAlert.LABEL, + id: ALERT_DISK_USAGE, + name: ALERT_DETAILS[ALERT_DISK_USAGE].label, iconClass: 'bell', alertParamsExpression: (props: Props) => ( - + ), validate, defaultActionMessage: '{{context.internalFullMessage}}', diff --git a/x-pack/plugins/monitoring/public/alerts/filter_alert_states.ts b/x-pack/plugins/monitoring/public/alerts/filter_alert_states.ts index 63714a6921e3f..e13ea7de0e226 100644 --- a/x-pack/plugins/monitoring/public/alerts/filter_alert_states.ts +++ b/x-pack/plugins/monitoring/public/alerts/filter_alert_states.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { CommonAlertState, CommonAlertStatus } from '../../common/types'; +import { CommonAlertState, CommonAlertStatus } from '../../common/types/alerts'; export function filterAlertStates( alerts: { [type: string]: CommonAlertStatus }, diff --git a/x-pack/plugins/monitoring/public/alerts/legacy_alert/legacy_alert.tsx b/x-pack/plugins/monitoring/public/alerts/legacy_alert/legacy_alert.tsx index f6223d41ab30e..83201b0512dbb 100644 --- a/x-pack/plugins/monitoring/public/alerts/legacy_alert/legacy_alert.tsx +++ b/x-pack/plugins/monitoring/public/alerts/legacy_alert/legacy_alert.tsx @@ -3,24 +3,21 @@ * 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, { Fragment } from 'react'; import { i18n } from '@kbn/i18n'; import { EuiTextColor, EuiSpacer } from '@elastic/eui'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { AlertTypeModel } from '../../../../triggers_actions_ui/public/types'; -import { LEGACY_ALERTS } from '../../../common/constants'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { BY_TYPE } from '../../../server/alerts'; +import { LEGACY_ALERTS, LEGACY_ALERT_DETAILS } from '../../../common/constants'; export function createLegacyAlertTypes(): AlertTypeModel[] { return LEGACY_ALERTS.map((legacyAlert) => { - const alertCls = BY_TYPE[legacyAlert]; - const alert = new alertCls(); return { id: legacyAlert, - name: alert.label, + name: LEGACY_ALERT_DETAILS[legacyAlert].label, iconClass: 'bell', - alertParamsExpression: (props: any) => ( + alertParamsExpression: () => ( diff --git a/x-pack/plugins/monitoring/public/alerts/lib/replace_tokens.tsx b/x-pack/plugins/monitoring/public/alerts/lib/replace_tokens.tsx index 02f5703f66382..b8ac69cbae68a 100644 --- a/x-pack/plugins/monitoring/public/alerts/lib/replace_tokens.tsx +++ b/x-pack/plugins/monitoring/public/alerts/lib/replace_tokens.tsx @@ -11,7 +11,7 @@ import { AlertMessageTimeToken, AlertMessageLinkToken, AlertMessageDocLinkToken, -} from '../../../server/alerts/types'; +} from '../../../common/types/alerts'; // @ts-ignore import { formatTimestampToDuration } from '../../../common'; import { CALCULATE_DURATION_UNTIL } from '../../../common/constants'; diff --git a/x-pack/plugins/monitoring/public/alerts/lib/should_show_alert_badge.ts b/x-pack/plugins/monitoring/public/alerts/lib/should_show_alert_badge.ts index 0b95592d92c84..2ec5d1ba8f94a 100644 --- a/x-pack/plugins/monitoring/public/alerts/lib/should_show_alert_badge.ts +++ b/x-pack/plugins/monitoring/public/alerts/lib/should_show_alert_badge.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { isInSetupMode } from '../../lib/setup_mode'; -import { CommonAlertStatus } from '../../../common/types'; +import { CommonAlertStatus } from '../../../common/types/alerts'; import { ISetupModeContext } from '../../components/setup_mode/setup_mode_context'; export function shouldShowAlertBadge( diff --git a/x-pack/plugins/monitoring/public/alerts/memory_usage_alert/index.tsx b/x-pack/plugins/monitoring/public/alerts/memory_usage_alert/index.tsx index dd60967a3458b..d3d48d907d02e 100644 --- a/x-pack/plugins/monitoring/public/alerts/memory_usage_alert/index.tsx +++ b/x-pack/plugins/monitoring/public/alerts/memory_usage_alert/index.tsx @@ -10,17 +10,15 @@ 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 { MemoryUsageAlert } from '../../../server/alerts'; +import { ALERT_MEMORY_USAGE, ALERT_DETAILS } from '../../../common/constants'; export function createMemoryUsageAlertType(): AlertTypeModel { return { - id: MemoryUsageAlert.TYPE, - name: MemoryUsageAlert.LABEL, + id: ALERT_MEMORY_USAGE, + name: ALERT_DETAILS[ALERT_MEMORY_USAGE].label, iconClass: 'bell', alertParamsExpression: (props: Props) => ( - + ), validate, defaultActionMessage: '{{context.internalFullMessage}}', diff --git a/x-pack/plugins/monitoring/public/alerts/missing_monitoring_data_alert/expression.tsx b/x-pack/plugins/monitoring/public/alerts/missing_monitoring_data_alert/expression.tsx index 7dc6155de529e..ac30a02173a5c 100644 --- a/x-pack/plugins/monitoring/public/alerts/missing_monitoring_data_alert/expression.tsx +++ b/x-pack/plugins/monitoring/public/alerts/missing_monitoring_data_alert/expression.tsx @@ -6,7 +6,7 @@ import React, { Fragment } from 'react'; import { EuiForm, EuiSpacer } from '@elastic/eui'; -import { CommonAlertParamDetails } from '../../../common/types'; +import { CommonAlertParamDetails } from '../../../common/types/alerts'; import { AlertParamDuration } from '../flyout_expressions/alert_param_duration'; import { AlertParamType } from '../../../common/enums'; import { AlertParamPercentage } from '../flyout_expressions/alert_param_percentage'; @@ -26,7 +26,7 @@ export const Expression: React.FC = (props) => { const details = paramDetails[alertParamName]; const value = alertParams[alertParamName]; - switch (details.type) { + switch (details?.type) { case AlertParamType.Duration: return ( ( - + ), validate, defaultActionMessage: '{{context.internalFullMessage}}', diff --git a/x-pack/plugins/monitoring/public/alerts/panel.tsx b/x-pack/plugins/monitoring/public/alerts/panel.tsx index eb3b6ff9da1be..99db6c8b3c945 100644 --- a/x-pack/plugins/monitoring/public/alerts/panel.tsx +++ b/x-pack/plugins/monitoring/public/alerts/panel.tsx @@ -18,8 +18,7 @@ import { EuiListGroupItem, } from '@elastic/eui'; -import { CommonAlertStatus, CommonAlertState } from '../../common/types'; -import { AlertMessage } from '../../server/alerts/types'; +import { CommonAlertStatus, CommonAlertState, AlertMessage } from '../../common/types/alerts'; import { Legacy } from '../legacy_shims'; import { replaceTokens } from './lib/replace_tokens'; import { AlertsContextProvider } from '../../../triggers_actions_ui/public'; diff --git a/x-pack/plugins/monitoring/public/alerts/status.tsx b/x-pack/plugins/monitoring/public/alerts/status.tsx index c1ad41fc8d763..53918807a4272 100644 --- a/x-pack/plugins/monitoring/public/alerts/status.tsx +++ b/x-pack/plugins/monitoring/public/alerts/status.tsx @@ -7,9 +7,8 @@ import React from 'react'; import { EuiToolTip, EuiHealth } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; -import { CommonAlertStatus } from '../../common/types'; +import { CommonAlertStatus, AlertMessage, AlertState } from '../../common/types/alerts'; import { AlertSeverity } from '../../common/enums'; -import { AlertMessage, AlertState } from '../../server/alerts/types'; import { AlertsBadge } from './badge'; import { isInSetupMode } from '../lib/setup_mode'; import { SetupModeContext } from '../components/setup_mode/setup_mode_context'; diff --git a/x-pack/plugins/monitoring/public/alerts/thread_pool_rejections_alert/index.tsx b/x-pack/plugins/monitoring/public/alerts/thread_pool_rejections_alert/index.tsx index 6ef0d160c09ba..5e8e676448218 100644 --- a/x-pack/plugins/monitoring/public/alerts/thread_pool_rejections_alert/index.tsx +++ b/x-pack/plugins/monitoring/public/alerts/thread_pool_rejections_alert/index.tsx @@ -10,29 +10,29 @@ import { EuiSpacer } from '@elastic/eui'; import { Expression, Props } from '../components/duration/expression'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { AlertTypeModel } from '../../../../triggers_actions_ui/public/types'; -import { CommonAlertParamDetails } from '../../../common/types'; +import { CommonAlertParamDetails } from '../../../common/types/alerts'; interface ThreadPoolTypes { [key: string]: unknown; } -interface ThreadPoolRejectionAlertClass { - TYPE: string; - LABEL: string; - PARAM_DETAILS: CommonAlertParamDetails; +interface ThreadPoolRejectionAlertDetails { + label: string; + paramDetails: CommonAlertParamDetails; } export function createThreadPoolRejectionsAlertType( - threadPoolAlertClass: ThreadPoolRejectionAlertClass + alertType: string, + threadPoolAlertDetails: ThreadPoolRejectionAlertDetails ): AlertTypeModel { return { - id: threadPoolAlertClass.TYPE, - name: threadPoolAlertClass.LABEL, + id: alertType, + name: threadPoolAlertDetails.label, iconClass: 'bell', alertParamsExpression: (props: Props) => ( <> - + ), validate: (inputValues: ThreadPoolTypes) => { diff --git a/x-pack/plugins/monitoring/public/components/chart/chart_target.js b/x-pack/plugins/monitoring/public/components/chart/chart_target.js index 6304a7b7f74dd..519964e4d5914 100644 --- a/x-pack/plugins/monitoring/public/components/chart/chart_target.js +++ b/x-pack/plugins/monitoring/public/components/chart/chart_target.js @@ -73,7 +73,7 @@ export class ChartTarget extends React.Component { } filterData(data, seriesToShow) { - return filter(data, this.filterByShow(seriesToShow)).value(); + return filter(data, this.filterByShow(seriesToShow)); } async getOptions() { diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/transformers/indices_by_nodes.js b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/transformers/indices_by_nodes.js index 67a44b9a378c9..a04e2bcd1786e 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/transformers/indices_by_nodes.js +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/transformers/indices_by_nodes.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { find, reduce, values } from 'lodash'; +import { find, reduce, values, sortBy } from 'lodash'; import { decorateShards } from '../lib/decorate_shards'; export function indicesByNodes() { @@ -64,9 +64,11 @@ export function indicesByNodes() { }, {} ); - - return values(data) - .sortBy((index) => [!index.unassignedPrimaries, /^\./.test(index.name), index.name]) - .value(); + const dataValues = values(data); + return sortBy(dataValues, (index) => [ + !index.unassignedPrimaries, + /^\./.test(index.name), + index.name, + ]); }; } diff --git a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/transformers/nodes_by_indices.js b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/transformers/nodes_by_indices.js index 771a780b4b97b..f8dd5b6cb8e8d 100644 --- a/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/transformers/nodes_by_indices.js +++ b/x-pack/plugins/monitoring/public/components/elasticsearch/shard_allocation/transformers/nodes_by_indices.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { find, some, reduce, values } from 'lodash'; +import { find, some, reduce, values, sortBy } from 'lodash'; import { hasPrimaryChildren } from '../lib/has_primary_children'; import { decorateShards } from '../lib/decorate_shards'; @@ -61,17 +61,14 @@ export function nodesByIndices() { } data = reduce(decorateShards(shards, nodes), createIndexAddShard, data); - - return values(data) - .sortBy(function (node) { - return [node.name !== 'Unassigned', !node.master, node.name]; - }) - .map(function (node) { - if (node.name === 'Unassigned') { - node.unassignedPrimaries = node.children.some(hasPrimaryChildren); - } - return node; - }) - .value(); + const dataValues = values(data); + return sortBy(dataValues, function (node) { + return [node.name !== 'Unassigned', !node.master, node.name]; + }).map(function (node) { + if (node.name === 'Unassigned') { + node.unassignedPrimaries = node.children.some(hasPrimaryChildren); + } + return node; + }); }; } diff --git a/x-pack/plugins/monitoring/public/plugin.ts b/x-pack/plugins/monitoring/public/plugin.ts index f649680fe4704..a228c540761b8 100644 --- a/x-pack/plugins/monitoring/public/plugin.ts +++ b/x-pack/plugins/monitoring/public/plugin.ts @@ -22,11 +22,11 @@ import { UI_SETTINGS } from '../../../../src/plugins/data/public'; import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/public'; import { MonitoringStartPluginDependencies, MonitoringConfig } from './types'; import { TriggersAndActionsUIPublicPluginSetup } from '../../triggers_actions_ui/public'; - -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { ThreadPoolSearchRejectionsAlert } from '../server/alerts'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { ThreadPoolWriteRejectionsAlert } from '../server/alerts'; +import { + ALERT_THREAD_POOL_SEARCH_REJECTIONS, + ALERT_THREAD_POOL_WRITE_REJECTIONS, + ALERT_DETAILS, +} from '../common/constants'; interface MonitoringSetupPluginDependencies { home?: HomePublicPluginSetup; @@ -165,9 +165,17 @@ export class MonitoringPlugin alertTypeRegistry.register(createMemoryUsageAlertType()); alertTypeRegistry.register(createMissingMonitoringDataAlertType()); alertTypeRegistry.register( - createThreadPoolRejectionsAlertType(ThreadPoolSearchRejectionsAlert) + createThreadPoolRejectionsAlertType( + ALERT_THREAD_POOL_SEARCH_REJECTIONS, + ALERT_DETAILS[ALERT_THREAD_POOL_SEARCH_REJECTIONS] + ) + ); + alertTypeRegistry.register( + createThreadPoolRejectionsAlertType( + ALERT_THREAD_POOL_WRITE_REJECTIONS, + ALERT_DETAILS[ALERT_THREAD_POOL_WRITE_REJECTIONS] + ) ); - alertTypeRegistry.register(createThreadPoolRejectionsAlertType(ThreadPoolWriteRejectionsAlert)); const legacyAlertTypes = createLegacyAlertTypes(); for (const legacyAlertType of legacyAlertTypes) { alertTypeRegistry.register(legacyAlertType); diff --git a/x-pack/plugins/monitoring/server/alerts/alerts_common.ts b/x-pack/plugins/monitoring/server/alerts/alert_helpers.ts similarity index 97% rename from x-pack/plugins/monitoring/server/alerts/alerts_common.ts rename to x-pack/plugins/monitoring/server/alerts/alert_helpers.ts index 41c8bba17df0a..984746e59f06b 100644 --- a/x-pack/plugins/monitoring/server/alerts/alerts_common.ts +++ b/x-pack/plugins/monitoring/server/alerts/alert_helpers.ts @@ -5,7 +5,7 @@ */ import { i18n } from '@kbn/i18n'; -import { AlertMessageDocLinkToken } from './types'; +import { AlertMessageDocLinkToken } from '../../common/types/alerts'; import { AlertMessageTokenType } from '../../common/enums'; export class AlertingDefaults { diff --git a/x-pack/plugins/monitoring/server/alerts/alerts_factory.ts b/x-pack/plugins/monitoring/server/alerts/alerts_factory.ts index f66338e838d8e..efd3d7d5e3b30 100644 --- a/x-pack/plugins/monitoring/server/alerts/alerts_factory.ts +++ b/x-pack/plugins/monitoring/server/alerts/alerts_factory.ts @@ -35,7 +35,7 @@ import { } from '../../common/constants'; import { AlertsClient } from '../../../alerts/server'; -export const BY_TYPE = { +const BY_TYPE = { [ALERT_CLUSTER_HEALTH]: ClusterHealthAlert, [ALERT_LICENSE_EXPIRATION]: LicenseExpirationAlert, [ALERT_CPU_USAGE]: CpuUsageAlert, diff --git a/x-pack/plugins/monitoring/server/alerts/base_alert.ts b/x-pack/plugins/monitoring/server/alerts/base_alert.ts index ce6bc07fb2344..48b783a450807 100644 --- a/x-pack/plugins/monitoring/server/alerts/base_alert.ts +++ b/x-pack/plugins/monitoring/server/alerts/base_alert.ts @@ -28,14 +28,16 @@ import { AlertData, AlertInstanceState, AlertEnableAction, -} from './types'; + CommonAlertFilter, + CommonAlertParams, + CommonBaseAlert, +} from '../../common/types/alerts'; import { fetchAvailableCcs } from '../lib/alerts/fetch_available_ccs'; import { fetchClusters } from '../lib/alerts/fetch_clusters'; import { getCcsIndexPattern } from '../lib/alerts/get_ccs_index_pattern'; import { INDEX_PATTERN_ELASTICSEARCH } from '../../common/constants'; import { MonitoringConfig } from '../config'; import { AlertSeverity } from '../../common/enums'; -import { CommonAlertFilter, CommonAlertParams, CommonBaseAlert } from '../../common/types'; import { MonitoringLicenseService } from '../types'; import { mbSafeQuery } from '../lib/mb_safe_query'; import { appendMetricbeatIndex } from '../lib/alerts/append_mb_index'; diff --git a/x-pack/plugins/monitoring/server/alerts/cluster_health_alert.ts b/x-pack/plugins/monitoring/server/alerts/cluster_health_alert.ts index 427dd2f86de00..1d3d36413ebc2 100644 --- a/x-pack/plugins/monitoring/server/alerts/cluster_health_alert.ts +++ b/x-pack/plugins/monitoring/server/alerts/cluster_health_alert.ts @@ -14,15 +14,15 @@ import { AlertMessageLinkToken, AlertInstanceState, LegacyAlert, -} from './types'; + CommonAlertParams, +} from '../../common/types/alerts'; import { AlertInstance } from '../../../alerts/server'; -import { INDEX_ALERTS, ALERT_CLUSTER_HEALTH } from '../../common/constants'; +import { INDEX_ALERTS, ALERT_CLUSTER_HEALTH, LEGACY_ALERT_DETAILS } from '../../common/constants'; import { getCcsIndexPattern } from '../lib/alerts/get_ccs_index_pattern'; import { AlertMessageTokenType, AlertClusterHealthType } from '../../common/enums'; import { fetchLegacyAlerts } from '../lib/alerts/fetch_legacy_alerts'; import { mapLegacySeverity } from '../lib/alerts/map_legacy_severity'; -import { CommonAlertParams } from '../../common/types'; -import { AlertingDefaults } from './alerts_common'; +import { AlertingDefaults } from './alert_helpers'; const RED_STATUS_MESSAGE = i18n.translate('xpack.monitoring.alerts.clusterHealth.redMessage', { defaultMessage: 'Allocate missing primary and replica shards', @@ -39,9 +39,7 @@ const WATCH_NAME = 'elasticsearch_cluster_status'; export class ClusterHealthAlert extends BaseAlert { public type = ALERT_CLUSTER_HEALTH; - public label = i18n.translate('xpack.monitoring.alerts.clusterHealth.label', { - defaultMessage: 'Cluster health', - }); + public label = LEGACY_ALERT_DETAILS[ALERT_CLUSTER_HEALTH].label; public isLegacy = true; protected actionVariables = [ diff --git a/x-pack/plugins/monitoring/server/alerts/cpu_usage_alert.ts b/x-pack/plugins/monitoring/server/alerts/cpu_usage_alert.ts index 09133dadca162..55931e2996cbf 100644 --- a/x-pack/plugins/monitoring/server/alerts/cpu_usage_alert.ts +++ b/x-pack/plugins/monitoring/server/alerts/cpu_usage_alert.ts @@ -16,55 +16,36 @@ import { AlertMessageTimeToken, AlertMessageLinkToken, AlertInstanceState, -} from './types'; + CommonAlertFilter, + CommonAlertNodeUuidFilter, + CommonAlertParams, +} from '../../common/types/alerts'; import { AlertInstance, AlertServices } from '../../../alerts/server'; -import { INDEX_PATTERN_ELASTICSEARCH, ALERT_CPU_USAGE } from '../../common/constants'; +import { + INDEX_PATTERN_ELASTICSEARCH, + ALERT_CPU_USAGE, + ALERT_DETAILS, +} from '../../common/constants'; import { fetchCpuUsageNodeStats } from '../lib/alerts/fetch_cpu_usage_node_stats'; import { getCcsIndexPattern } from '../lib/alerts/get_ccs_index_pattern'; -import { AlertMessageTokenType, AlertSeverity, AlertParamType } from '../../common/enums'; +import { AlertMessageTokenType, AlertSeverity } from '../../common/enums'; import { RawAlertInstance } from '../../../alerts/common'; import { parseDuration } from '../../../alerts/common/parse_duration'; -import { - CommonAlertFilter, - CommonAlertNodeUuidFilter, - CommonAlertParams, - CommonAlertParamDetail, -} from '../../common/types'; -import { AlertingDefaults, createLink } from './alerts_common'; +import { AlertingDefaults, createLink } from './alert_helpers'; import { appendMetricbeatIndex } from '../lib/alerts/append_mb_index'; -const DEFAULT_THRESHOLD = 85; -const DEFAULT_DURATION = '5m'; - interface CpuUsageParams { threshold: number; duration: string; } export class CpuUsageAlert extends BaseAlert { - public static paramDetails = { - threshold: { - label: i18n.translate('xpack.monitoring.alerts.cpuUsage.paramDetails.threshold.label', { - defaultMessage: `Notify when CPU is over`, - }), - type: AlertParamType.Percentage, - } as CommonAlertParamDetail, - duration: { - label: i18n.translate('xpack.monitoring.alerts.cpuUsage.paramDetails.duration.label', { - defaultMessage: `Look at the average over`, - }), - type: AlertParamType.Duration, - } as CommonAlertParamDetail, - }; - public type = ALERT_CPU_USAGE; - public label = i18n.translate('xpack.monitoring.alerts.cpuUsage.label', { - defaultMessage: 'CPU Usage', - }); + public label = ALERT_DETAILS[ALERT_CPU_USAGE].label; protected defaultParams: CpuUsageParams = { - threshold: DEFAULT_THRESHOLD, - duration: DEFAULT_DURATION, + threshold: 85, + duration: '5m', }; protected actionVariables = [ diff --git a/x-pack/plugins/monitoring/server/alerts/disk_usage_alert.ts b/x-pack/plugins/monitoring/server/alerts/disk_usage_alert.ts index 34c640de79625..e54e736724357 100644 --- a/x-pack/plugins/monitoring/server/alerts/disk_usage_alert.ts +++ b/x-pack/plugins/monitoring/server/alerts/disk_usage_alert.ts @@ -15,43 +15,25 @@ import { AlertMessageTimeToken, AlertMessageLinkToken, AlertInstanceState, -} from './types'; + CommonAlertFilter, + CommonAlertParams, +} from '../../common/types/alerts'; import { AlertInstance, AlertServices } from '../../../alerts/server'; -import { INDEX_PATTERN_ELASTICSEARCH, ALERT_DISK_USAGE } from '../../common/constants'; +import { + INDEX_PATTERN_ELASTICSEARCH, + ALERT_DISK_USAGE, + ALERT_DETAILS, +} from '../../common/constants'; import { fetchDiskUsageNodeStats } from '../lib/alerts/fetch_disk_usage_node_stats'; import { getCcsIndexPattern } from '../lib/alerts/get_ccs_index_pattern'; -import { AlertMessageTokenType, AlertSeverity, AlertParamType } from '../../common/enums'; +import { AlertMessageTokenType, AlertSeverity } from '../../common/enums'; import { RawAlertInstance } from '../../../alerts/common'; -import { CommonAlertFilter, CommonAlertParams, CommonAlertParamDetail } from '../../common/types'; -import { AlertingDefaults, createLink } from './alerts_common'; +import { AlertingDefaults, createLink } from './alert_helpers'; import { appendMetricbeatIndex } from '../lib/alerts/append_mb_index'; -interface ParamDetails { - [key: string]: CommonAlertParamDetail; -} - export class DiskUsageAlert extends BaseAlert { - public static readonly PARAM_DETAILS: ParamDetails = { - threshold: { - label: i18n.translate('xpack.monitoring.alerts.diskUsage.paramDetails.threshold.label', { - defaultMessage: `Notify when disk capacity is over`, - }), - type: AlertParamType.Percentage, - }, - duration: { - label: i18n.translate('xpack.monitoring.alerts.diskUsage.paramDetails.duration.label', { - defaultMessage: `Look at the average over`, - }), - type: AlertParamType.Duration, - }, - }; - public static paramDetails = DiskUsageAlert.PARAM_DETAILS; - public static readonly TYPE = ALERT_DISK_USAGE; - public static readonly LABEL = i18n.translate('xpack.monitoring.alerts.diskUsage.label', { - defaultMessage: 'Disk Usage', - }); - public type = DiskUsageAlert.TYPE; - public label = DiskUsageAlert.LABEL; + public type = ALERT_DISK_USAGE; + public label = ALERT_DETAILS[ALERT_DISK_USAGE].label; protected defaultParams = { threshold: 80, diff --git a/x-pack/plugins/monitoring/server/alerts/elasticsearch_version_mismatch_alert.ts b/x-pack/plugins/monitoring/server/alerts/elasticsearch_version_mismatch_alert.ts index f26b21f0c64c5..6412dcfde54bd 100644 --- a/x-pack/plugins/monitoring/server/alerts/elasticsearch_version_mismatch_alert.ts +++ b/x-pack/plugins/monitoring/server/alerts/elasticsearch_version_mismatch_alert.ts @@ -13,22 +13,24 @@ import { AlertMessage, AlertInstanceState, LegacyAlert, -} from './types'; + CommonAlertParams, +} from '../../common/types/alerts'; import { AlertInstance } from '../../../alerts/server'; -import { INDEX_ALERTS, ALERT_ELASTICSEARCH_VERSION_MISMATCH } from '../../common/constants'; +import { + INDEX_ALERTS, + ALERT_ELASTICSEARCH_VERSION_MISMATCH, + LEGACY_ALERT_DETAILS, +} from '../../common/constants'; import { getCcsIndexPattern } from '../lib/alerts/get_ccs_index_pattern'; import { AlertSeverity } from '../../common/enums'; -import { CommonAlertParams } from '../../common/types'; import { fetchLegacyAlerts } from '../lib/alerts/fetch_legacy_alerts'; -import { AlertingDefaults } from './alerts_common'; +import { AlertingDefaults } from './alert_helpers'; const WATCH_NAME = 'elasticsearch_version_mismatch'; export class ElasticsearchVersionMismatchAlert extends BaseAlert { public type = ALERT_ELASTICSEARCH_VERSION_MISMATCH; - public label = i18n.translate('xpack.monitoring.alerts.elasticsearchVersionMismatch.label', { - defaultMessage: 'Elasticsearch version mismatch', - }); + public label = LEGACY_ALERT_DETAILS[ALERT_ELASTICSEARCH_VERSION_MISMATCH].label; public isLegacy = true; protected actionVariables = [ diff --git a/x-pack/plugins/monitoring/server/alerts/index.ts b/x-pack/plugins/monitoring/server/alerts/index.ts index 17a4826806d1c..5fa718dfb34cd 100644 --- a/x-pack/plugins/monitoring/server/alerts/index.ts +++ b/x-pack/plugins/monitoring/server/alerts/index.ts @@ -17,4 +17,4 @@ export { NodesChangedAlert } from './nodes_changed_alert'; export { ElasticsearchVersionMismatchAlert } from './elasticsearch_version_mismatch_alert'; export { KibanaVersionMismatchAlert } from './kibana_version_mismatch_alert'; export { LogstashVersionMismatchAlert } from './logstash_version_mismatch_alert'; -export { AlertsFactory, BY_TYPE } from './alerts_factory'; +export { AlertsFactory } from './alerts_factory'; diff --git a/x-pack/plugins/monitoring/server/alerts/kibana_version_mismatch_alert.ts b/x-pack/plugins/monitoring/server/alerts/kibana_version_mismatch_alert.ts index 316f305603964..851a401635792 100644 --- a/x-pack/plugins/monitoring/server/alerts/kibana_version_mismatch_alert.ts +++ b/x-pack/plugins/monitoring/server/alerts/kibana_version_mismatch_alert.ts @@ -13,22 +13,24 @@ import { AlertMessage, AlertInstanceState, LegacyAlert, -} from './types'; + CommonAlertParams, +} from '../../common/types/alerts'; import { AlertInstance } from '../../../alerts/server'; -import { INDEX_ALERTS, ALERT_KIBANA_VERSION_MISMATCH } from '../../common/constants'; +import { + INDEX_ALERTS, + ALERT_KIBANA_VERSION_MISMATCH, + LEGACY_ALERT_DETAILS, +} from '../../common/constants'; import { getCcsIndexPattern } from '../lib/alerts/get_ccs_index_pattern'; import { AlertSeverity } from '../../common/enums'; -import { CommonAlertParams } from '../../common/types'; import { fetchLegacyAlerts } from '../lib/alerts/fetch_legacy_alerts'; -import { AlertingDefaults } from './alerts_common'; +import { AlertingDefaults } from './alert_helpers'; const WATCH_NAME = 'kibana_version_mismatch'; export class KibanaVersionMismatchAlert extends BaseAlert { public type = ALERT_KIBANA_VERSION_MISMATCH; - public label = i18n.translate('xpack.monitoring.alerts.kibanaVersionMismatch.label', { - defaultMessage: 'Kibana version mismatch', - }); + public label = LEGACY_ALERT_DETAILS[ALERT_KIBANA_VERSION_MISMATCH].label; public isLegacy = true; protected actionVariables = [ diff --git a/x-pack/plugins/monitoring/server/alerts/license_expiration_alert.ts b/x-pack/plugins/monitoring/server/alerts/license_expiration_alert.ts index f1412ff0fc91a..e0396ee6673e8 100644 --- a/x-pack/plugins/monitoring/server/alerts/license_expiration_alert.ts +++ b/x-pack/plugins/monitoring/server/alerts/license_expiration_alert.ts @@ -16,27 +16,26 @@ import { AlertMessageLinkToken, AlertInstanceState, LegacyAlert, -} from './types'; + CommonAlertParams, +} from '../../common/types/alerts'; import { AlertInstance } from '../../../alerts/server'; import { INDEX_ALERTS, ALERT_LICENSE_EXPIRATION, FORMAT_DURATION_TEMPLATE_SHORT, + LEGACY_ALERT_DETAILS, } from '../../common/constants'; import { getCcsIndexPattern } from '../lib/alerts/get_ccs_index_pattern'; import { AlertMessageTokenType } from '../../common/enums'; -import { CommonAlertParams } from '../../common/types'; import { fetchLegacyAlerts } from '../lib/alerts/fetch_legacy_alerts'; import { mapLegacySeverity } from '../lib/alerts/map_legacy_severity'; -import { AlertingDefaults } from './alerts_common'; +import { AlertingDefaults } from './alert_helpers'; const WATCH_NAME = 'xpack_license_expiration'; export class LicenseExpirationAlert extends BaseAlert { public type = ALERT_LICENSE_EXPIRATION; - public label = i18n.translate('xpack.monitoring.alerts.licenseExpiration.label', { - defaultMessage: 'License expiration', - }); + public label = LEGACY_ALERT_DETAILS[ALERT_LICENSE_EXPIRATION].label; public isLegacy = true; protected actionVariables = [ { diff --git a/x-pack/plugins/monitoring/server/alerts/logstash_version_mismatch_alert.ts b/x-pack/plugins/monitoring/server/alerts/logstash_version_mismatch_alert.ts index 37515e32e591a..7f5c0ea40e36a 100644 --- a/x-pack/plugins/monitoring/server/alerts/logstash_version_mismatch_alert.ts +++ b/x-pack/plugins/monitoring/server/alerts/logstash_version_mismatch_alert.ts @@ -13,22 +13,24 @@ import { AlertMessage, AlertInstanceState, LegacyAlert, -} from './types'; + CommonAlertParams, +} from '../../common/types/alerts'; import { AlertInstance } from '../../../alerts/server'; -import { INDEX_ALERTS, ALERT_LOGSTASH_VERSION_MISMATCH } from '../../common/constants'; +import { + INDEX_ALERTS, + ALERT_LOGSTASH_VERSION_MISMATCH, + LEGACY_ALERT_DETAILS, +} from '../../common/constants'; import { getCcsIndexPattern } from '../lib/alerts/get_ccs_index_pattern'; import { AlertSeverity } from '../../common/enums'; -import { CommonAlertParams } from '../../common/types'; import { fetchLegacyAlerts } from '../lib/alerts/fetch_legacy_alerts'; -import { AlertingDefaults } from './alerts_common'; +import { AlertingDefaults } from './alert_helpers'; const WATCH_NAME = 'logstash_version_mismatch'; export class LogstashVersionMismatchAlert extends BaseAlert { public type = ALERT_LOGSTASH_VERSION_MISMATCH; - public label = i18n.translate('xpack.monitoring.alerts.logstashVersionMismatch.label', { - defaultMessage: 'Logstash version mismatch', - }); + public label = LEGACY_ALERT_DETAILS[ALERT_LOGSTASH_VERSION_MISMATCH].label; public isLegacy = true; protected actionVariables = [ diff --git a/x-pack/plugins/monitoring/server/alerts/memory_usage_alert.ts b/x-pack/plugins/monitoring/server/alerts/memory_usage_alert.ts index 8dc707afab1e1..c37176764c020 100644 --- a/x-pack/plugins/monitoring/server/alerts/memory_usage_alert.ts +++ b/x-pack/plugins/monitoring/server/alerts/memory_usage_alert.ts @@ -15,44 +15,26 @@ import { AlertMessageTimeToken, AlertMessageLinkToken, AlertInstanceState, -} from './types'; + CommonAlertFilter, + CommonAlertParams, +} from '../../common/types/alerts'; import { AlertInstance, AlertServices } from '../../../alerts/server'; -import { INDEX_PATTERN_ELASTICSEARCH, ALERT_MEMORY_USAGE } from '../../common/constants'; +import { + INDEX_PATTERN_ELASTICSEARCH, + ALERT_MEMORY_USAGE, + ALERT_DETAILS, +} from '../../common/constants'; import { fetchMemoryUsageNodeStats } from '../lib/alerts/fetch_memory_usage_node_stats'; import { getCcsIndexPattern } from '../lib/alerts/get_ccs_index_pattern'; -import { AlertMessageTokenType, AlertSeverity, AlertParamType } from '../../common/enums'; +import { AlertMessageTokenType, AlertSeverity } from '../../common/enums'; import { RawAlertInstance } from '../../../alerts/common'; -import { CommonAlertFilter, CommonAlertParams, CommonAlertParamDetail } from '../../common/types'; -import { AlertingDefaults, createLink } from './alerts_common'; +import { AlertingDefaults, createLink } from './alert_helpers'; import { appendMetricbeatIndex } from '../lib/alerts/append_mb_index'; import { parseDuration } from '../../../alerts/common/parse_duration'; -interface ParamDetails { - [key: string]: CommonAlertParamDetail; -} - export class MemoryUsageAlert extends BaseAlert { - public static readonly PARAM_DETAILS: ParamDetails = { - threshold: { - label: i18n.translate('xpack.monitoring.alerts.memoryUsage.paramDetails.threshold.label', { - defaultMessage: `Notify when memory usage is over`, - }), - type: AlertParamType.Percentage, - }, - duration: { - label: i18n.translate('xpack.monitoring.alerts.memoryUsage.paramDetails.duration.label', { - defaultMessage: `Look at the average over`, - }), - type: AlertParamType.Duration, - }, - }; - public static paramDetails = MemoryUsageAlert.PARAM_DETAILS; - public static readonly TYPE = ALERT_MEMORY_USAGE; - public static readonly LABEL = i18n.translate('xpack.monitoring.alerts.memoryUsage.label', { - defaultMessage: 'Memory Usage (JVM)', - }); - public type = MemoryUsageAlert.TYPE; - public label = MemoryUsageAlert.LABEL; + public type = ALERT_MEMORY_USAGE; + public label = ALERT_DETAILS[ALERT_MEMORY_USAGE].label; protected defaultParams = { threshold: 85, diff --git a/x-pack/plugins/monitoring/server/alerts/missing_monitoring_data_alert.ts b/x-pack/plugins/monitoring/server/alerts/missing_monitoring_data_alert.ts index 5b4542a4439ca..456ad92855f65 100644 --- a/x-pack/plugins/monitoring/server/alerts/missing_monitoring_data_alert.ts +++ b/x-pack/plugins/monitoring/server/alerts/missing_monitoring_data_alert.ts @@ -16,24 +16,22 @@ import { AlertMissingData, AlertMessageTimeToken, AlertInstanceState, -} from './types'; + CommonAlertFilter, + CommonAlertParams, + CommonAlertStackProductFilter, + CommonAlertNodeUuidFilter, +} from '../../common/types/alerts'; import { AlertInstance, AlertServices } from '../../../alerts/server'; import { INDEX_PATTERN, ALERT_MISSING_MONITORING_DATA, INDEX_PATTERN_ELASTICSEARCH, + ALERT_DETAILS, } from '../../common/constants'; import { getCcsIndexPattern } from '../lib/alerts/get_ccs_index_pattern'; -import { AlertMessageTokenType, AlertSeverity, AlertParamType } from '../../common/enums'; +import { AlertMessageTokenType, AlertSeverity } from '../../common/enums'; import { RawAlertInstance } from '../../../alerts/common'; import { parseDuration } from '../../../alerts/common/parse_duration'; -import { - CommonAlertFilter, - CommonAlertParams, - CommonAlertParamDetail, - CommonAlertStackProductFilter, - CommonAlertNodeUuidFilter, -} from '../../common/types'; import { appendMetricbeatIndex } from '../lib/alerts/append_mb_index'; import { fetchMissingMonitoringData } from '../lib/alerts/fetch_missing_monitoring_data'; import { getTypeLabelForStackProduct } from '../lib/alerts/get_type_label_for_stack_product'; @@ -41,7 +39,7 @@ import { getListingLinkForStackProduct } from '../lib/alerts/get_listing_link_fo import { getStackProductLabel } from '../lib/alerts/get_stack_product_label'; import { fetchClusters } from '../lib/alerts/fetch_clusters'; import { fetchAvailableCcs } from '../lib/alerts/fetch_available_ccs'; -import { AlertingDefaults, createLink } from './alerts_common'; +import { AlertingDefaults, createLink } from './alert_helpers'; const RESOLVED = i18n.translate('xpack.monitoring.alerts.missingData.resolved', { defaultMessage: 'resolved', @@ -62,27 +60,10 @@ interface MissingDataParams { } export class MissingMonitoringDataAlert extends BaseAlert { - public static paramDetails = { - duration: { - label: i18n.translate('xpack.monitoring.alerts.missingData.paramDetails.duration.label', { - defaultMessage: `Notify if monitoring data is missing for the last`, - }), - type: AlertParamType.Duration, - } as CommonAlertParamDetail, - limit: { - label: i18n.translate('xpack.monitoring.alerts.missingData.paramDetails.limit.label', { - defaultMessage: `looking back`, - }), - type: AlertParamType.Duration, - } as CommonAlertParamDetail, - }; - public defaultThrottle: string = '6h'; public type = ALERT_MISSING_MONITORING_DATA; - public label = i18n.translate('xpack.monitoring.alerts.missingData.label', { - defaultMessage: 'Missing monitoring data', - }); + public label = ALERT_DETAILS[ALERT_MISSING_MONITORING_DATA].label; protected defaultParams: MissingDataParams = { duration: DEFAULT_DURATION, diff --git a/x-pack/plugins/monitoring/server/alerts/nodes_changed_alert.ts b/x-pack/plugins/monitoring/server/alerts/nodes_changed_alert.ts index e03e6ea53ab4e..7b54ef629cba6 100644 --- a/x-pack/plugins/monitoring/server/alerts/nodes_changed_alert.ts +++ b/x-pack/plugins/monitoring/server/alerts/nodes_changed_alert.ts @@ -14,22 +14,20 @@ import { AlertInstanceState, LegacyAlert, LegacyAlertNodesChangedList, -} from './types'; + CommonAlertParams, +} from '../../common/types/alerts'; import { AlertInstance } from '../../../alerts/server'; -import { INDEX_ALERTS, ALERT_NODES_CHANGED } from '../../common/constants'; +import { INDEX_ALERTS, ALERT_NODES_CHANGED, LEGACY_ALERT_DETAILS } from '../../common/constants'; import { getCcsIndexPattern } from '../lib/alerts/get_ccs_index_pattern'; -import { CommonAlertParams } from '../../common/types'; import { fetchLegacyAlerts } from '../lib/alerts/fetch_legacy_alerts'; import { mapLegacySeverity } from '../lib/alerts/map_legacy_severity'; -import { AlertingDefaults } from './alerts_common'; +import { AlertingDefaults } from './alert_helpers'; const WATCH_NAME = 'elasticsearch_nodes'; export class NodesChangedAlert extends BaseAlert { public type = ALERT_NODES_CHANGED; - public label = i18n.translate('xpack.monitoring.alerts.nodesChanged.label', { - defaultMessage: 'Nodes changed', - }); + public label = LEGACY_ALERT_DETAILS[ALERT_NODES_CHANGED].label; public isLegacy = true; protected actionVariables = [ diff --git a/x-pack/plugins/monitoring/server/alerts/thread_pool_rejections_alert_base.ts b/x-pack/plugins/monitoring/server/alerts/thread_pool_rejections_alert_base.ts index 043f55856a53b..4905ae73b0545 100644 --- a/x-pack/plugins/monitoring/server/alerts/thread_pool_rejections_alert_base.ts +++ b/x-pack/plugins/monitoring/server/alerts/thread_pool_rejections_alert_base.ts @@ -13,55 +13,21 @@ import { AlertThreadPoolRejectionsState, AlertMessageTimeToken, AlertMessageLinkToken, -} from './types'; + CommonAlertFilter, + ThreadPoolRejectionsAlertParams, +} from '../../common/types/alerts'; import { AlertInstance, AlertServices } from '../../../alerts/server'; import { INDEX_PATTERN_ELASTICSEARCH } from '../../common/constants'; import { fetchThreadPoolRejectionStats } from '../lib/alerts/fetch_thread_pool_rejections_stats'; import { getCcsIndexPattern } from '../lib/alerts/get_ccs_index_pattern'; -import { AlertMessageTokenType, AlertSeverity, AlertParamType } from '../../common/enums'; +import { AlertMessageTokenType, AlertSeverity } from '../../common/enums'; import { Alert, RawAlertInstance } from '../../../alerts/common'; -import { - CommonAlertFilter, - ThreadPoolRejectionsAlertParams, - CommonAlertParamDetail, -} from '../../common/types'; -import { AlertingDefaults, createLink } from './alerts_common'; +import { AlertingDefaults, createLink } from './alert_helpers'; import { appendMetricbeatIndex } from '../lib/alerts/append_mb_index'; -interface ThreadpoolParamDetails { - threshold: CommonAlertParamDetail; - duration: CommonAlertParamDetail; - [key: string]: CommonAlertParamDetail; -} - type ActionVariables = Array<{ name: string; description: string }>; export class ThreadPoolRejectionsAlertBase extends BaseAlert { - protected static createParamDetails(type: string): ThreadpoolParamDetails { - return { - threshold: { - label: i18n.translate('xpack.monitoring.alerts.rejection.paramDetails.threshold.label', { - defaultMessage: `Notify when {type} rejection count is over`, - values: { type }, - }), - type: AlertParamType.Number, - }, - duration: { - label: i18n.translate('xpack.monitoring.alerts.rejection.paramDetails.duration.label', { - defaultMessage: `In the last`, - }), - type: AlertParamType.Duration, - }, - }; - } - - protected static createLabel(type: string) { - return i18n.translate('xpack.monitoring.alerts.threadPoolRejections.label', { - defaultMessage: 'Thread pool {type} rejections', - values: { type }, - }); - } - protected static createActionVariables(type: string) { return [ { diff --git a/x-pack/plugins/monitoring/server/alerts/thread_pool_search_rejections_alert.ts b/x-pack/plugins/monitoring/server/alerts/thread_pool_search_rejections_alert.ts index 37c545d09c32f..10df95c05ba3f 100644 --- a/x-pack/plugins/monitoring/server/alerts/thread_pool_search_rejections_alert.ts +++ b/x-pack/plugins/monitoring/server/alerts/thread_pool_search_rejections_alert.ts @@ -5,18 +5,13 @@ */ import { ThreadPoolRejectionsAlertBase } from './thread_pool_rejections_alert_base'; -import { ALERT_THREAD_POOL_SEARCH_REJECTIONS } from '../../common/constants'; +import { ALERT_THREAD_POOL_SEARCH_REJECTIONS, ALERT_DETAILS } from '../../common/constants'; import { Alert } from '../../../alerts/common'; export class ThreadPoolSearchRejectionsAlert extends ThreadPoolRejectionsAlertBase { - public static TYPE = ALERT_THREAD_POOL_SEARCH_REJECTIONS; - public static THREAD_POOL_TYPE = 'search'; - public static readonly PARAM_DETAILS = ThreadPoolRejectionsAlertBase.createParamDetails( - ThreadPoolSearchRejectionsAlert.THREAD_POOL_TYPE - ); - public static readonly LABEL = ThreadPoolRejectionsAlertBase.createLabel( - ThreadPoolSearchRejectionsAlert.THREAD_POOL_TYPE - ); + private static TYPE = ALERT_THREAD_POOL_SEARCH_REJECTIONS; + private static THREAD_POOL_TYPE = 'search'; + private static readonly LABEL = ALERT_DETAILS[ALERT_THREAD_POOL_SEARCH_REJECTIONS].label; constructor(rawAlert?: Alert) { super( rawAlert, diff --git a/x-pack/plugins/monitoring/server/alerts/thread_pool_write_rejections_alert.ts b/x-pack/plugins/monitoring/server/alerts/thread_pool_write_rejections_alert.ts index 308cfe93bffd8..d415515315b37 100644 --- a/x-pack/plugins/monitoring/server/alerts/thread_pool_write_rejections_alert.ts +++ b/x-pack/plugins/monitoring/server/alerts/thread_pool_write_rejections_alert.ts @@ -5,18 +5,13 @@ */ import { ThreadPoolRejectionsAlertBase } from './thread_pool_rejections_alert_base'; -import { ALERT_THREAD_POOL_WRITE_REJECTIONS } from '../../common/constants'; +import { ALERT_THREAD_POOL_WRITE_REJECTIONS, ALERT_DETAILS } from '../../common/constants'; import { Alert } from '../../../alerts/common'; export class ThreadPoolWriteRejectionsAlert extends ThreadPoolRejectionsAlertBase { - public static TYPE = ALERT_THREAD_POOL_WRITE_REJECTIONS; - public static THREAD_POOL_TYPE = 'write'; - public static readonly PARAM_DETAILS = ThreadPoolRejectionsAlertBase.createParamDetails( - ThreadPoolWriteRejectionsAlert.THREAD_POOL_TYPE - ); - public static readonly LABEL = ThreadPoolRejectionsAlertBase.createLabel( - ThreadPoolWriteRejectionsAlert.THREAD_POOL_TYPE - ); + private static TYPE = ALERT_THREAD_POOL_WRITE_REJECTIONS; + private static THREAD_POOL_TYPE = 'write'; + private static readonly LABEL = ALERT_DETAILS[ALERT_THREAD_POOL_WRITE_REJECTIONS].label; constructor(rawAlert?: Alert) { super( rawAlert, diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_clusters.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_clusters.ts index d474338bce922..368a909279b8c 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_clusters.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_clusters.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { get } from 'lodash'; -import { AlertCluster } from '../../alerts/types'; +import { AlertCluster } from '../../../common/types/alerts'; interface RangeFilter { [field: string]: { diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_cpu_usage_node_stats.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_cpu_usage_node_stats.ts index ecd324c083a8c..b38a32164223e 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_cpu_usage_node_stats.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_cpu_usage_node_stats.ts @@ -6,7 +6,7 @@ import { get } from 'lodash'; import moment from 'moment'; import { NORMALIZED_DERIVATIVE_UNIT } from '../../../common/constants'; -import { AlertCluster, AlertCpuUsageNodeStats } from '../../alerts/types'; +import { AlertCluster, AlertCpuUsageNodeStats } from '../../../common/types/alerts'; interface NodeBucketESResponse { key: string; diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_disk_usage_node_stats.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_disk_usage_node_stats.ts index 6201204ebebe0..f00c42d708b16 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_disk_usage_node_stats.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_disk_usage_node_stats.ts @@ -5,7 +5,7 @@ */ import { get } from 'lodash'; -import { AlertCluster, AlertDiskUsageNodeStats } from '../../alerts/types'; +import { AlertCluster, AlertDiskUsageNodeStats } from '../../../common/types/alerts'; export async function fetchDiskUsageNodeStats( callCluster: any, diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_legacy_alerts.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_legacy_alerts.ts index fe01a1b921c2e..fbf7608a737ba 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_legacy_alerts.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_legacy_alerts.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { get } from 'lodash'; -import { LegacyAlert, AlertCluster, LegacyAlertMetadata } from '../../alerts/types'; +import { LegacyAlert, AlertCluster, LegacyAlertMetadata } from '../../../common/types/alerts'; export async function fetchLegacyAlerts( callCluster: any, diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_memory_usage_node_stats.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_memory_usage_node_stats.ts index c6843c3ed5f12..9a68b3afc7758 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_memory_usage_node_stats.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_memory_usage_node_stats.ts @@ -5,7 +5,7 @@ */ import { get } from 'lodash'; -import { AlertCluster, AlertMemoryUsageNodeStats } from '../../alerts/types'; +import { AlertCluster, AlertMemoryUsageNodeStats } from '../../../common/types/alerts'; export async function fetchMemoryUsageNodeStats( callCluster: any, diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_missing_monitoring_data.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_missing_monitoring_data.ts index 91fc05137a8c1..49307764e9f01 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_missing_monitoring_data.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_missing_monitoring_data.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { get } from 'lodash'; -import { AlertCluster, AlertMissingData } from '../../alerts/types'; +import { AlertCluster, AlertMissingData } from '../../../common/types/alerts'; import { KIBANA_SYSTEM_ID, BEATS_SYSTEM_ID, diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_status.test.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_status.test.ts index 824eeab7245b4..c31ab91866b1d 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_status.test.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_status.test.ts @@ -5,7 +5,7 @@ */ import { fetchStatus } from './fetch_status'; -import { AlertUiState, AlertState } from '../../alerts/types'; +import { AlertUiState, AlertState } from '../../../common/types/alerts'; import { AlertSeverity } from '../../../common/enums'; import { ALERT_CPU_USAGE, diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_status.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_status.ts index ed49f42e4908c..ed860ee21344d 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_status.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_status.ts @@ -4,10 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ import moment from 'moment'; -import { AlertInstanceState } from '../../alerts/types'; +import { AlertInstanceState } from '../../../common/types/alerts'; import { AlertsClient } from '../../../../alerts/server'; import { AlertsFactory } from '../../alerts'; -import { CommonAlertStatus, CommonAlertState, CommonAlertFilter } from '../../../common/types'; +import { + CommonAlertStatus, + CommonAlertState, + CommonAlertFilter, +} from '../../../common/types/alerts'; import { ALERTS } from '../../../common/constants'; import { MonitoringLicenseService } from '../../types'; diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_thread_pool_rejections_stats.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_thread_pool_rejections_stats.ts index aa178f0af3a43..664ceb1d9411b 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_thread_pool_rejections_stats.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_thread_pool_rejections_stats.ts @@ -5,7 +5,7 @@ */ import { get } from 'lodash'; -import { AlertCluster, AlertThreadPoolRejectionsStats } from '../../alerts/types'; +import { AlertCluster, AlertThreadPoolRejectionsStats } from '../../../common/types/alerts'; const invalidNumberValue = (value: number) => { return isNaN(value) || value === undefined || value === null; diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/alerts/status.ts b/x-pack/plugins/monitoring/server/routes/api/v1/alerts/status.ts index d97bc34c2adb0..29a27ac3d05e7 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/alerts/status.ts +++ b/x-pack/plugins/monitoring/server/routes/api/v1/alerts/status.ts @@ -9,7 +9,7 @@ import { schema } from '@kbn/config-schema'; import { handleError } from '../../../../lib/errors'; import { RouteDependencies } from '../../../../types'; import { fetchStatus } from '../../../../lib/alerts/fetch_status'; -import { CommonAlertFilter } from '../../../../../common/types'; +import { CommonAlertFilter } from '../../../../../common/types/alerts'; export function alertStatusRoute(server: any, npRoute: RouteDependencies) { npRoute.router.post( From 7d2a33df8210449cf78009e766499393d973c7dd Mon Sep 17 00:00:00 2001 From: Igor Zaytsev Date: Thu, 29 Oct 2020 11:07:16 -0400 Subject: [PATCH 7/7] Fixed tests and bundle size --- packages/kbn-optimizer/limits.yml | 2 +- .../public/alerts/components/duration/expression.tsx | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index df9e36e6c11e3..3f6e0dcd11393 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -54,7 +54,7 @@ pageLoadAssetSize: mapsLegacy: 116817 mapsLegacyLicensing: 20214 ml: 82187 - monitoring: 288612 + monitoring: 50000 navigation: 37269 newsfeed: 42228 observability: 89709 diff --git a/x-pack/plugins/monitoring/public/alerts/components/duration/expression.tsx b/x-pack/plugins/monitoring/public/alerts/components/duration/expression.tsx index 9cc6fa5245f35..26593fdd6e7b0 100644 --- a/x-pack/plugins/monitoring/public/alerts/components/duration/expression.tsx +++ b/x-pack/plugins/monitoring/public/alerts/components/duration/expression.tsx @@ -27,14 +27,14 @@ export const Expression: React.FC = (props) => { const details = paramDetails[alertParamName]; const value = alertParams[alertParamName]; - switch (details.type) { + switch (details?.type) { case AlertParamType.Duration: return ( @@ -44,7 +44,7 @@ export const Expression: React.FC = (props) => { = (props) => {