"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.queryMonitorStatus = queryMonitorStatus; var _pMap = _interopRequireDefault(require("p-map")); var _times = _interopRequireDefault(require("lodash/times")); var _lodash = require("lodash"); var _client_defaults = require("../../common/constants/client_defaults"); var _lib = require("../lib"); /* * 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_ES_BUCKET_SIZE = 10000; const fields = ['@timestamp', 'summary', 'monitor', 'observer', 'config_id', 'error', 'agent', 'url', 'state']; async function queryMonitorStatus(esClient, listOfLocations, range, monitorQueryIds, monitorLocationsMap, monitorQueryIdToConfigIdMap) { const idSize = Math.trunc(DEFAULT_MAX_ES_BUCKET_SIZE / listOfLocations.length || 1); const pageCount = Math.ceil(monitorQueryIds.length / idSize); let up = 0; let down = 0; const upConfigs = {}; const downConfigs = {}; const monitorsWithoutData = new Map(Object.entries((0, _lodash.cloneDeep)(monitorLocationsMap))); const pendingConfigs = {}; await (0, _pMap.default)((0, _times.default)(pageCount), async i => { var _result$aggregations; const idsToQuery = monitorQueryIds.slice(i * idSize, i * idSize + idSize); const params = (0, _lib.createEsParams)({ body: { size: 0, query: { bool: { filter: [_client_defaults.SUMMARY_FILTER, { range: { '@timestamp': { gte: range.from, lte: range.to } } }, { terms: { 'monitor.id': idsToQuery } }] } }, aggs: { id: { terms: { field: 'monitor.id', size: idSize }, aggs: { location: { terms: { field: 'observer.geo.name', size: listOfLocations.length || 100 }, aggs: { status: { top_hits: { size: 1, sort: [{ '@timestamp': { order: 'desc' } }], _source: { includes: fields } } } } } } } } } }); if (listOfLocations.length > 0) { params.body.query.bool.filter.push({ terms: { 'observer.geo.name': listOfLocations } }); } const { body: result } = await esClient.search(params, 'getCurrentStatusOverview' + i); (_result$aggregations = result.aggregations) === null || _result$aggregations === void 0 ? void 0 : _result$aggregations.id.buckets.forEach(({ location, key: queryId }) => { const locationSummaries = location.buckets.map(({ status, key: locationName }) => { const ping = status.hits.hits[0]._source; return { location: locationName, ping }; }); // discard any locations that are not in the monitorLocationsMap for the given monitor as well as those which are // in monitorLocationsMap but not in listOfLocations const monLocations = monitorLocationsMap === null || monitorLocationsMap === void 0 ? void 0 : monitorLocationsMap[queryId]; const monQueriedLocations = (0, _lodash.intersection)(monLocations, listOfLocations); monQueriedLocations === null || monQueriedLocations === void 0 ? void 0 : monQueriedLocations.forEach(monLocation => { const locationSummary = locationSummaries.find(summary => summary.location === monLocation); if (locationSummary) { var _ping$summary$down, _ping$summary, _ping$summary$up, _ping$summary2, _monitorsWithoutData$; const { ping } = locationSummary; const downCount = (_ping$summary$down = (_ping$summary = ping.summary) === null || _ping$summary === void 0 ? void 0 : _ping$summary.down) !== null && _ping$summary$down !== void 0 ? _ping$summary$down : 0; const upCount = (_ping$summary$up = (_ping$summary2 = ping.summary) === null || _ping$summary2 === void 0 ? void 0 : _ping$summary2.up) !== null && _ping$summary$up !== void 0 ? _ping$summary$up : 0; const configId = ping.config_id; const monitorQueryId = ping.monitor.id; const meta = { ping, configId, monitorQueryId, location: monLocation, timestamp: ping['@timestamp'] }; if (downCount > 0) { down += 1; downConfigs[`${configId}-${monLocation}`] = { ...meta, status: 'down' }; } else if (upCount > 0) { up += 1; upConfigs[`${configId}-${monLocation}`] = { ...meta, status: 'up' }; } const monitorsMissingData = monitorsWithoutData.get(monitorQueryId) || []; monitorsWithoutData.set(monitorQueryId, monitorsMissingData === null || monitorsMissingData === void 0 ? void 0 : monitorsMissingData.filter(loc => loc !== monLocation)); if (!((_monitorsWithoutData$ = monitorsWithoutData.get(monitorQueryId)) !== null && _monitorsWithoutData$ !== void 0 && _monitorsWithoutData$.length)) { monitorsWithoutData.delete(monitorQueryId); } } }); }); }, { concurrency: 5 }); // identify the remaining monitors without data, to determine pending monitors for (const [queryId, locs] of monitorsWithoutData) { locs.forEach(loc => { pendingConfigs[`${monitorQueryIdToConfigIdMap[queryId]}-${loc}`] = { configId: `${monitorQueryIdToConfigIdMap[queryId]}`, monitorQueryId: queryId, status: 'unknown', location: loc }; }); } return { up, down, pending: Object.values(pendingConfigs).length, upConfigs, downConfigs, pendingConfigs, enabledMonitorQueryIds: monitorQueryIds }; }