"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getTraceItems = getTraceItems; var _common = require("@kbn/observability-plugin/common"); var _server = require("@kbn/observability-plugin/server"); var _lodash = require("lodash"); var _apm = require("../../../common/es_fields/apm"); var _get_linked_children = require("../span_links/get_linked_children"); /* * 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. */ async function getTraceItems({ traceId, config, apmEventClient, start, end, maxTraceItemsFromUrlParam, logger }) { const maxTraceItems = maxTraceItemsFromUrlParam !== null && maxTraceItemsFromUrlParam !== void 0 ? maxTraceItemsFromUrlParam : config.ui.maxTraceItems; const excludedLogLevels = ['debug', 'info', 'warning']; const errorResponsePromise = apmEventClient.search('get_errors_docs', { apm: { events: [_common.ProcessorEvent.error] }, body: { track_total_hits: false, size: 1000, _source: [_apm.TIMESTAMP, _apm.TRACE_ID, _apm.TRANSACTION_ID, _apm.PARENT_ID, _apm.SERVICE_NAME, _apm.ERROR_ID, _apm.ERROR_LOG_MESSAGE, _apm.ERROR_EXCEPTION, _apm.ERROR_GROUP_ID], query: { bool: { filter: [{ term: { [_apm.TRACE_ID]: traceId } }, ...(0, _server.rangeQuery)(start, end)], must_not: { terms: { [_apm.ERROR_LOG_LEVEL]: excludedLogLevels } } } } } }); const traceResponsePromise = getTraceDocsPaginated({ apmEventClient, maxTraceItems, traceId, start, end, logger }); const [errorResponse, traceResponse, spanLinksCountById] = await Promise.all([errorResponsePromise, traceResponsePromise, (0, _get_linked_children.getSpanLinksCountById)({ traceId, apmEventClient, start, end })]); const traceDocsTotal = traceResponse.total; const exceedsMax = traceDocsTotal > maxTraceItems; const traceDocs = traceResponse.hits.map(hit => hit._source); const errorDocs = errorResponse.hits.hits.map(hit => hit._source); return { exceedsMax, traceDocs, errorDocs, spanLinksCountById, traceDocsTotal, maxTraceItems }; } const MAX_ITEMS_PER_PAGE = 10000; // 10000 is the max allowed by ES async function getTraceDocsPaginated({ apmEventClient, maxTraceItems, traceId, start, end, hits = [], searchAfter, logger }) { var _last; const response = await getTraceDocsPerPage({ apmEventClient, maxTraceItems, traceId, start, end, searchAfter }); const mergedHits = [...hits, ...response.hits]; logger.debug(`Paginating traces: retrieved: ${response.hits.length}, (total: ${mergedHits.length} of ${response.total}), maxTraceItems: ${maxTraceItems}`); if (mergedHits.length >= maxTraceItems || mergedHits.length >= response.total || mergedHits.length === 0 || response.hits.length < MAX_ITEMS_PER_PAGE) { return { hits: mergedHits, total: response.total }; } return getTraceDocsPaginated({ apmEventClient, maxTraceItems, traceId, start, end, hits: mergedHits, searchAfter: (_last = (0, _lodash.last)(response.hits)) === null || _last === void 0 ? void 0 : _last.sort, logger }); } async function getTraceDocsPerPage({ apmEventClient, maxTraceItems, traceId, start, end, searchAfter }) { const size = Math.min(maxTraceItems, MAX_ITEMS_PER_PAGE); const body = { track_total_hits: true, size, search_after: searchAfter, _source: [_apm.TIMESTAMP, _apm.TRACE_ID, _apm.PARENT_ID, _apm.SERVICE_NAME, _apm.SERVICE_ENVIRONMENT, _apm.AGENT_NAME, _apm.EVENT_OUTCOME, _apm.PROCESSOR_EVENT, _apm.TRANSACTION_DURATION, _apm.TRANSACTION_ID, _apm.TRANSACTION_NAME, _apm.TRANSACTION_TYPE, _apm.TRANSACTION_RESULT, _apm.FAAS_COLDSTART, _apm.SPAN_ID, _apm.SPAN_TYPE, _apm.SPAN_SUBTYPE, _apm.SPAN_ACTION, _apm.SPAN_NAME, _apm.SPAN_DURATION, _apm.SPAN_LINKS, _apm.SPAN_COMPOSITE_COUNT, _apm.SPAN_COMPOSITE_COMPRESSION_STRATEGY, _apm.SPAN_COMPOSITE_SUM, _apm.SPAN_SYNC, _apm.CHILD_ID], query: { bool: { filter: [{ term: { [_apm.TRACE_ID]: traceId } }, ...(0, _server.rangeQuery)(start, end)], should: { exists: { field: _apm.PARENT_ID } } } }, sort: [{ _score: 'asc' }, { _script: { type: 'number', script: { lang: 'painless', source: `if (doc['${_apm.TRANSACTION_DURATION}'].size() > 0) { return doc['${_apm.TRANSACTION_DURATION}'].value } else { return doc['${_apm.SPAN_DURATION}'].value }` }, order: 'desc' } }, { '@timestamp': 'asc' }, { _doc: 'asc' }] }; const res = await apmEventClient.search('get_trace_docs', { apm: { events: [_common.ProcessorEvent.span, _common.ProcessorEvent.transaction] }, body }); return { hits: res.hits.hits, total: res.hits.total.value }; }