Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Monitoring] Out of the box alerting #68805

Merged
merged 85 commits into from
Jul 14, 2020
Merged
Show file tree
Hide file tree
Changes from 78 commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
d4be8c1
First draft, not quite working but a good start
chrisronline May 14, 2020
ca6981e
Merge in master
chrisronline May 15, 2020
be3f757
More working
chrisronline May 15, 2020
6ea56e8
Support configuring throttle
chrisronline May 15, 2020
2f2955b
Get the other alerts working too
chrisronline May 15, 2020
9a460f4
More
chrisronline May 15, 2020
7f7aa37
Separate into individual files
chrisronline May 18, 2020
6d6aa63
Menu support as well as better integration in existing UIs
chrisronline May 19, 2020
dc81674
Red borders!
chrisronline May 20, 2020
f8dc391
Merge remote-tracking branch 'elastic/master' into monitoring/guardrails
chrisronline May 20, 2020
cbd61ef
New overview style, and renamed alert
chrisronline May 21, 2020
6a613a7
more visual updates
chrisronline May 22, 2020
fe33433
Merge in master
chrisronline May 27, 2020
4e5b25c
Merge remote-tracking branch 'elastic/master' into monitoring/guardrails
chrisronline May 28, 2020
6b991db
Update cpu usage and improve settings configuration in UI
chrisronline May 29, 2020
2dc61d1
Merge remote-tracking branch 'elastic/master' into monitoring/guardrails
chrisronline May 29, 2020
cecf0e9
Convert cluster health and license expiration alert to use legacy dat…
chrisronline May 29, 2020
7cdcbae
Merge remote-tracking branch 'elastic/master' into monitoring/guardrails
chrisronline Jun 1, 2020
0f2fa45
Remove most of the custom UI and use the flyout
chrisronline Jun 4, 2020
8ed790a
Add the actual alerts
chrisronline Jun 4, 2020
5605eca
Remove more code
chrisronline Jun 4, 2020
f8537c3
Merge in master
chrisronline Jun 5, 2020
a353097
Merge remote-tracking branch 'elastic/master' into monitoring/guardrails
chrisronline Jun 8, 2020
3ed13fe
Fix formatting
chrisronline Jun 8, 2020
1bb2584
Merge remote-tracking branch 'elastic/master' into monitoring/guardrails
chrisronline Jun 8, 2020
1eb1e38
Fix up some errors
chrisronline Jun 8, 2020
34dd501
Remove unnecessary code
chrisronline Jun 8, 2020
f04deb0
Updates
chrisronline Jun 9, 2020
66263a0
add more links here
chrisronline Jun 9, 2020
103cdd0
Fix up linkage
chrisronline Jun 10, 2020
04922bd
Added nodes changed alert
chrisronline Jun 11, 2020
35e8a7e
Merge remote-tracking branch 'elastic/master' into monitoring/guardrails
chrisronline Jun 15, 2020
da9b12e
Most of the version mismatch working
chrisronline Jun 16, 2020
e438134
Add kibana mismatch
chrisronline Jun 17, 2020
06daf32
Merge remote-tracking branch 'elastic/master' into monitoring/guardrails
chrisronline Jun 17, 2020
84bfd8f
UI tweaks
chrisronline Jun 17, 2020
91fff09
Add timestamp
chrisronline Jun 17, 2020
c2f329c
Support actions in the enable api
chrisronline Jun 18, 2020
4b9447c
Move this around
chrisronline Jun 18, 2020
05496a0
Merge remote-tracking branch 'elastic/master' into monitoring/guardrails
chrisronline Jun 20, 2020
161a10a
Better support for changing legacy alerts
chrisronline Jun 23, 2020
1353368
Add missing files
chrisronline Jun 23, 2020
830e21d
Merge remote-tracking branch 'elastic/master' into monitoring/guardrails
chrisronline Jun 24, 2020
e404aa0
Update alerts
chrisronline Jun 25, 2020
003e9d3
Enable alerts whenever any page is visited in SM
chrisronline Jun 25, 2020
f341465
Tweaks
chrisronline Jun 29, 2020
400e2a9
Use more practical default
chrisronline Jun 29, 2020
2dd1451
Remove the buggy renderer and ensure setup mode can show all alerts
chrisronline Jun 29, 2020
65c4bca
Merge remote-tracking branch 'elastic/master' into monitoring/guardrails
chrisronline Jun 30, 2020
528ef6c
Updates
chrisronline Jun 30, 2020
b5016c5
Remove unnecessary code
chrisronline Jul 1, 2020
5f27dc6
Remove some dead code
chrisronline Jul 1, 2020
faa7c07
Merge remote-tracking branch 'elastic/master' into monitoring/guardrails
chrisronline Jul 2, 2020
0214557
Cleanup
chrisronline Jul 2, 2020
74c706f
Fix snapshot
chrisronline Jul 2, 2020
0d79951
Merge in master
chrisronline Jul 6, 2020
4f395b7
Fixes
chrisronline Jul 6, 2020
fbce4de
Fixes
chrisronline Jul 7, 2020
1276d98
Fix test
chrisronline Jul 7, 2020
8116208
Add alerts to kibana and logstash listing pages
chrisronline Jul 7, 2020
b1a8685
Fix test
chrisronline Jul 7, 2020
0bff377
Add disable/mute options
chrisronline Jul 7, 2020
93acb1e
Merge remote-tracking branch 'elastic/master' into monitoring/guardrails
chrisronline Jul 7, 2020
d5e1e17
Tweaks
chrisronline Jul 8, 2020
0306f30
Fix linting
chrisronline Jul 8, 2020
42d9383
Fix i18n
chrisronline Jul 8, 2020
6eccc05
Adding a couple tests
chrisronline Jul 8, 2020
3f90bb7
Fix localization
chrisronline Jul 9, 2020
22c8f89
Use http
chrisronline Jul 9, 2020
5bfc3a1
Ensure we properly handle when an alert is resolved
chrisronline Jul 12, 2020
911fb03
Fix tests
chrisronline Jul 12, 2020
9e9a333
Hide legacy alerts if not the right license
chrisronline Jul 13, 2020
550cae8
Merge remote-tracking branch 'elastic/master' into monitoring/guardrails
chrisronline Jul 13, 2020
f89e21c
Design tweaks
chrisronline Jul 13, 2020
ee86a83
Fix tests
chrisronline Jul 13, 2020
0bbc150
PR feedback
chrisronline Jul 13, 2020
48df3b9
Merge remote-tracking branch 'elastic/master' into monitoring/guardrails
chrisronline Jul 13, 2020
8235195
Moar tests
chrisronline Jul 13, 2020
0c32aca
Fix i18n
chrisronline Jul 14, 2020
371165f
Ensure we have a control over the messaging
chrisronline Jul 14, 2020
7e1c835
Fix translations
chrisronline Jul 14, 2020
7fca12a
Tweaks
chrisronline Jul 14, 2020
43a8344
More localization
chrisronline Jul 14, 2020
2dcf32c
Copy changes
chrisronline Jul 14, 2020
9cb8f7e
Type
chrisronline Jul 14, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions x-pack/legacy/plugins/monitoring/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,13 @@

