"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.profilingRouteRepository = void 0;
var _ioTsUtils = require("@kbn/io-ts-utils");
var t = _interopRequireWildcard(require("io-ts"));
var _common = require("@kbn/observability-plugin/common");
var _apm = require("../../../common/es_fields/apm");
var _to_kuery_filter_format = require("../../../common/utils/to_kuery_filter_format");
var _get_apm_event_client = require("../../lib/helpers/get_apm_event_client");
var _create_apm_server_route = require("../apm_routes/create_apm_server_route");
var _default_api_types = require("../default_api_types");
var _get_service_host_names = require("./get_service_host_names");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
/*
 * 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 profilingFlamegraphRoute = (0, _create_apm_server_route.createApmServerRoute)({
  endpoint: 'GET /internal/apm/services/{serviceName}/profiling/flamegraph',
  params: t.type({
    path: t.type({
      serviceName: t.string
    }),
    query: t.intersection([_default_api_types.rangeRt, _default_api_types.environmentRt, _default_api_types.serviceTransactionDataSourceRt])
  }),
  options: {
    tags: ['access:apm']
  },
  handler: async resources => {
    var _plugins$profilingDat;
    const {
      context,
      plugins,
      params
    } = resources;
    const useLegacyFlamegraphAPI = await (await context.core).uiSettings.client.get(_common.profilingUseLegacyFlamegraphAPI);
    const [esClient, apmEventClient, profilingDataAccessStart] = await Promise.all([(await context.core).elasticsearch.client, await (0, _get_apm_event_client.getApmEventClient)(resources), await ((_plugins$profilingDat = plugins.profilingDataAccess) === null || _plugins$profilingDat === void 0 ? void 0 : _plugins$profilingDat.start())]);
    if (profilingDataAccessStart) {
      const {
        start,
        end,
        environment,
        documentType,
        rollupInterval
      } = params.query;
      const {
        serviceName
      } = params.path;
      const serviceHostNames = await (0, _get_service_host_names.getServiceHostNames)({
        apmEventClient,
        start,
        end,
        environment,
        serviceName,
        documentType,
        rollupInterval
      });
      if (!serviceHostNames.length) {
        return undefined;
      }
      const flamegraph = await (profilingDataAccessStart === null || profilingDataAccessStart === void 0 ? void 0 : profilingDataAccessStart.services.fetchFlamechartData({
        esClient: esClient.asCurrentUser,
        rangeFromMs: start,
        rangeToMs: end,
        kuery: (0, _to_kuery_filter_format.toKueryFilterFormat)(_apm.HOST_NAME, serviceHostNames),
        useLegacyFlamegraphAPI
      }));
      return {
        flamegraph,
        hostNames: serviceHostNames
      };
    }
    return undefined;
  }
});
const profilingFunctionsRoute = (0, _create_apm_server_route.createApmServerRoute)({
  endpoint: 'GET /internal/apm/services/{serviceName}/profiling/functions',
  params: t.type({
    path: t.type({
      serviceName: t.string
    }),
    query: t.intersection([_default_api_types.rangeRt, _default_api_types.environmentRt, _default_api_types.serviceTransactionDataSourceRt, t.type({
      startIndex: _ioTsUtils.toNumberRt,
      endIndex: _ioTsUtils.toNumberRt
    })])
  }),
  options: {
    tags: ['access:apm']
  },
  handler: async resources => {
    var _plugins$profilingDat2;
    const {
      context,
      plugins,
      params
    } = resources;
    const [esClient, apmEventClient, profilingDataAccessStart] = await Promise.all([(await context.core).elasticsearch.client, await (0, _get_apm_event_client.getApmEventClient)(resources), await ((_plugins$profilingDat2 = plugins.profilingDataAccess) === null || _plugins$profilingDat2 === void 0 ? void 0 : _plugins$profilingDat2.start())]);
    if (profilingDataAccessStart) {
      const {
        start,
        end,
        environment,
        startIndex,
        endIndex,
        documentType,
        rollupInterval
      } = params.query;
      const {
        serviceName
      } = params.path;
      const serviceHostNames = await (0, _get_service_host_names.getServiceHostNames)({
        apmEventClient,
        start,
        end,
        environment,
        serviceName,
        documentType,
        rollupInterval
      });
      if (!serviceHostNames.length) {
        return undefined;
      }
      const functions = await (profilingDataAccessStart === null || profilingDataAccessStart === void 0 ? void 0 : profilingDataAccessStart.services.fetchFunction({
        esClient: esClient.asCurrentUser,
        rangeFromMs: start,
        rangeToMs: end,
        kuery: (0, _to_kuery_filter_format.toKueryFilterFormat)(_apm.HOST_NAME, serviceHostNames),
        startIndex,
        endIndex
      }));
      return {
        functions,
        hostNames: serviceHostNames
      };
    }
    return undefined;
  }
});
const profilingStatusRoute = (0, _create_apm_server_route.createApmServerRoute)({
  endpoint: 'GET /internal/apm/profiling/status',
  options: {
    tags: ['access:apm']
  },
  handler: async resources => {
    var _plugins$profilingDat3;
    const {
      context,
      plugins,
      logger
    } = resources;
    const [esClient, profilingDataAccessStart] = await Promise.all([(await context.core).elasticsearch.client, await ((_plugins$profilingDat3 = plugins.profilingDataAccess) === null || _plugins$profilingDat3 === void 0 ? void 0 : _plugins$profilingDat3.start())]);
    if (profilingDataAccessStart) {
      try {
        var _await$plugins$spaces, _plugins$spaces;
        const response = await (profilingDataAccessStart === null || profilingDataAccessStart === void 0 ? void 0 : profilingDataAccessStart.services.getStatus({
          esClient: esClient.asCurrentUser,
          soClient: (await context.core).savedObjects.client,
          spaceId: (_await$plugins$spaces = await ((_plugins$spaces = plugins.spaces) === null || _plugins$spaces === void 0 ? void 0 : _plugins$spaces.start())) === null || _await$plugins$spaces === void 0 ? void 0 : _await$plugins$spaces.spacesService.getSpaceId(resources.request)
        }));
        return {
          initialized: response.has_setup
        };
      } catch (e) {
        // If any error happens just return as if profiling has not been initialized
        logger.warn('Could not check Universal Profiling status');
      }
    }
    return {
      initialized: false
    };
  }
});
const profilingRouteRepository = {
  ...profilingFlamegraphRoute,
  ...profilingStatusRoute,
  ...profilingFunctionsRoute
};
exports.profilingRouteRepository = profilingRouteRepository;