Skip to content

Commit 250fe67

Browse files
[Metrics UI] Add full custom metric UI to inventory alerts (#81929)
Co-authored-by: Kibana Machine <[email protected]>
1 parent 074ef6f commit 250fe67

File tree

4 files changed

+282
-94
lines changed

4 files changed

+282
-94
lines changed

x-pack/plugins/infra/public/alerting/inventory/components/expression.test.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { AlertsContextValue } from '../../../../../triggers_actions_ui/public/ap
1212
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
1313
import { InventoryMetricConditions } from '../../../../server/lib/alerting/inventory_metric_threshold/types';
1414
import React from 'react';
15-
import { Expressions, AlertContextMeta, ExpressionRow } from './expression';
15+
import { Expressions, AlertContextMeta, ExpressionRow, defaultExpression } from './expression';
1616
import { act } from 'react-dom/test-utils';
1717
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
1818
import { Comparator } from '../../../../server/lib/alerting/metric_threshold/types';
@@ -105,6 +105,7 @@ describe('Expression', () => {
105105
threshold: [],
106106
timeSize: 1,
107107
timeUnit: 'm',
108+
customMetric: defaultExpression.customMetric,
108109
},
109110
]);
110111
});
@@ -155,6 +156,7 @@ describe('ExpressionRow', () => {
155156
alertsContextMetadata={{
156157
customMetrics: [],
157158
}}
159+
fields={[{ name: 'some.system.field', type: 'bzzz' }]}
158160
/>
159161
);
160162

x-pack/plugins/infra/public/alerting/inventory/components/expression.tsx

Lines changed: 31 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
* you may not use this file except in compliance with the Elastic License.
55
*/
66

7-
import { set } from '@elastic/safer-lodash-set';
8-
import { debounce, pick, uniqBy, isEqual } from 'lodash';
7+
import { debounce, pick } from 'lodash';
98
import { Unit } from '@elastic/datemath';
109
import React, { useCallback, useMemo, useEffect, useState, ChangeEvent } from 'react';
10+
import { IFieldType } from 'src/plugins/data/public';
1111
import {
1212
EuiFlexGroup,
1313
EuiFlexItem,
@@ -23,7 +23,6 @@ import {
2323
} from '@elastic/eui';
2424
import { FormattedMessage } from '@kbn/i18n/react';
2525
import { i18n } from '@kbn/i18n';
26-
import { getCustomMetricLabel } from '../../../../common/formatters/get_custom_metric_label';
2726
import { toMetricOpt } from '../../../../common/snapshot_metric_i18n';
2827
import { AlertPreview } from '../../common';
2928
import { METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID } from '../../../../common/alerting/metrics';
@@ -95,13 +94,18 @@ interface Props {
9594
setAlertProperty(key: string, value: any): void;
9695
}
9796

98-
const defaultExpression = {
97+
export const defaultExpression = {
9998
metric: 'cpu' as SnapshotMetricType,
10099
comparator: Comparator.GT,
101100
threshold: [],
102101
timeSize: 1,
103102
timeUnit: 'm',
104-
customMetric: undefined,
103+
customMetric: {
104+
type: 'custom',
105+
id: 'alert-custom-metric',
106+
field: '',
107+
aggregation: 'avg',
108+
},
105109
} as InventoryMetricConditions;
106110

107111
export const Expressions: React.FC<Props> = (props) => {
@@ -226,7 +230,7 @@ export const Expressions: React.FC<Props> = (props) => {
226230
metric: md.options.metric!.type,
227231
customMetric: SnapshotCustomMetricInputRT.is(md.options.metric)
228232
? md.options.metric
229-
: undefined,
233+
: defaultExpression.customMetric,
230234
} as InventoryMetricConditions,
231235
]);
232236
} else {
@@ -306,6 +310,7 @@ export const Expressions: React.FC<Props> = (props) => {
306310
errors={errors[idx] || emptyError}
307311
expression={e || {}}
308312
alertsContextMetadata={alertsContext.metadata}
313+
fields={derivedIndexPattern.fields}
309314
/>
310315
);
311316
})}
@@ -415,6 +420,7 @@ interface ExpressionRowProps {
415420
remove(id: number): void;
416421
setAlertParams(id: number, params: Partial<InventoryMetricConditions>): void;
417422
alertsContextMetadata: AlertsContextValue<AlertContextMeta>['metadata'];
423+
fields: IFieldType[];
418424
}
419425