import Hapi from 'hapi';
import { config } from './config';
import { KIBANA_ALERTING_ENABLED } from '../../../plugins/monitoring/common/constants';

/**
* Invokes plugin modules to instantiate the Monitoring plugin for Kibana
* @param kibana {Object} Kibana plugin instance
* @return {Object} Monitoring UI Kibana plugin object
*/
const deps = ['kibana', 'elasticsearch', 'xpack_main'];
if (KIBANA_ALERTING_ENABLED) {
deps.push(...['alerts', 'actions']);
}
export const monitoring = (kibana: any) => {
return new kibana.Plugin({
require: deps,
Expand Down
51 changes: 32 additions & 19 deletions x-pack/plugins/monitoring/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export const INDEX_PATTERN = '.monitoring-*-6-*,.monitoring-*-7-*';
export const INDEX_PATTERN_KIBANA = '.monitoring-kibana-6-*,.monitoring-kibana-7-*';
export const INDEX_PATTERN_LOGSTASH = '.monitoring-logstash-6-*,.monitoring-logstash-7-*';
export const INDEX_PATTERN_BEATS = '.monitoring-beats-6-*,.monitoring-beats-7-*';
export const INDEX_ALERTS = '.monitoring-alerts-6,.monitoring-alerts-7';
export const INDEX_ALERTS = '.monitoring-alerts-6*,.monitoring-alerts-7*';
export const INDEX_PATTERN_ELASTICSEARCH = '.monitoring-es-6-*,.monitoring-es-7-*';

// This is the unique token that exists in monitoring indices collected by metricbeat
Expand Down Expand Up @@ -222,41 +222,54 @@ export const TELEMETRY_COLLECTION_INTERVAL = 86400000;
* 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_ALERTING_ENABLED = false;
export const KIBANA_CLUSTER_ALERTS_ENABLED = false;

/**
* The prefix for all alert types used by monitoring
*/
export const ALERT_TYPE_PREFIX = 'monitoring_';
export const ALERT_PREFIX = 'monitoring_';
export const ALERT_LICENSE_EXPIRATION = `${ALERT_PREFIX}alert_license_expiration`;
export const ALERT_CLUSTER_HEALTH = `${ALERT_PREFIX}alert_cluster_health`;
export const ALERT_CPU_USAGE = `${ALERT_PREFIX}alert_cpu_usage`;
export const ALERT_NODES_CHANGED = `${ALERT_PREFIX}alert_nodes_changed`;
export const ALERT_ELASTICSEARCH_VERSION_MISMATCH = `${ALERT_PREFIX}alert_elasticsearch_version_mismatch`;
export const ALERT_KIBANA_VERSION_MISMATCH = `${ALERT_PREFIX}alert_kibana_version_mismatch`;
export const ALERT_LOGSTASH_VERSION_MISMATCH = `${ALERT_PREFIX}alert_logstash_version_mismatch`;

/**
* This is the alert type id for the license expiration alert
*/
export const ALERT_TYPE_LICENSE_EXPIRATION = `${ALERT_TYPE_PREFIX}alert_type_license_expiration`;
/**
* This is the alert type id for the cluster state alert
* A listing of all alert types
*/
export const ALERT_TYPE_CLUSTER_STATE = `${ALERT_TYPE_PREFIX}alert_type_cluster_state`;
export const ALERTS = [
ALERT_LICENSE_EXPIRATION,
ALERT_CLUSTER_HEALTH,
ALERT_CPU_USAGE,
ALERT_NODES_CHANGED,
ALERT_ELASTICSEARCH_VERSION_MISMATCH,
ALERT_KIBANA_VERSION_MISMATCH,
ALERT_LOGSTASH_VERSION_MISMATCH,
];

/**
* A listing of all alert types
* A list of all legacy alerts, which means they are powered by watcher
*/
export const ALERT_TYPES = [ALERT_TYPE_LICENSE_EXPIRATION, ALERT_TYPE_CLUSTER_STATE];
export const LEGACY_ALERTS = [
ALERT_LICENSE_EXPIRATION,
ALERT_CLUSTER_HEALTH,
ALERT_NODES_CHANGED,
ALERT_ELASTICSEARCH_VERSION_MISMATCH,
ALERT_KIBANA_VERSION_MISMATCH,
ALERT_LOGSTASH_VERSION_MISMATCH,
];

/**
* Matches the id for the built-in in email action type
* See x-pack/plugins/actions/server/builtin_action_types/email.ts
*/
export const ALERT_ACTION_TYPE_EMAIL = '.email';

/**
* The number of alerts that have been migrated
*/
export const NUMBER_OF_MIGRATED_ALERTS = 2;

/**
* The advanced settings config name for the email address
* Matches the id for the built-in in log action type
* See x-pack/plugins/actions/server/builtin_action_types/log.ts
*/
export const MONITORING_CONFIG_ALERTING_EMAIL_ADDRESS = 'monitoring:alertingEmailAddress';
export const ALERT_ACTION_TYPE_LOG = '.server-log';

export const ALERT_EMAIL_SERVICES = ['gmail', 'hotmail', 'icloud', 'outlook365', 'ses', 'yahoo'];
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,25 @@
* you may not use this file except in compliance with the Elastic License.
*/

export enum AlertClusterStateState {
export enum AlertClusterHealthType {
Green = 'green',
Red = 'red',
Yellow = 'yellow',
}

export enum AlertCommonPerClusterMessageTokenType {
export enum AlertSeverity {
Success = 'success',
Danger = 'danger',
Warning = 'warning',
}

export enum AlertMessageTokenType {
Time = 'time',
Link = 'link',
DocLink = 'docLink',
}

export enum AlertParamType {
Duration = 'duration',
Percentage = 'percentage',
}
4 changes: 2 additions & 2 deletions x-pack/plugins/monitoring/common/formatting.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ export const LARGE_ABBREVIATED = '0,0.[0]a';
* @param date Either a numeric Unix timestamp or a {@code Date} object
* @returns The date formatted using 'LL LTS'
*/
export function formatDateTimeLocal(date, useUTC = false) {
export function formatDateTimeLocal(date, useUTC = false, timezone = null) {
return useUTC
? moment.utc(date).format('LL LTS')
: moment.tz(date, moment.tz.guess()).format('LL LTS');
: moment.tz(date, timezone || moment.tz.guess()).format('LL LTS');
}

/**
Expand Down
48 changes: 48 additions & 0 deletions x-pack/plugins/monitoring/common/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* 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;
}

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface CommonAlertFilter {}

export interface CommonAlertCpuUsageFilter extends CommonAlertFilter {
nodeUuid: string;
}

export interface CommonAlertParamDetail {
label: string;
type: AlertParamType;
}

export interface CommonAlertParamDetails {
[name: string]: CommonAlertParamDetail;
}

export interface CommonAlertParams {
[name: string]: string | number;
}
13 changes: 11 additions & 2 deletions x-pack/plugins/monitoring/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,17 @@
"version": "8.0.0",
"kibanaVersion": "kibana",
"configPath": ["monitoring"],
"requiredPlugins": ["licensing", "features", "data", "navigation", "kibanaLegacy"],
"optionalPlugins": ["alerts", "actions", "infra", "telemetryCollectionManager", "usageCollection", "home", "cloud"],
"requiredPlugins": [
"licensing",
"features",
"data",
"navigation",
"kibanaLegacy",
"triggers_actions_ui",
"alerts",
"actions"
],
"optionalPlugins": ["infra", "telemetryCollectionManager", "usageCollection", "home", "cloud"],
"server": true,
"ui": true,
"requiredBundles": ["kibanaUtils", "home", "alerts", "kibanaReact", "licenseManagement"]
Expand Down
180 changes: 180 additions & 0 deletions x-pack/plugins/monitoring/public/alerts/badge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
/*
* 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 {
EuiContextMenu,
EuiPopover,
EuiBadge,
EuiFlexGrid,
EuiFlexItem,
EuiText,
} from '@elastic/eui';
import { CommonAlertStatus, CommonAlertState } from '../../common/types';
import { AlertSeverity } from '../../common/enums';
// @ts-ignore
import { formatDateTimeLocal } from '../../common/formatting';
import { AlertState } from '../../server/alerts/types';
import { AlertPanel } from './panel';
import { Legacy } from '../legacy_shims';
import { isInSetupMode } from '../lib/setup_mode';

function getDateFromState(states: CommonAlertState[]) {
const timestamp = states[0].state.ui.triggeredMS;
const tz = Legacy.shims.uiSettings.get('dateFormat:tz');
return formatDateTimeLocal(timestamp, false, tz === 'Browser' ? null : tz);
}

export const numberOfAlertsLabel = (count: number) => `${count} alert${count > 1 ? 's' : ''}`;

interface Props {
alerts: { [alertTypeId: string]: CommonAlertStatus };
}
export const AlertsBadge: React.FC<Props> = (props: Props) => {
const [showPopover, setShowPopover] = React.useState<AlertSeverity | boolean | null>(null);
const inSetupMode = isInSetupMode();
const alerts = Object.values(props.alerts).filter(Boolean);

if (alerts.length === 0) {
return null;
}

const badges = [];

if (inSetupMode) {
const button = (
<EuiBadge
iconType="bell"
onClickAriaLabel={numberOfAlertsLabel(alerts.length)}
onClick={() => setShowPopover(true)}
>
{numberOfAlertsLabel(alerts.length)}
</EuiBadge>
);
const panels = [
{
id: 0,
title: `Alerts`,
items: alerts.map(({ alert }, index) => {
return {
name: (
<Fragment>
<EuiText>{alert.label}</EuiText>
</Fragment>
),
panel: index + 1,
};
}),
},
...alerts.map((alertStatus, index) => {
return {
id: index + 1,
title: alertStatus.alert.label,
width: 400,
content: <AlertPanel alert={alertStatus} />,
};
}),
];

badges.push(
<EuiPopover
id="monitoringAlertMenu"
button={button}
isOpen={showPopover === true}
closePopover={() => setShowPopover(null)}
panelPaddingSize="none"
withTitle
anchorPosition="downLeft"
>
<EuiContextMenu initialPanelId={0} panels={panels} />
</EuiPopover>
);
} else {
const byType = {
[AlertSeverity.Danger]: [] as CommonAlertStatus[],
[AlertSeverity.Warning]: [] as CommonAlertStatus[],
[AlertSeverity.Success]: [] as CommonAlertStatus[],
};

for (const alert of alerts) {
for (const alertState of alert.states) {
const state = alertState.state as AlertState;
byType[state.ui.severity].push(alert);
}
}

const typesToShow = [AlertSeverity.Danger, AlertSeverity.Warning];
for (const type of typesToShow) {
const list = byType[type];
if (list.length === 0) {
continue;
}

const button = (
<EuiBadge
iconType="bell"
color={type}
onClickAriaLabel={numberOfAlertsLabel(list.length)}
onClick={() => setShowPopover(type)}
>
{numberOfAlertsLabel(list.length)}
</EuiBadge>
);

const panels = [
{
id: 0,
title: `Alerts`,
items: list.map(({ alert, states }, index) => {
return {
name: (
<Fragment>
<EuiText size="s">
<h4>{getDateFromState(states)}</h4>
</EuiText>
<EuiText>{alert.label}</EuiText>
</Fragment>
),
panel: index + 1,
};
}),
},
...list.map((alertStatus, index) => {
return {
id: index + 1,
title: getDateFromState(alertStatus.states),
width: 400,
content: <AlertPanel alert={alertStatus} />,
};
}),
];

badges.push(
<EuiPopover
id="monitoringAlertMenu"
button={button}
isOpen={showPopover === type}
closePopover={() => setShowPopover(null)}
panelPaddingSize="none"
withTitle
anchorPosition="downLeft"
>
<EuiContextMenu initialPanelId={0} panels={panels} />
</EuiPopover>
);
}
}

return (
<EuiFlexGrid>
{badges.map((badge, index) => (
<EuiFlexItem key={index} grow={false}>
{badge}
</EuiFlexItem>
))}
</EuiFlexGrid>
);
};
Loading