[Metrics UI] Add context.reason and alertOnNoData to Inventory alerts (#70260)

This commit is contained in:
Zacqary Adam Xeper 2020-06-30 16:34:38 -05:00 committed by GitHub
parent 893525c74c
commit 0047eeded6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 352 additions and 264 deletions

View file

@ -6,6 +6,7 @@
import React, { useMemo } from 'react';
import { EuiFlexItem } from '@elastic/eui';
import { toMetricOpt } from '../../../snapshot_metric_i18n';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { WaffleSortControls } from '../../../../public/pages/metrics/inventory_view/components/waffle/waffle_sort_controls';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
@ -16,7 +17,6 @@ import { WaffleMetricControls } from '../../../../public/pages/metrics/inventory
import { WaffleGroupByControls } from '../../../../public/pages/metrics/inventory_view/components/waffle/waffle_group_by_controls';
import {
toGroupByOpt,
toMetricOpt,
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
} from '../../../../public/pages/metrics/inventory_view/components/toolbars/toolbar_wrapper';
import { SnapshotMetricType } from '../../types';

View file

@ -0,0 +1,208 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { i18n } from '@kbn/i18n';
import { SnapshotMetricType } from './inventory_models/types';
const Translations = {
CPUUsage: i18n.translate('xpack.infra.waffle.metricOptions.cpuUsageText', {
defaultMessage: 'CPU usage',
}),
MemoryUsage: i18n.translate('xpack.infra.waffle.metricOptions.memoryUsageText', {
defaultMessage: 'Memory usage',
}),
InboundTraffic: i18n.translate('xpack.infra.waffle.metricOptions.inboundTrafficText', {
defaultMessage: 'Inbound traffic',
}),
OutboundTraffic: i18n.translate('xpack.infra.waffle.metricOptions.outboundTrafficText', {
defaultMessage: 'Outbound traffic',
}),
LogRate: i18n.translate('xpack.infra.waffle.metricOptions.hostLogRateText', {
defaultMessage: 'Log rate',
}),
Load: i18n.translate('xpack.infra.waffle.metricOptions.loadText', {
defaultMessage: 'Load',
}),
Count: i18n.translate('xpack.infra.waffle.metricOptions.countText', {
defaultMessage: 'Count',
}),
DiskIOReadBytes: i18n.translate('xpack.infra.waffle.metricOptions.diskIOReadBytes', {
defaultMessage: 'Disk Reads',
}),
DiskIOWriteBytes: i18n.translate('xpack.infra.waffle.metricOptions.diskIOWriteBytes', {
defaultMessage: 'Disk Writes',
}),
s3BucketSize: i18n.translate('xpack.infra.waffle.metricOptions.s3BucketSize', {
defaultMessage: 'Bucket Size',
}),
s3TotalRequests: i18n.translate('xpack.infra.waffle.metricOptions.s3TotalRequests', {
defaultMessage: 'Total Requests',
}),
s3NumberOfObjects: i18n.translate('xpack.infra.waffle.metricOptions.s3NumberOfObjects', {
defaultMessage: 'Number of Objects',
}),
s3DownloadBytes: i18n.translate('xpack.infra.waffle.metricOptions.s3DownloadBytes', {
defaultMessage: 'Downloads (Bytes)',
}),
s3UploadBytes: i18n.translate('xpack.infra.waffle.metricOptions.s3UploadBytes', {
defaultMessage: 'Uploads (Bytes)',
}),
rdsConnections: i18n.translate('xpack.infra.waffle.metricOptions.rdsConnections', {
defaultMessage: 'Connections',
}),
rdsQueriesExecuted: i18n.translate('xpack.infra.waffle.metricOptions.rdsQueriesExecuted', {
defaultMessage: 'Queries Executed',
}),
rdsActiveTransactions: i18n.translate('xpack.infra.waffle.metricOptions.rdsActiveTransactions', {
defaultMessage: 'Active Transactions',
}),
rdsLatency: i18n.translate('xpack.infra.waffle.metricOptions.rdsLatency', {
defaultMessage: 'Latency',
}),
sqsMessagesVisible: i18n.translate('xpack.infra.waffle.metricOptions.sqsMessagesVisible', {
defaultMessage: 'Messages Available',
}),
sqsMessagesDelayed: i18n.translate('xpack.infra.waffle.metricOptions.sqsMessagesDelayed', {
defaultMessage: 'Messages Delayed',
}),
sqsMessagesSent: i18n.translate('xpack.infra.waffle.metricOptions.sqsMessagesSent', {
defaultMessage: 'Messages Added',
}),
sqsMessagesEmpty: i18n.translate('xpack.infra.waffle.metricOptions.sqsMessagesEmpty', {
defaultMessage: 'Messages Returned Empty',
}),
sqsOldestMessage: i18n.translate('xpack.infra.waffle.metricOptions.sqsOldestMessage', {
defaultMessage: 'Oldest Message',
}),
};
export const toMetricOpt = (
metric: SnapshotMetricType
): { text: string; value: SnapshotMetricType } | undefined => {
switch (metric) {
case 'cpu':
return {
text: Translations.CPUUsage,
value: 'cpu',
};
case 'memory':
return {
text: Translations.MemoryUsage,
value: 'memory',
};
case 'rx':
return {
text: Translations.InboundTraffic,
value: 'rx',
};
case 'tx':
return {
text: Translations.OutboundTraffic,
value: 'tx',
};
case 'logRate':
return {
text: Translations.LogRate,
value: 'logRate',
};
case 'load':
return {
text: Translations.Load,
value: 'load',
};
case 'count':
return {
text: Translations.Count,
value: 'count',
};
case 'diskIOReadBytes':
return {
text: Translations.DiskIOReadBytes,
value: 'diskIOReadBytes',
};
case 'diskIOWriteBytes':
return {
text: Translations.DiskIOWriteBytes,
value: 'diskIOWriteBytes',
};
case 's3BucketSize':
return {
text: Translations.s3BucketSize,
value: 's3BucketSize',
};
case 's3TotalRequests':
return {
text: Translations.s3TotalRequests,
value: 's3TotalRequests',
};
case 's3NumberOfObjects':
return {
text: Translations.s3NumberOfObjects,
value: 's3NumberOfObjects',
};
case 's3DownloadBytes':
return {
text: Translations.s3DownloadBytes,
value: 's3DownloadBytes',
};
case 's3UploadBytes':
return {
text: Translations.s3UploadBytes,
value: 's3UploadBytes',
};
case 'rdsConnections':
return {
text: Translations.rdsConnections,
value: 'rdsConnections',
};
case 'rdsQueriesExecuted':
return {
text: Translations.rdsQueriesExecuted,
value: 'rdsQueriesExecuted',
};
case 'rdsActiveTransactions':
return {
text: Translations.rdsActiveTransactions,
value: 'rdsActiveTransactions',
};
case 'rdsLatency':
return {
text: Translations.rdsLatency,
value: 'rdsLatency',
};
case 'sqsMessagesVisible':
return {
text: Translations.sqsMessagesVisible,
value: 'sqsMessagesVisible',
};
case 'sqsMessagesDelayed':
return {
text: Translations.sqsMessagesDelayed,
value: 'sqsMessagesDelayed',
};
case 'sqsMessagesSent':
return {
text: Translations.sqsMessagesSent,
value: 'sqsMessagesSent',
};
case 'sqsMessagesEmpty':
return {
text: Translations.sqsMessagesEmpty,
value: 'sqsMessagesEmpty',
};
case 'sqsOldestMessage':
return {
text: Translations.sqsOldestMessage,
value: 'sqsOldestMessage',
};
}
};

View file

@ -16,9 +16,13 @@ import {
EuiFormRow,
EuiButtonEmpty,
EuiFieldSearch,
EuiCheckbox,
EuiToolTip,
EuiIcon,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import { toMetricOpt } from '../../../../common/snapshot_metric_i18n';
import { AlertPreview } from '../../common';
import { METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID } from '../../../../common/alerting/metrics';
import {
@ -38,7 +42,6 @@ import { AlertsContextValue } from '../../../../../triggers_actions_ui/public/ap
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { MetricsExplorerKueryBar } from '../../../pages/metrics/metrics_explorer/components/kuery_bar';
import { useSourceViaHttp } from '../../../containers/source/use_source_via_http';
import { toMetricOpt } from '../../../pages/metrics/inventory_view/components/toolbars/toolbar_wrapper';
import { sqsMetricTypes } from '../../../../common/inventory_models/aws_sqs/toolbar_items';
import { ec2MetricTypes } from '../../../../common/inventory_models/aws_ec2/toolbar_items';
import { s3MetricTypes } from '../../../../common/inventory_models/aws_s3/toolbar_items';
@ -73,6 +76,7 @@ interface Props {
filterQuery?: string;
filterQueryText?: string;
sourceId?: string;
alertOnNoData?: boolean;
};
alertInterval: string;
alertsContext: AlertsContextValue<AlertContextMeta>;
@ -306,6 +310,28 @@ export const Expressions: React.FC<Props> = (props) => {
</EuiButtonEmpty>
</div>
<EuiSpacer size={'m'} />
<EuiCheckbox
id="metrics-alert-no-data-toggle"
label={
<>
{i18n.translate('xpack.infra.metrics.alertFlyout.alertOnNoData', {
defaultMessage: "Alert me if there's no data",
})}{' '}
<EuiToolTip
content={i18n.translate('xpack.infra.metrics.alertFlyout.noDataHelpText', {
defaultMessage:
'Enable this to trigger the action if the metric(s) do not report any data over the expected time period, or if the alert fails to query Elasticsearch',
})}
>
<EuiIcon type="questionInCircle" color="subdued" />
</EuiToolTip>
</>
}
checked={alertParams.alertOnNoData}
onChange={(e) => setAlertParams('alertOnNoData', e.target.checked)}
/>
<EuiSpacer size={'m'} />
<EuiFormRow

View file

@ -24,10 +24,10 @@ export function createInventoryMetricAlertType(): AlertTypeModel {
defaultActionMessage: i18n.translate(
'xpack.infra.metrics.alerting.inventory.threshold.defaultActionMessage',
{
defaultMessage: `\\{\\{alertName\\}\\} - \\{\\{context.group\\}\\}
defaultMessage: `\\{\\{alertName\\}\\} - \\{\\{context.group\\}\\} is in a state of \\{\\{context.alertState\\}\\}
\\{\\{context.metricOf.condition0\\}\\} has crossed a threshold of \\{\\{context.thresholdOf.condition0\\}\\}
Current value is \\{\\{context.valueOf.condition0\\}\\}
Reason:
\\{\\{context.reason\\}\\}
`,
}
),

View file

@ -6,8 +6,6 @@
import React from 'react';
import { EuiFlexItem } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { SnapshotMetricType } from '../../../../../../common/inventory_models/types';
import { fieldToName } from '../../lib/field_to_display_name';
import { useSourceContext } from '../../../../../containers/source';
import { useWaffleOptionsContext } from '../../hooks/use_waffle_options';
@ -68,208 +66,7 @@ export const ToolbarWrapper = (props: Props) => {
);
};
const ToolbarTranslations = {
CPUUsage: i18n.translate('xpack.infra.waffle.metricOptions.cpuUsageText', {
defaultMessage: 'CPU usage',
}),
MemoryUsage: i18n.translate('xpack.infra.waffle.metricOptions.memoryUsageText', {
defaultMessage: 'Memory usage',
}),
InboundTraffic: i18n.translate('xpack.infra.waffle.metricOptions.inboundTrafficText', {
defaultMessage: 'Inbound traffic',
}),
OutboundTraffic: i18n.translate('xpack.infra.waffle.metricOptions.outboundTrafficText', {
defaultMessage: 'Outbound traffic',
}),
LogRate: i18n.translate('xpack.infra.waffle.metricOptions.hostLogRateText', {
defaultMessage: 'Log rate',
}),
Load: i18n.translate('xpack.infra.waffle.metricOptions.loadText', {
defaultMessage: 'Load',
}),
Count: i18n.translate('xpack.infra.waffle.metricOptions.countText', {
defaultMessage: 'Count',
}),
DiskIOReadBytes: i18n.translate('xpack.infra.waffle.metricOptions.diskIOReadBytes', {
defaultMessage: 'Disk Reads',
}),
DiskIOWriteBytes: i18n.translate('xpack.infra.waffle.metricOptions.diskIOWriteBytes', {
defaultMessage: 'Disk Writes',
}),
s3BucketSize: i18n.translate('xpack.infra.waffle.metricOptions.s3BucketSize', {
defaultMessage: 'Bucket Size',
}),
s3TotalRequests: i18n.translate('xpack.infra.waffle.metricOptions.s3TotalRequests', {
defaultMessage: 'Total Requests',
}),
s3NumberOfObjects: i18n.translate('xpack.infra.waffle.metricOptions.s3NumberOfObjects', {
defaultMessage: 'Number of Objects',
}),
s3DownloadBytes: i18n.translate('xpack.infra.waffle.metricOptions.s3DownloadBytes', {
defaultMessage: 'Downloads (Bytes)',
}),
s3UploadBytes: i18n.translate('xpack.infra.waffle.metricOptions.s3UploadBytes', {
defaultMessage: 'Uploads (Bytes)',
}),
rdsConnections: i18n.translate('xpack.infra.waffle.metricOptions.rdsConnections', {
defaultMessage: 'Connections',
}),
rdsQueriesExecuted: i18n.translate('xpack.infra.waffle.metricOptions.rdsQueriesExecuted', {
defaultMessage: 'Queries Executed',
}),
rdsActiveTransactions: i18n.translate('xpack.infra.waffle.metricOptions.rdsActiveTransactions', {
defaultMessage: 'Active Transactions',
}),
rdsLatency: i18n.translate('xpack.infra.waffle.metricOptions.rdsLatency', {
defaultMessage: 'Latency',
}),
sqsMessagesVisible: i18n.translate('xpack.infra.waffle.metricOptions.sqsMessagesVisible', {
defaultMessage: 'Messages Available',
}),
sqsMessagesDelayed: i18n.translate('xpack.infra.waffle.metricOptions.sqsMessagesDelayed', {
defaultMessage: 'Messages Delayed',
}),
sqsMessagesSent: i18n.translate('xpack.infra.waffle.metricOptions.sqsMessagesSent', {
defaultMessage: 'Messages Added',
}),
sqsMessagesEmpty: i18n.translate('xpack.infra.waffle.metricOptions.sqsMessagesEmpty', {
defaultMessage: 'Messages Returned Empty',
}),
sqsOldestMessage: i18n.translate('xpack.infra.waffle.metricOptions.sqsOldestMessage', {
defaultMessage: 'Oldest Message',
}),
};
export const toGroupByOpt = (field: string) => ({
text: fieldToName(field),
field,
});
export const toMetricOpt = (
metric: SnapshotMetricType
): { text: string; value: SnapshotMetricType } | undefined => {
switch (metric) {
case 'cpu':
return {
text: ToolbarTranslations.CPUUsage,
value: 'cpu',
};
case 'memory':
return {
text: ToolbarTranslations.MemoryUsage,
value: 'memory',
};
case 'rx':
return {
text: ToolbarTranslations.InboundTraffic,
value: 'rx',
};
case 'tx':
return {
text: ToolbarTranslations.OutboundTraffic,
value: 'tx',
};
case 'logRate':
return {
text: ToolbarTranslations.LogRate,
value: 'logRate',
};
case 'load':
return {
text: ToolbarTranslations.Load,
value: 'load',
};
case 'count':
return {
text: ToolbarTranslations.Count,
value: 'count',
};
case 'diskIOReadBytes':
return {
text: ToolbarTranslations.DiskIOReadBytes,
value: 'diskIOReadBytes',
};
case 'diskIOWriteBytes':
return {
text: ToolbarTranslations.DiskIOWriteBytes,
value: 'diskIOWriteBytes',
};
case 's3BucketSize':
return {
text: ToolbarTranslations.s3BucketSize,
value: 's3BucketSize',
};
case 's3TotalRequests':
return {
text: ToolbarTranslations.s3TotalRequests,
value: 's3TotalRequests',
};
case 's3NumberOfObjects':
return {
text: ToolbarTranslations.s3NumberOfObjects,
value: 's3NumberOfObjects',
};
case 's3DownloadBytes':
return {
text: ToolbarTranslations.s3DownloadBytes,
value: 's3DownloadBytes',
};
case 's3UploadBytes':
return {
text: ToolbarTranslations.s3UploadBytes,
value: 's3UploadBytes',
};
case 'rdsConnections':
return {
text: ToolbarTranslations.rdsConnections,
value: 'rdsConnections',
};
case 'rdsQueriesExecuted':
return {
text: ToolbarTranslations.rdsQueriesExecuted,
value: 'rdsQueriesExecuted',
};
case 'rdsActiveTransactions':
return {
text: ToolbarTranslations.rdsActiveTransactions,
value: 'rdsActiveTransactions',
};
case 'rdsLatency':
return {
text: ToolbarTranslations.rdsLatency,
value: 'rdsLatency',
};
case 'sqsMessagesVisible':
return {
text: ToolbarTranslations.sqsMessagesVisible,
value: 'sqsMessagesVisible',
};
case 'sqsMessagesDelayed':
return {
text: ToolbarTranslations.sqsMessagesDelayed,
value: 'sqsMessagesDelayed',
};
case 'sqsMessagesSent':
return {
text: ToolbarTranslations.sqsMessagesSent,
value: 'sqsMessagesSent',
};
case 'sqsMessagesEmpty':
return {
text: ToolbarTranslations.sqsMessagesEmpty,
value: 'sqsMessagesEmpty',
};
case 'sqsOldestMessage':
return {
text: ToolbarTranslations.sqsOldestMessage,
value: 'sqsOldestMessage',
};
}
};

View file

@ -0,0 +1,33 @@
/*
* 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.
*/
export enum Comparator {
GT = '>',
LT = '<',
GT_OR_EQ = '>=',
LT_OR_EQ = '<=',
BETWEEN = 'between',
OUTSIDE_RANGE = 'outside',
}
export enum Aggregators {
COUNT = 'count',
AVERAGE = 'avg',
SUM = 'sum',
MIN = 'min',
MAX = 'max',
RATE = 'rate',
CARDINALITY = 'cardinality',
P95 = 'p95',
P99 = 'p99',
}
export enum AlertStates {
OK,
ALERT,
NO_DATA,
ERROR,
}

View file

@ -17,13 +17,12 @@ import { InventoryItemType, SnapshotMetricType } from '../../../../common/invent
import { InfraTimerangeInput } from '../../../../common/http_api/snapshot_api';
import { InfraSourceConfiguration } from '../../sources';
interface ConditionResult {
type ConditionResult = InventoryMetricConditions & {
shouldFire: boolean | boolean[];
currentValue?: number | null;
metric: string;
currentValue: number;
isNoData: boolean;
isError: boolean;
}
};
export const evaluateCondition = async (
condition: InventoryMetricConditions,
@ -59,19 +58,25 @@ export const evaluateCondition = async (
const comparisonFunction = comparatorMap[comparator];
return mapValues(currentValues, (value) => ({
...condition,
shouldFire:
value !== undefined &&
value !== null &&
(Array.isArray(value)
? value.map((v) => comparisonFunction(Number(v), threshold))
: comparisonFunction(value, threshold)),
metric,
isNoData: value === null,
isError: value === undefined,
...(!Array.isArray(value) ? { currentValue: value } : {}),
currentValue: getCurrentValue(value),
}));
};
const getCurrentValue: (value: any) => number = (value) => {
if (Array.isArray(value)) return getCurrentValue(last(value));
if (value !== null) return Number(value);
return NaN;
};
const getData = async (
callCluster: AlertServices['callCluster'],
nodeType: InventoryItemType,

View file

@ -5,12 +5,20 @@
*/
import { first, get } from 'lodash';
import { i18n } from '@kbn/i18n';
import moment from 'moment';
import { toMetricOpt } from '../../../../common/snapshot_metric_i18n';
import { AlertStates, InventoryMetricConditions } from './types';
import { AlertExecutorOptions } from '../../../../../alerts/server';
import { InventoryItemType, SnapshotMetricType } from '../../../../common/inventory_models/types';
import { InfraBackendLibs } from '../../infra_types';
import { METRIC_FORMATTERS } from '../../../../common/formatters/snapshot_metric_formats';
import { createFormatter } from '../../../../common/formatters';
import {
buildErrorAlertReason,
buildFiredAlertReason,
buildNoDataAlertReason,
stateToAlertMessage,
} from '../common/messages';
import { evaluateCondition } from './evaluate_condition';
interface InventoryMetricThresholdParams {
@ -18,13 +26,20 @@ interface InventoryMetricThresholdParams {
filterQuery: string | undefined;
nodeType: InventoryItemType;
sourceId?: string;
alertOnNoData?: boolean;
}
export const createInventoryMetricThresholdExecutor = (
libs: InfraBackendLibs,
alertId: string
) => async ({ services, params }: AlertExecutorOptions) => {
const { criteria, filterQuery, sourceId, nodeType } = params as InventoryMetricThresholdParams;
const {
criteria,
filterQuery,
sourceId,
nodeType,
alertOnNoData,
} = params as InventoryMetricThresholdParams;
const source = await libs.sources.getSourceConfiguration(
services.savedObjectsClient,
@ -48,26 +63,56 @@ export const createInventoryMetricThresholdExecutor = (
const isNoData = results.some((result) => result[item].isNoData);
const isError = results.some((result) => result[item].isError);
if (shouldAlertFire) {
const nextState = isError
? AlertStates.ERROR
: isNoData
? AlertStates.NO_DATA
: shouldAlertFire
? AlertStates.ALERT
: AlertStates.OK;
let reason;
if (nextState === AlertStates.ALERT) {
reason = results
.map((result) => {
if (!result[item]) return '';
const resultWithVerboseMetricName = {
...result[item],
metric: toMetricOpt(result[item].metric)?.text || result[item].metric,
};
return buildFiredAlertReason(resultWithVerboseMetricName);
})
.join('\n');
}
if (alertOnNoData) {
if (nextState === AlertStates.NO_DATA) {
reason = results
.filter((result) => result[item].isNoData)
.map((result) => buildNoDataAlertReason(result[item]))
.join('\n');
} else if (nextState === AlertStates.ERROR) {
reason = results
.filter((result) => result[item].isError)
.map((result) => buildErrorAlertReason(result[item].metric))
.join('\n');
}
}
if (reason) {
alertInstance.scheduleActions(FIRED_ACTIONS.id, {
group: item,
item,
valueOf: mapToConditionsLookup(results, (result) =>
alertState: stateToAlertMessage[nextState],
reason,
timestamp: moment().toISOString(),
value: mapToConditionsLookup(results, (result) =>
formatMetric(result[item].metric, result[item].currentValue)
),
thresholdOf: mapToConditionsLookup(criteria, (c) => c.threshold),
metricOf: mapToConditionsLookup(criteria, (c) => c.metric),
threshold: mapToConditionsLookup(criteria, (c) => c.threshold),
metric: mapToConditionsLookup(criteria, (c) => c.metric),
});
}
alertInstance.replaceState({
alertState: isError
? AlertStates.ERROR
: isNoData
? AlertStates.NO_DATA
: shouldAlertFire
? AlertStates.ALERT
: AlertStates.OK,
alertState: nextState,
});
}
};

View file

@ -35,6 +35,7 @@ export const registerMetricInventoryThresholdAlertType = (libs: InfraBackendLibs
schema.string({ validate: validateIsStringElasticsearchJSONFilter })
),
sourceId: schema.string(),
alertOnNoData: schema.maybe(schema.boolean()),
},
{ unknowns: 'allow' }
),

View file

@ -5,25 +5,12 @@
*/
import { Unit } from '@elastic/datemath';
import { SnapshotMetricType } from '../../../../common/inventory_models/types';
import { Comparator, AlertStates } from '../common/types';
export { Comparator, AlertStates };
export const METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID = 'metrics.alert.inventory.threshold';
export enum Comparator {
GT = '>',
LT = '<',
GT_OR_EQ = '>=',
LT_OR_EQ = '<=',
BETWEEN = 'between',
OUTSIDE_RANGE = 'outside',
}
export enum AlertStates {
OK,
ALERT,
NO_DATA,
ERROR,
}
export interface InventoryMetricConditions {
metric: SnapshotMetricType;
timeSize: number;

View file

@ -15,8 +15,8 @@ import { InfraDatabaseSearchResponse } from '../../../adapters/framework/adapter
import { createAfterKeyHandler } from '../../../../utils/create_afterkey_handler';
import { AlertServices, AlertExecutorOptions } from '../../../../../../alerts/server';
import { getAllCompositeData } from '../../../../utils/get_all_composite_data';
import { DOCUMENT_COUNT_I18N } from '../../common/messages';
import { MetricExpressionParams, Comparator, Aggregators } from '../types';
import { DOCUMENT_COUNT_I18N } from '../messages';
import { getElasticsearchMetricQuery } from './metric_query';
interface Aggregation {

View file

@ -8,14 +8,14 @@ import { i18n } from '@kbn/i18n';
import moment from 'moment';
import { AlertExecutorOptions } from '../../../../../alerts/server';
import { InfraBackendLibs } from '../../infra_types';
import { AlertStates } from './types';
import { evaluateAlert } from './lib/evaluate_alert';
import {
buildErrorAlertReason,
buildFiredAlertReason,
buildNoDataAlertReason,
stateToAlertMessage,
} from './messages';
} from '../common/messages';
import { AlertStates } from './types';
import { evaluateAlert } from './lib/evaluate_alert';
export const createMetricThresholdExecutor = (libs: InfraBackendLibs, alertId: string) =>
async function (options: AlertExecutorOptions) {

View file

@ -3,18 +3,11 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { Unit } from '@elastic/datemath';
export const METRIC_THRESHOLD_ALERT_TYPE_ID = 'metrics.alert.threshold';
import { Comparator, AlertStates } from '../common/types';
export enum Comparator {
GT = '>',
LT = '<',
GT_OR_EQ = '>=',
LT_OR_EQ = '<=',
BETWEEN = 'between',
OUTSIDE_RANGE = 'outside',
}
export { Comparator, AlertStates };
export const METRIC_THRESHOLD_ALERT_TYPE_ID = 'metrics.alert.threshold';
export enum Aggregators {
COUNT = 'count',
@ -28,13 +21,6 @@ export enum Aggregators {
P99 = 'p99',
}
export enum AlertStates {
OK,
ALERT,
NO_DATA,
ERROR,
}
interface BaseMetricExpressionParams {
timeSize: number;
timeUnit: Unit;