"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.getTopDependencyOperations = getTopDependencyOperations;
var _server = require("@kbn/observability-plugin/server");
var _is_finite_number = require("@kbn/observability-plugin/common/utils/is_finite_number");
var _apm = require("../../../common/es_fields/apm");
var _event_outcome = require("../../../common/event_outcome");
var _environment_query = require("../../../common/utils/environment_query");
var _get_offset_in_ms = require("../../../common/utils/get_offset_in_ms");
var _calculate_throughput = require("../../lib/helpers/calculate_throughput");
var _get_bucket_size_for_aggregated_transactions = require("../../lib/helpers/get_bucket_size_for_aggregated_transactions");
var _get_is_using_service_destination_metrics = require("../../lib/helpers/spans/get_is_using_service_destination_metrics");
var _calculate_impact_builder = require("../traces/calculate_impact_builder");
/*
 * 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 MAX_NUM_OPERATIONS = 500;
async function getTopDependencyOperations({
  apmEventClient,
  dependencyName,
  start,
  end,
  offset,
  environment,
  kuery,
  searchServiceDestinationMetrics
}) {
  var _response$aggregation, _response$aggregation2, _response$aggregation3, _response$aggregation4;
  const {
    startWithOffset,
    endWithOffset,
    offsetInMs
  } = (0, _get_offset_in_ms.getOffsetInMs)({
    start,
    end,
    offset
  });
  const {
    intervalString
  } = (0, _get_bucket_size_for_aggregated_transactions.getBucketSizeForAggregatedTransactions)({
    start: startWithOffset,
    end: endWithOffset,
    searchAggregatedServiceMetrics: searchServiceDestinationMetrics
  });
  const field = (0, _get_is_using_service_destination_metrics.getLatencyFieldForServiceDestinationStatistics)(searchServiceDestinationMetrics);
  const aggs = {
    latency: {
      ...(searchServiceDestinationMetrics ? {
        sum: {
          field: _apm.SPAN_DESTINATION_SERVICE_RESPONSE_TIME_SUM
        }
      } : {
        avg: {
          field
        }
      })
    },
    count: {
      sum: {
        field: _apm.SPAN_DESTINATION_SERVICE_RESPONSE_TIME_COUNT
      }
    },
    successful: {
      filter: {
        term: {
          [_apm.EVENT_OUTCOME]: _event_outcome.EventOutcome.success
        }
      }
    },
    failure: {
      filter: {
        term: {
          [_apm.EVENT_OUTCOME]: _event_outcome.EventOutcome.failure
        }
      }
    }
  };
  const response = await apmEventClient.search('get_top_dependency_operations', {
    apm: {
      events: [(0, _get_is_using_service_destination_metrics.getProcessorEventForServiceDestinationStatistics)(searchServiceDestinationMetrics)]
    },
    body: {
      track_total_hits: false,
      size: 0,
      query: {
        bool: {
          filter: [...(0, _server.rangeQuery)(startWithOffset, endWithOffset), ...(0, _environment_query.environmentQuery)(environment), ...(0, _server.kqlQuery)(kuery), ...(0, _server.termQuery)(_apm.SPAN_DESTINATION_SERVICE_RESOURCE, dependencyName), ...(0, _get_is_using_service_destination_metrics.getDocumentTypeFilterForServiceDestinationStatistics)(searchServiceDestinationMetrics)]
        }
      },
      aggs: {
        operationName: {
          terms: {
            field: _apm.SPAN_NAME,
            size: MAX_NUM_OPERATIONS
          },
          aggs: {
            over_time: {
              date_histogram: {
                field: '@timestamp',
                fixed_interval: intervalString,
                min_doc_count: 0,
                extended_bounds: {
                  min: startWithOffset,
                  max: endWithOffset
                }
              },
              aggs
            },
            ...aggs,
            total_time: {
              sum: {
                field
              }
            }
          }
        }
      }
    }
  });
  const getImpact = (0, _calculate_impact_builder.calculateImpactBuilder)((_response$aggregation = (_response$aggregation2 = response.aggregations) === null || _response$aggregation2 === void 0 ? void 0 : _response$aggregation2.operationName.buckets.map(bucket => bucket.total_time.value)) !== null && _response$aggregation !== void 0 ? _response$aggregation : []);
  return (_response$aggregation3 = (_response$aggregation4 = response.aggregations) === null || _response$aggregation4 === void 0 ? void 0 : _response$aggregation4.operationName.buckets.map(bucket => {
    var _bucket$total_time$va;
    const timeseries = {
      latency: [],
      throughput: [],
      failureRate: []
    };
    bucket.over_time.buckets.forEach(dateBucket => {
      const x = dateBucket.key + offsetInMs;
      const latencyValue = (0, _is_finite_number.isFiniteNumber)(dateBucket.latency.value) ? dateBucket.latency.value : 0;
      const count = (0, _is_finite_number.isFiniteNumber)(dateBucket.count.value) ? dateBucket.count.value : 1;
      timeseries.throughput.push({
        x,
        y: (0, _calculate_throughput.calculateThroughputWithRange)({
          start: startWithOffset,
          end: endWithOffset,
          value: searchServiceDestinationMetrics ? dateBucket.count.value || 0 : dateBucket.doc_count
        })
      });
      timeseries.latency.push({
        x,
        y: searchServiceDestinationMetrics ? latencyValue / count : dateBucket.latency.value
      });
      timeseries.failureRate.push({
        x,
        y: dateBucket.failure.doc_count > 0 || dateBucket.successful.doc_count > 0 ? dateBucket.failure.doc_count / (dateBucket.successful.doc_count + dateBucket.failure.doc_count) : null
      });
    });
    const latencyValue = (0, _is_finite_number.isFiniteNumber)(bucket.latency.value) ? bucket.latency.value : 0;
    const count = (0, _is_finite_number.isFiniteNumber)(bucket.count.value) ? bucket.count.value : 1;
    return {
      spanName: bucket.key,
      latency: searchServiceDestinationMetrics ? latencyValue / count : bucket.latency.value,
      throughput: (0, _calculate_throughput.calculateThroughputWithRange)({
        start: startWithOffset,
        end: endWithOffset,
        value: searchServiceDestinationMetrics ? bucket.count.value || 0 : bucket.doc_count
      }),
      failureRate: bucket.failure.doc_count > 0 || bucket.successful.doc_count > 0 ? bucket.failure.doc_count / (bucket.successful.doc_count + bucket.failure.doc_count) : null,
      impact: getImpact((_bucket$total_time$va = bucket.total_time.value) !== null && _bucket$total_time$va !== void 0 ? _bucket$total_time$va : 0),
      timeseries
    };
  })) !== null && _response$aggregation3 !== void 0 ? _response$aggregation3 : [];
}