"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.getServiceMap = getServiceMap;
var _lodash = require("lodash");
var _with_apm_span = require("../../utils/with_apm_span");
var _get_service_anomalies = require("./get_service_anomalies");
var _get_service_map_from_trace_ids = require("./get_service_map_from_trace_ids");
var _get_service_stats = require("./get_service_stats");
var _get_trace_sample_ids = require("./get_trace_sample_ids");
var _transform_service_map_responses = require("./transform_service_map_responses");
/*
 * 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 getConnectionData({
  config,
  apmEventClient,
  serviceName,
  environment,
  start,
  end,
  serviceGroupKuery,
  kuery,
  logger
}) {
  return (0, _with_apm_span.withApmSpan)('get_service_map_connections', async () => {
    logger.debug('Getting trace sample IDs');
    const {
      traceIds
    } = await (0, _get_trace_sample_ids.getTraceSampleIds)({
      config,
      apmEventClient,
      serviceName,
      environment,
      start,
      end,
      serviceGroupKuery,
      kuery
    });
    logger.debug(`Found ${traceIds.length} traces to inspect`);
    const chunks = (0, _lodash.chunk)(traceIds, config.serviceMapMaxTracesPerRequest);
    const init = {
      connections: [],
      discoveredServices: []
    };
    if (!traceIds.length) {
      return init;
    }
    logger.debug(`Executing scripted metric agg (${chunks.length} chunks)`);
    const chunkedResponses = await (0, _with_apm_span.withApmSpan)('get_service_paths_from_all_trace_ids', () => Promise.all(chunks.map(traceIdsChunk => (0, _get_service_map_from_trace_ids.getServiceMapFromTraceIds)({
      apmEventClient,
      traceIds: traceIdsChunk,
      start,
      end,
      terminateAfter: config.serviceMapTerminateAfter,
      logger
    }))));
    logger.debug('Received chunk responses');
    const mergedResponses = chunkedResponses.reduce((prev, current) => {
      return {
        connections: prev.connections.concat(current.connections),
        discoveredServices: prev.discoveredServices.concat(current.discoveredServices)
      };
    });
    logger.debug('Merged responses');
    return mergedResponses;
  });
}
function getServiceMap(options) {
  return (0, _with_apm_span.withApmSpan)('get_service_map', async () => {
    const {
      logger
    } = options;
    const anomaliesPromise = (0, _get_service_anomalies.getServiceAnomalies)(options

    // always catch error to avoid breaking service maps if there is a problem with ML
    ).catch(error => {
      logger.warn(`Unable to retrieve anomalies for service maps.`);
      logger.error(error);
      return _get_service_anomalies.DEFAULT_ANOMALIES;
    });
    const [connectionData, servicesData, anomalies] = await Promise.all([getConnectionData(options), (0, _get_service_stats.getServiceStats)(options), anomaliesPromise]);
    logger.debug('Received and parsed all responses');
    const transformedResponse = (0, _transform_service_map_responses.transformServiceMapResponses)({
      response: {
        ...connectionData,
        services: servicesData,
        anomalies
      }
    });
    logger.debug('Transformed service map response');
    return transformedResponse;
  });
}