"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.EMPTY_EXECUTION_LOG_RESULT = exports.ACTION_FILTER = void 0; exports.formatExecutionKPIResult = formatExecutionKPIResult; exports.formatExecutionLogResult = formatExecutionLogResult; exports.formatSortForBucketSort = formatSortForBucketSort; exports.formatSortForTermSort = formatSortForTermSort; exports.getExecutionKPIAggregation = void 0; exports.getExecutionLogAggregation = getExecutionLogAggregation; var _boom = _interopRequireDefault(require("@hapi/boom")); var _lodash = require("lodash"); var _esQuery = require("@kbn/es-query"); var _common = require("../../common"); /* * 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 DEFAULT_MAX_BUCKETS_LIMIT = 1000; // do not retrieve more than this number of executions const DEFAULT_MAX_KPI_BUCKETS_LIMIT = 10000; const SPACE_ID_FIELD = 'kibana.space_ids'; const ACTION_NAME_FIELD = 'kibana.action.name'; const ACTION_ID_FIELD = 'kibana.action.id'; const START_FIELD = 'event.start'; const ACTION_FIELD = 'event.action'; const OUTCOME_FIELD = 'event.outcome'; const DURATION_FIELD = 'event.duration'; const MESSAGE_FIELD = 'message'; const VERSION_FIELD = 'kibana.version'; const ERROR_MESSAGE_FIELD = 'error.message'; const SCHEDULE_DELAY_FIELD = 'kibana.task.schedule_delay'; const EXECUTION_UUID_FIELD = 'kibana.action.execution.uuid'; const EXECUTION_SOURCE_FIELD = 'kibana.action.execution.source'; const Millis2Nanos = 1000 * 1000; const ACTION_FILTER = 'event.provider: actions AND NOT event.action: execute-start'; exports.ACTION_FILTER = ACTION_FILTER; const EMPTY_EXECUTION_LOG_RESULT = { total: 0, data: [] }; exports.EMPTY_EXECUTION_LOG_RESULT = EMPTY_EXECUTION_LOG_RESULT; const ExecutionLogSortFields = { timestamp: 'actionExecution>executeStartTime', execution_duration: 'actionExecution>executionDuration', schedule_delay: 'actionExecution>scheduleDelay' }; const getExecutionKPIAggregation = filter => { const dslFilterQuery = buildDslFilterQuery(filter); return { executionKpiAgg: { ...(dslFilterQuery ? { filter: { bool: { filter: dslFilterQuery } } } : {}), aggs: { executionUuid: { // Bucket by execution UUID terms: { field: EXECUTION_UUID_FIELD, size: DEFAULT_MAX_KPI_BUCKETS_LIMIT, order: formatSortForTermSort([{ timestamp: { order: 'desc' } }]) }, aggs: { executionUuidSorted: { bucket_sort: { from: 0, size: DEFAULT_MAX_KPI_BUCKETS_LIMIT, gap_policy: 'insert_zeros' } }, actionExecution: { filter: { bool: { must: [{ match: { [ACTION_FIELD]: 'execute' } }] } }, aggs: { executeStartTime: { min: { field: START_FIELD } }, actionExecutionOutcomes: { terms: { size: 3, field: OUTCOME_FIELD } } } } } } } } }; }; exports.getExecutionKPIAggregation = getExecutionKPIAggregation; function getExecutionLogAggregation({ filter, page, perPage, sort }) { // Check if valid sort fields const sortFields = (0, _lodash.flatMap)(sort, s => Object.keys(s)); for (const field of sortFields) { if (!Object.keys(ExecutionLogSortFields).includes(field)) { throw _boom.default.badRequest(`Invalid sort field "${field}" - must be one of [${Object.keys(ExecutionLogSortFields).join(',')}]`); } } // Check if valid page value if (page <= 0) { throw _boom.default.badRequest(`Invalid page field "${page}" - must be greater than 0`); } // Check if valid page value if (perPage <= 0) { throw _boom.default.badRequest(`Invalid perPage field "${perPage}" - must be greater than 0`); } const dslFilterQuery = buildDslFilterQuery(filter); return { executionLogAgg: { ...(dslFilterQuery ? { filter: { bool: { filter: dslFilterQuery } } } : {}), aggs: { // Get total number of executions executionUuidCardinality: { filter: { bool: { must: [{ match: { [ACTION_FIELD]: 'execute' } }] } }, aggs: { executionUuidCardinality: { cardinality: { field: EXECUTION_UUID_FIELD } } } }, executionUuid: { // Bucket by execution UUID terms: { field: EXECUTION_UUID_FIELD, size: DEFAULT_MAX_BUCKETS_LIMIT, order: formatSortForTermSort(sort) }, aggs: { // Bucket sort to allow paging through executions executionUuidSorted: { bucket_sort: { sort: formatSortForBucketSort(sort), from: (page - 1) * perPage, size: perPage, gap_policy: 'insert_zeros' } }, // Filter by action execute doc and get information from this event actionExecution: { filter: { bool: { must: [{ match: { [ACTION_FIELD]: 'execute' } }] } }, aggs: { executeStartTime: { min: { field: START_FIELD } }, scheduleDelay: { max: { field: SCHEDULE_DELAY_FIELD } }, executionDuration: { max: { field: DURATION_FIELD } }, outcomeAndMessage: { top_hits: { _source: { includes: [OUTCOME_FIELD, MESSAGE_FIELD, ERROR_MESSAGE_FIELD, VERSION_FIELD, SPACE_ID_FIELD, ACTION_NAME_FIELD, ACTION_ID_FIELD, EXECUTION_SOURCE_FIELD] } } } } }, // If there was a timeout, this filter will return non-zero doc count timeoutMessage: { filter: { bool: { must: [{ match: { [ACTION_FIELD]: 'execute-timeout' } }] } } } } } } } }; } function buildDslFilterQuery(filter) { try { const filterKueryNode = typeof filter === 'string' ? (0, _esQuery.fromKueryExpression)(filter) : filter; return filterKueryNode ? (0, _esQuery.toElasticsearchQuery)(filterKueryNode) : undefined; } catch (err) { throw _boom.default.badRequest(`Invalid kuery syntax for filter ${filter}`); } } function formatExecutionLogAggBucket(bucket) { var _bucket$actionExecuti, _bucket$actionExecuti2, _bucket$actionExecuti3, _bucket$actionExecuti4, _bucket$actionExecuti5, _bucket$actionExecuti6, _bucket$actionExecuti7, _bucket$actionExecuti8, _bucket$actionExecuti9, _outcomeAndMessage$ki, _outcomeAndMessage$ki2, _outcomeAndMessage$ki3, _outcomeAndMessage$me, _outcomeAndMessage$er, _outcomeAndMessage$er2, _outcomeAndMessage$ki4, _outcomeAndMessage$ki5, _outcomeAndMessage$ki6, _outcomeAndMessage$ki7, _outcomeAndMessage$ki8, _outcomeAndMessage$ki9, _outcomeAndMessage$ki10, _outcomeAndMessage$ki11, _outcomeAndMessage$ki12, _outcomeAndMessage$ki13, _outcomeAndMessage$ki14, _outcomeAndMessage$ki15, _outcomeAndMessage$ki16, _outcomeAndMessage$ki17, _bucket$timeoutMessag, _bucket$timeoutMessag2, _bucket$key, _bucket$actionExecuti10, _bucket$actionExecuti11; const durationUs = bucket !== null && bucket !== void 0 && (_bucket$actionExecuti = bucket.actionExecution) !== null && _bucket$actionExecuti !== void 0 && (_bucket$actionExecuti2 = _bucket$actionExecuti.executionDuration) !== null && _bucket$actionExecuti2 !== void 0 && _bucket$actionExecuti2.value ? bucket.actionExecution.executionDuration.value : 0; const scheduleDelayUs = bucket !== null && bucket !== void 0 && (_bucket$actionExecuti3 = bucket.actionExecution) !== null && _bucket$actionExecuti3 !== void 0 && (_bucket$actionExecuti4 = _bucket$actionExecuti3.scheduleDelay) !== null && _bucket$actionExecuti4 !== void 0 && _bucket$actionExecuti4.value ? bucket.actionExecution.scheduleDelay.value : 0; const outcomeAndMessage = (_bucket$actionExecuti5 = bucket === null || bucket === void 0 ? void 0 : (_bucket$actionExecuti6 = bucket.actionExecution) === null || _bucket$actionExecuti6 === void 0 ? void 0 : (_bucket$actionExecuti7 = _bucket$actionExecuti6.outcomeAndMessage) === null || _bucket$actionExecuti7 === void 0 ? void 0 : (_bucket$actionExecuti8 = _bucket$actionExecuti7.hits) === null || _bucket$actionExecuti8 === void 0 ? void 0 : (_bucket$actionExecuti9 = _bucket$actionExecuti8.hits[0]) === null || _bucket$actionExecuti9 === void 0 ? void 0 : _bucket$actionExecuti9._source) !== null && _bucket$actionExecuti5 !== void 0 ? _bucket$actionExecuti5 : {}; let status = (_outcomeAndMessage$ki = (_outcomeAndMessage$ki2 = outcomeAndMessage.kibana) === null || _outcomeAndMessage$ki2 === void 0 ? void 0 : (_outcomeAndMessage$ki3 = _outcomeAndMessage$ki2.alerting) === null || _outcomeAndMessage$ki3 === void 0 ? void 0 : _outcomeAndMessage$ki3.outcome) !== null && _outcomeAndMessage$ki !== void 0 ? _outcomeAndMessage$ki : ''; if ((0, _lodash.isEmpty)(status)) { var _outcomeAndMessage$ev, _outcomeAndMessage$ev2; status = (_outcomeAndMessage$ev = (_outcomeAndMessage$ev2 = outcomeAndMessage.event) === null || _outcomeAndMessage$ev2 === void 0 ? void 0 : _outcomeAndMessage$ev2.outcome) !== null && _outcomeAndMessage$ev !== void 0 ? _outcomeAndMessage$ev : ''; } const outcomeMessage = (_outcomeAndMessage$me = outcomeAndMessage.message) !== null && _outcomeAndMessage$me !== void 0 ? _outcomeAndMessage$me : ''; const outcomeErrorMessage = (_outcomeAndMessage$er = (_outcomeAndMessage$er2 = outcomeAndMessage.error) === null || _outcomeAndMessage$er2 === void 0 ? void 0 : _outcomeAndMessage$er2.message) !== null && _outcomeAndMessage$er !== void 0 ? _outcomeAndMessage$er : ''; const message = status === 'failure' ? `${outcomeMessage} - ${outcomeErrorMessage}` : outcomeMessage; const version = (_outcomeAndMessage$ki4 = (_outcomeAndMessage$ki5 = outcomeAndMessage.kibana) === null || _outcomeAndMessage$ki5 === void 0 ? void 0 : _outcomeAndMessage$ki5.version) !== null && _outcomeAndMessage$ki4 !== void 0 ? _outcomeAndMessage$ki4 : ''; const source = (_outcomeAndMessage$ki6 = (_outcomeAndMessage$ki7 = outcomeAndMessage.kibana) === null || _outcomeAndMessage$ki7 === void 0 ? void 0 : (_outcomeAndMessage$ki8 = _outcomeAndMessage$ki7.action) === null || _outcomeAndMessage$ki8 === void 0 ? void 0 : (_outcomeAndMessage$ki9 = _outcomeAndMessage$ki8.execution) === null || _outcomeAndMessage$ki9 === void 0 ? void 0 : _outcomeAndMessage$ki9.source) !== null && _outcomeAndMessage$ki6 !== void 0 ? _outcomeAndMessage$ki6 : ''; const spaceIds = (_outcomeAndMessage$ki10 = outcomeAndMessage === null || outcomeAndMessage === void 0 ? void 0 : (_outcomeAndMessage$ki11 = outcomeAndMessage.kibana) === null || _outcomeAndMessage$ki11 === void 0 ? void 0 : _outcomeAndMessage$ki11.space_ids) !== null && _outcomeAndMessage$ki10 !== void 0 ? _outcomeAndMessage$ki10 : []; const connectorName = (_outcomeAndMessage$ki12 = outcomeAndMessage === null || outcomeAndMessage === void 0 ? void 0 : (_outcomeAndMessage$ki13 = outcomeAndMessage.kibana) === null || _outcomeAndMessage$ki13 === void 0 ? void 0 : (_outcomeAndMessage$ki14 = _outcomeAndMessage$ki13.action) === null || _outcomeAndMessage$ki14 === void 0 ? void 0 : _outcomeAndMessage$ki14.name) !== null && _outcomeAndMessage$ki12 !== void 0 ? _outcomeAndMessage$ki12 : ''; const connectorId = (_outcomeAndMessage$ki15 = outcomeAndMessage === null || outcomeAndMessage === void 0 ? void 0 : (_outcomeAndMessage$ki16 = outcomeAndMessage.kibana) === null || _outcomeAndMessage$ki16 === void 0 ? void 0 : (_outcomeAndMessage$ki17 = _outcomeAndMessage$ki16.action) === null || _outcomeAndMessage$ki17 === void 0 ? void 0 : _outcomeAndMessage$ki17.id) !== null && _outcomeAndMessage$ki15 !== void 0 ? _outcomeAndMessage$ki15 : ''; const timedOut = ((_bucket$timeoutMessag = bucket === null || bucket === void 0 ? void 0 : (_bucket$timeoutMessag2 = bucket.timeoutMessage) === null || _bucket$timeoutMessag2 === void 0 ? void 0 : _bucket$timeoutMessag2.doc_count) !== null && _bucket$timeoutMessag !== void 0 ? _bucket$timeoutMessag : 0) > 0; return { id: (_bucket$key = bucket === null || bucket === void 0 ? void 0 : bucket.key) !== null && _bucket$key !== void 0 ? _bucket$key : '', timestamp: (_bucket$actionExecuti10 = bucket === null || bucket === void 0 ? void 0 : (_bucket$actionExecuti11 = bucket.actionExecution) === null || _bucket$actionExecuti11 === void 0 ? void 0 : _bucket$actionExecuti11.executeStartTime.value_as_string) !== null && _bucket$actionExecuti10 !== void 0 ? _bucket$actionExecuti10 : '', duration_ms: durationUs / Millis2Nanos, status, message, version, source, schedule_delay_ms: scheduleDelayUs / Millis2Nanos, space_ids: spaceIds, connector_name: connectorName, connector_id: connectorId, timed_out: timedOut }; } function formatExecutionKPIAggBuckets(buckets) { const objToReturn = { success: 0, unknown: 0, failure: 0, warning: 0 }; buckets.forEach(bucket => { var _bucket$actionExecuti12, _bucket$actionExecuti13, _bucket$actionExecuti14, _bucket$actionExecuti15, _bucket$actionExecuti16; const actionExecutionOutcomes = (_bucket$actionExecuti12 = bucket === null || bucket === void 0 ? void 0 : (_bucket$actionExecuti13 = bucket.actionExecution) === null || _bucket$actionExecuti13 === void 0 ? void 0 : (_bucket$actionExecuti14 = _bucket$actionExecuti13.actionExecutionOutcomes) === null || _bucket$actionExecuti14 === void 0 ? void 0 : _bucket$actionExecuti14.buckets) !== null && _bucket$actionExecuti12 !== void 0 ? _bucket$actionExecuti12 : []; const actionExecutionCount = (_bucket$actionExecuti15 = bucket === null || bucket === void 0 ? void 0 : (_bucket$actionExecuti16 = bucket.actionExecution) === null || _bucket$actionExecuti16 === void 0 ? void 0 : _bucket$actionExecuti16.doc_count) !== null && _bucket$actionExecuti15 !== void 0 ? _bucket$actionExecuti15 : 0; const outcomes = { successActionExecution: 0, failureActionExecution: 0, warningActionExecution: 0 }; actionExecutionOutcomes.reduce((acc, subBucket) => { const key = subBucket.key; if (key === 'success') { var _subBucket$doc_count; acc.successActionExecution = (_subBucket$doc_count = subBucket.doc_count) !== null && _subBucket$doc_count !== void 0 ? _subBucket$doc_count : 0; } else if (key === 'failure') { var _subBucket$doc_count2; acc.failureActionExecution = (_subBucket$doc_count2 = subBucket.doc_count) !== null && _subBucket$doc_count2 !== void 0 ? _subBucket$doc_count2 : 0; } else if (key === 'warning') { var _subBucket$doc_count3; acc.warningActionExecution = (_subBucket$doc_count3 = subBucket.doc_count) !== null && _subBucket$doc_count3 !== void 0 ? _subBucket$doc_count3 : 0; } return acc; }, outcomes); objToReturn.success += outcomes.successActionExecution; objToReturn.unknown += actionExecutionCount - (outcomes.successActionExecution + outcomes.failureActionExecution + outcomes.warningActionExecution); objToReturn.failure += outcomes.failureActionExecution; objToReturn.warning += outcomes.warningActionExecution; }); return objToReturn; } function formatExecutionKPIResult(results) { const { aggregations } = results; if (!aggregations || !aggregations.executionKpiAgg) { return _common.EMPTY_EXECUTION_KPI_RESULT; } const aggs = aggregations.executionKpiAgg; const buckets = aggs.executionUuid.buckets; return formatExecutionKPIAggBuckets(buckets); } function formatExecutionLogResult(results) { const { aggregations } = results; if (!aggregations || !aggregations.executionLogAgg) { return EMPTY_EXECUTION_LOG_RESULT; } const aggs = aggregations.executionLogAgg; const total = aggs.executionUuidCardinality.executionUuidCardinality.value; const buckets = aggs.executionUuid.buckets; return { total, data: buckets.map(bucket => formatExecutionLogAggBucket(bucket)) }; } function formatSortForBucketSort(sort) { return sort.map(s => Object.keys(s).reduce((acc, curr) => { acc[ExecutionLogSortFields[curr]] = (0, _lodash.get)(s, curr); return acc; }, {})); } function formatSortForTermSort(sort) { return sort.map(s => Object.keys(s).reduce((acc, curr) => { acc[ExecutionLogSortFields[curr]] = (0, _lodash.get)(s, `${curr}.order`); return acc; }, {})); }