"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.aggregationType = exports.ExpressionRow = void 0; var _eui = require("@elastic/eui"); var _i18n = require("@kbn/i18n"); var _i18nReact = require("@kbn/i18n-react"); var _lodash = require("lodash"); var _react = _interopRequireWildcard(require("react")); var _common = require("@kbn/kibana-react-plugin/common"); var _public = require("@kbn/triggers-actions-ui-plugin/public"); var _useToggle = _interopRequireDefault(require("react-use/lib/useToggle")); var _metrics = require("../../../../common/alerting/metrics"); var _corrected_percent_convert = require("../../../../common/utils/corrected_percent_convert"); var _types = require("../types"); var _custom_equation = require("./custom_equation"); var _i18n_strings = require("../i18n_strings"); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ const customComparators = { ..._public.builtInComparators, [_metrics.Comparator.OUTSIDE_RANGE]: { text: _i18n.i18n.translate('xpack.infra.metrics.alertFlyout.outsideRangeLabel', { defaultMessage: 'Is not between' }), value: _metrics.Comparator.OUTSIDE_RANGE, requiredValues: 2 } }; const StyledExpressionRow = (0, _common.euiStyled)(_eui.EuiFlexGroup)` display: flex; flex-wrap: wrap; align-items: center; margin: 0 -4px; `; const StyledExpression = _common.euiStyled.div` padding: 0 4px; `; const StyledHealth = (0, _common.euiStyled)(_eui.EuiHealth)` margin-left: 4px; `; const ExpressionRow = props => { var _ref, _ref2; const [isExpanded, toggle] = (0, _useToggle.default)(true); const { dataView, children, setRuleParams, expression, errors, expressionId, remove, fields, canDelete } = props; const { aggType = _types.AGGREGATION_TYPES.MAX, metric, comparator = _metrics.Comparator.GT, threshold = [], warningThreshold = [], warningComparator } = expression; const [displayWarningThreshold, setDisplayWarningThreshold] = (0, _react.useState)(Boolean(warningThreshold === null || warningThreshold === void 0 ? void 0 : warningThreshold.length)); const isMetricPct = (0, _react.useMemo)(() => Boolean(metric && metric.endsWith('.pct')), [metric]); const updateAggType = (0, _react.useCallback)(at => { setRuleParams(expressionId, { ...expression, aggType: at, metric: ['custom', 'count'].includes(at) ? undefined : expression.metric, customMetrics: at === 'custom' ? expression.customMetrics : undefined, equation: at === 'custom' ? expression.equation : undefined, label: at === 'custom' ? expression.label : undefined }); }, [expressionId, expression, setRuleParams]); const updateMetric = (0, _react.useCallback)(m => { setRuleParams(expressionId, { ...expression, metric: m }); }, [expressionId, expression, setRuleParams]); const updateComparator = (0, _react.useCallback)(c => { setRuleParams(expressionId, { ...expression, comparator: c }); }, [expressionId, expression, setRuleParams]); const updateWarningComparator = (0, _react.useCallback)(c => { setRuleParams(expressionId, { ...expression, warningComparator: c }); }, [expressionId, expression, setRuleParams]); const convertThreshold = (0, _react.useCallback)(enteredThreshold => isMetricPct ? enteredThreshold.map(v => (0, _corrected_percent_convert.pctToDecimal)(v)) : enteredThreshold, [isMetricPct]); const updateThreshold = (0, _react.useCallback)(enteredThreshold => { const t = convertThreshold(enteredThreshold); if (t.join() !== expression.threshold.join()) { setRuleParams(expressionId, { ...expression, threshold: t }); } }, [expressionId, expression, convertThreshold, setRuleParams]); const updateWarningThreshold = (0, _react.useCallback)(enteredThreshold => { var _expression$warningTh; const t = convertThreshold(enteredThreshold); if (t.join() !== ((_expression$warningTh = expression.warningThreshold) === null || _expression$warningTh === void 0 ? void 0 : _expression$warningTh.join())) { setRuleParams(expressionId, { ...expression, warningThreshold: t }); } }, [expressionId, expression, convertThreshold, setRuleParams]); const toggleWarningThreshold = (0, _react.useCallback)(() => { if (!displayWarningThreshold) { setDisplayWarningThreshold(true); setRuleParams(expressionId, { ...expression, warningComparator: comparator, warningThreshold: [] }); } else { setDisplayWarningThreshold(false); setRuleParams(expressionId, (0, _lodash.omit)(expression, 'warningComparator', 'warningThreshold')); } }, [displayWarningThreshold, setDisplayWarningThreshold, setRuleParams, comparator, expression, expressionId]); const handleCustomMetricChange = (0, _react.useCallback)(exp => { setRuleParams(expressionId, exp); }, [expressionId, setRuleParams]); const criticalThresholdExpression = /*#__PURE__*/_react.default.createElement(ThresholdElement, { comparator: comparator, threshold: threshold, updateComparator: updateComparator, updateThreshold: updateThreshold, errors: (_ref = errors.critical) !== null && _ref !== void 0 ? _ref : {}, isMetricPct: isMetricPct }); const warningThresholdExpression = displayWarningThreshold && /*#__PURE__*/_react.default.createElement(ThresholdElement, { comparator: warningComparator || comparator, threshold: warningThreshold, updateComparator: updateWarningComparator, updateThreshold: updateWarningThreshold, errors: (_ref2 = errors.warning) !== null && _ref2 !== void 0 ? _ref2 : {}, isMetricPct: isMetricPct }); const normalizedFields = fields.map(f => ({ normalizedType: f.type, name: f.name })); return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexGroup, { gutterSize: "xs" }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: false }, /*#__PURE__*/_react.default.createElement(_eui.EuiButtonIcon, { iconType: isExpanded ? 'arrowDown' : 'arrowRight', onClick: toggle, "data-test-subj": "expandRow", "aria-label": _i18n.i18n.translate('xpack.infra.metrics.alertFlyout.expandRowLabel', { defaultMessage: 'Expand row.' }) })), /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: true }, /*#__PURE__*/_react.default.createElement(StyledExpressionRow, { style: { gap: aggType !== 'custom' ? 24 : 12 } }, /*#__PURE__*/_react.default.createElement(StyledExpression, null, /*#__PURE__*/_react.default.createElement(_public.WhenExpression, { customAggTypesOptions: aggregationType, aggType: aggType, onChangeSelectedAggType: updateAggType })), !['count', 'custom'].includes(aggType) && /*#__PURE__*/_react.default.createElement(StyledExpression, null, /*#__PURE__*/_react.default.createElement(_public.OfExpression, { customAggTypesOptions: aggregationType, aggField: metric, fields: normalizedFields, aggType: aggType, errors: errors, onChangeSelectedAggField: updateMetric, helpText: /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.infra.metrics.alertFlyout.ofExpression.helpTextDetail", defaultMessage: "Can't find a metric? {documentationLink}.", values: { documentationLink: /*#__PURE__*/_react.default.createElement(_eui.EuiLink, { "data-test-subj": "infraExpressionRowLearnHowToAddMoreDataLink", href: "https://www.elastic.co/guide/en/observability/current/configure-settings.html", target: "BLANK" }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.infra.metrics.alertFlyout.ofExpression.popoverLinkLabel", defaultMessage: "Learn how to add more data" })) } }), "data-test-subj": "ofExpression" })), !displayWarningThreshold && criticalThresholdExpression, !displayWarningThreshold && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: 'xs' }), /*#__PURE__*/_react.default.createElement(StyledExpressionRow, null, /*#__PURE__*/_react.default.createElement(_eui.EuiButtonEmpty, { "data-test-subj": "infraExpressionRowAddWarningThresholdButton", color: 'primary', flush: 'left', size: "xs", iconType: 'plusInCircleFilled', onClick: toggleWarningThreshold }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.infra.metrics.alertFlyout.addWarningThreshold", defaultMessage: "Add warning threshold" }))))), displayWarningThreshold && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(StyledExpressionRow, null, criticalThresholdExpression, /*#__PURE__*/_react.default.createElement(StyledHealth, { color: "danger" }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.infra.metrics.alertFlyout.criticalThreshold", defaultMessage: "Alert" }))), /*#__PURE__*/_react.default.createElement(StyledExpressionRow, null, warningThresholdExpression, /*#__PURE__*/_react.default.createElement(StyledHealth, { color: "warning" }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.infra.metrics.alertFlyout.warningThreshold", defaultMessage: "Warning" })), /*#__PURE__*/_react.default.createElement(_eui.EuiButtonIcon, { "aria-label": _i18n.i18n.translate('xpack.infra.metrics.alertFlyout.removeWarningThreshold', { defaultMessage: 'Remove warningThreshold' }), iconSize: "s", color: "text", iconType: 'minusInCircleFilled', onClick: toggleWarningThreshold }))), aggType === _metrics.Aggregators.CUSTOM && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: 'm' }), /*#__PURE__*/_react.default.createElement(StyledExpressionRow, null, /*#__PURE__*/_react.default.createElement(_custom_equation.CustomEquationEditor, { expression: expression, fields: normalizedFields, aggregationTypes: aggregationType, onChange: handleCustomMetricChange, errors: errors, dataView: dataView })), /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: 's' }))), canDelete && /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: false }, /*#__PURE__*/_react.default.createElement(_eui.EuiButtonIcon, { "aria-label": _i18n.i18n.translate('xpack.infra.metrics.alertFlyout.removeCondition', { defaultMessage: 'Remove condition' }), color: 'danger', iconType: 'trash', onClick: () => remove(expressionId) }))), isExpanded ? /*#__PURE__*/_react.default.createElement("div", { style: { padding: '0 0 0 28px' } }, children) : null, /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: 's' })); }; exports.ExpressionRow = ExpressionRow; const ThresholdElement = ({ updateComparator, updateThreshold, threshold, isMetricPct, comparator, errors }) => { const displayedThreshold = (0, _react.useMemo)(() => { if (isMetricPct) return threshold.map(v => (0, _corrected_percent_convert.decimalToPct)(v)); return threshold; }, [threshold, isMetricPct]); return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(StyledExpression, null, /*#__PURE__*/_react.default.createElement(_public.ThresholdExpression, { thresholdComparator: comparator || _metrics.Comparator.GT, threshold: displayedThreshold, customComparators: customComparators, onChangeSelectedThresholdComparator: updateComparator, onChangeSelectedThreshold: updateThreshold, errors: errors })), isMetricPct && /*#__PURE__*/_react.default.createElement("div", { style: { alignSelf: 'center' } }, /*#__PURE__*/_react.default.createElement(_eui.EuiText, { size: 's' }, "%"))); }; const aggregationType = { avg: { text: _i18n.i18n.translate('xpack.infra.metrics.alertFlyout.aggregationText.avg', { defaultMessage: 'Average' }), fieldRequired: true, validNormalizedTypes: ['number', 'histogram'], value: _types.AGGREGATION_TYPES.AVERAGE }, max: { text: _i18n.i18n.translate('xpack.infra.metrics.alertFlyout.aggregationText.max', { defaultMessage: 'Max' }), fieldRequired: true, validNormalizedTypes: ['number', 'date', 'histogram'], value: _types.AGGREGATION_TYPES.MAX }, min: { text: _i18n.i18n.translate('xpack.infra.metrics.alertFlyout.aggregationText.min', { defaultMessage: 'Min' }), fieldRequired: true, validNormalizedTypes: ['number', 'date', 'histogram'], value: _types.AGGREGATION_TYPES.MIN }, cardinality: { text: _i18n.i18n.translate('xpack.infra.metrics.alertFlyout.aggregationText.cardinality', { defaultMessage: 'Cardinality' }), fieldRequired: false, value: _types.AGGREGATION_TYPES.CARDINALITY, validNormalizedTypes: ['number', 'string', 'ip', 'date'] }, rate: { text: _i18n.i18n.translate('xpack.infra.metrics.alertFlyout.aggregationText.rate', { defaultMessage: 'Rate' }), fieldRequired: false, value: _types.AGGREGATION_TYPES.RATE, validNormalizedTypes: ['number'] }, count: { text: _i18n.i18n.translate('xpack.infra.metrics.alertFlyout.aggregationText.count', { defaultMessage: 'Document count' }), fieldRequired: false, value: _types.AGGREGATION_TYPES.COUNT, validNormalizedTypes: ['number'] }, sum: { text: _i18n.i18n.translate('xpack.infra.metrics.alertFlyout.aggregationText.sum', { defaultMessage: 'Sum' }), fieldRequired: false, value: _types.AGGREGATION_TYPES.SUM, validNormalizedTypes: ['number', 'histogram'] }, p95: { text: _i18n.i18n.translate('xpack.infra.metrics.alertFlyout.aggregationText.p95', { defaultMessage: '95th Percentile' }), fieldRequired: false, value: _types.AGGREGATION_TYPES.P95, validNormalizedTypes: ['number', 'histogram'] }, p99: { text: _i18n.i18n.translate('xpack.infra.metrics.alertFlyout.aggregationText.p99', { defaultMessage: '99th Percentile' }), fieldRequired: false, value: _types.AGGREGATION_TYPES.P99, validNormalizedTypes: ['number', 'histogram'] }, custom: { text: _i18n_strings.CUSTOM_EQUATION, fieldRequired: false, value: _types.AGGREGATION_TYPES.CUSTOM, validNormalizedTypes: ['number', 'histogram'] } }; exports.aggregationType = aggregationType;