420426
const StyledExpressionRow = euiStyled(EuiFlexGroup)`
@@ -428,48 +434,25 @@ const StyledExpression = euiStyled.div`
428434
`;
429435

430436
export const ExpressionRow: React.FC<ExpressionRowProps> = (props) => {
431-
const {
432-
setAlertParams,
433-
expression,
434-
errors,
435-
expressionId,
436-
remove,
437-
canDelete,
438-
alertsContextMetadata,
439-
} = props;
437+
const { setAlertParams, expression, errors, expressionId, remove, canDelete, fields } = props;
440438
const { metric, comparator = Comparator.GT, threshold = [], customMetric } = expression;
441-
const [customMetrics, updateCustomMetrics] = useState<SnapshotCustomMetricInput[]>([]);
442-
443-
// Create and uniquify a list of custom metrics including:
444-
// - The alert metadata context (which only gives us custom metrics on the inventory page)
445-
// - The custom metric stored in the expression (necessary when editing this alert without having
446-
// access to the metadata context)
447-
// - Whatever custom metrics were previously stored in this list (to preserve the custom metric in the dropdown
448-
// if the user edits the alert and switches away from the custom metric)
449-
useEffect(() => {
450-
const ctxCustomMetrics = alertsContextMetadata?.customMetrics ?? [];
451-
const expressionCustomMetrics = customMetric ? [customMetric] : [];
452-
const newCustomMetrics = uniqBy(
453-
[...customMetrics, ...ctxCustomMetrics, ...expressionCustomMetrics],
454-
(cm: SnapshotCustomMetricInput) => cm.id
455-
);
456-
if (!isEqual(customMetrics, newCustomMetrics)) updateCustomMetrics(newCustomMetrics);
457-
}, [alertsContextMetadata, customMetric, customMetrics, updateCustomMetrics]);
458439

459440
const updateMetric = useCallback(
460441
(m?: SnapshotMetricType | string) => {
461-
const newMetric = SnapshotMetricTypeRT.is(m) ? m : 'custom';
442+
const newMetric = SnapshotMetricTypeRT.is(m) ? m : Boolean(m) ? 'custom' : undefined;
462443
const newAlertParams = { ...expression, metric: newMetric };
463-
if (newMetric === 'custom' && customMetrics) {
464-
set(
465-
newAlertParams,
466-
'customMetric',
467-
customMetrics.find((cm) => cm.id === m)
468-
);
469-
}
470444
setAlertParams(expressionId, newAlertParams);
471445
},
472-
[expressionId, expression, setAlertParams, customMetrics]
446+
[expressionId, expression, setAlertParams]
447+
);
448+
449+
const updateCustomMetric = useCallback(
450+
(cm?: SnapshotCustomMetricInput) => {
451+
if (SnapshotCustomMetricInputRT.is(cm)) {
452+
setAlertParams(expressionId, { ...expression, customMetric: cm });
453+
}
454+
},
455+
[expressionId, expression, setAlertParams]
473456
);
474457

475458
const updateComparator = useCallback(
@@ -515,17 +498,8 @@ export const ExpressionRow: React.FC<ExpressionRowProps> = (props) => {
515498
myMetrics = containerMetricTypes;
516499
break;
517500
}
518-
const baseMetricOpts = myMetrics.map(toMetricOpt);
519-
const customMetricOpts = customMetrics
520-
? customMetrics.map((m, i) => ({
521-
text: getCustomMetricLabel(m),
522-
value: m.id,
523-
}))
524-
: [];
525-
return [...baseMetricOpts, ...customMetricOpts];
526-
}, [props.nodeType, customMetrics]);
527-
528-
const selectedMetricValue = metric === 'custom' && customMetric ? customMetric.id : metric!;
501+
return myMetrics.map(toMetricOpt);
502+
}, [props.nodeType]);
529503

530504
return (
531505
<>
@@ -535,8 +509,8 @@ export const ExpressionRow: React.FC<ExpressionRowProps> = (props) => {
535509
<StyledExpression>
536510
<MetricExpression
537511
metric={{
538-
value: selectedMetricValue,
539-
text: ofFields.find((v) => v?.value === selectedMetricValue)?.text || '',
512+
value: metric!,
513+
text: ofFields.find((v) => v?.value === metric)?.text || '',
540514
}}
541515
metrics={
542516
ofFields.filter((m) => m !== undefined && m.value !== undefined) as Array<{
@@ -545,7 +519,10 @@ export const ExpressionRow: React.FC<ExpressionRowProps> = (props) => {
545519
}>
546520
}
547521
onChange={updateMetric}
522+
onChangeCustom={updateCustomMetric}
548523
errors={errors}
524+
customMetric={customMetric}
525+
fields={fields}
549526
/>
550527
</StyledExpression>
551528
<StyledExpression>

0 commit comments

Comments
 (0)