"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.ServiceInventory = ServiceInventory; var _eui = require("@elastic/eui"); var _i18n = require("@kbn/i18n"); var _i18nReact = require("@kbn/i18n-react"); var _react = _interopRequireDefault(require("react")); var _uuid = require("uuid"); var _document_type = require("../../../../common/document_type"); var _service_inventory = require("../../../../common/service_inventory"); var _use_anomaly_detection_jobs_context = require("../../../context/anomaly_detection_jobs/use_anomaly_detection_jobs_context"); var _use_apm_params = require("../../../hooks/use_apm_params"); var _use_fetcher = require("../../../hooks/use_fetcher"); var _use_local_storage = require("../../../hooks/use_local_storage"); var _use_preferred_data_source_and_bucket_size = require("../../../hooks/use_preferred_data_source_and_bucket_size"); var _use_progressive_fetcher = require("../../../hooks/use_progressive_fetcher"); var _use_time_range = require("../../../hooks/use_time_range"); var _ml_callout = require("../../shared/ml_callout"); var _search_bar = require("../../shared/search_bar/search_bar"); var _get_comparison_options = require("../../shared/time_comparison/get_comparison_options"); var _service_list = require("./service_list"); var _order_service_items = require("./service_list/order_service_items"); /* * 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 initialData = { requestId: '', items: [], hasHistoricalData: true, hasLegacyData: false }; const INITIAL_PAGE_SIZE = 25; function useServicesMainStatisticsFetcher() { const { query: { rangeFrom, rangeTo, environment, kuery, serviceGroup, page = 0, pageSize = INITIAL_PAGE_SIZE, sortDirection, sortField } } = (0, _use_apm_params.useApmParams)('/services'); const { start, end } = (0, _use_time_range.useTimeRange)({ rangeFrom, rangeTo }); const preferred = (0, _use_preferred_data_source_and_bucket_size.usePreferredDataSourceAndBucketSize)({ start, end, kuery, type: _document_type.ApmDocumentType.ServiceTransactionMetric, numBuckets: 20 }); const mainStatisticsFetch = (0, _use_progressive_fetcher.useProgressiveFetcher)(callApmApi => { if (preferred) { return callApmApi('GET /internal/apm/services', { params: { query: { environment, kuery, start, end, serviceGroup, documentType: preferred.source.documentType, rollupInterval: preferred.source.rollupInterval } } }).then(mainStatisticsData => { return { requestId: (0, _uuid.v4)(), ...mainStatisticsData }; }); } }, // eslint-disable-next-line react-hooks/exhaustive-deps [environment, kuery, start, end, serviceGroup, preferred, // not used, but needed to update the requestId to call the details statistics API when table is options are updated page, pageSize, sortField, sortDirection]); return { mainStatisticsFetch }; } function useServicesDetailedStatisticsFetcher({ mainStatisticsFetch, initialSortField, initialSortDirection, tiebreakerField }) { const { query: { rangeFrom, rangeTo, environment, kuery, offset, comparisonEnabled, page = 0, pageSize = INITIAL_PAGE_SIZE, sortDirection = initialSortDirection, sortField = initialSortField } } = (0, _use_apm_params.useApmParams)('/services'); const { start, end } = (0, _use_time_range.useTimeRange)({ rangeFrom, rangeTo }); const dataSourceOptions = (0, _use_preferred_data_source_and_bucket_size.usePreferredDataSourceAndBucketSize)({ start, end, kuery, type: _document_type.ApmDocumentType.ServiceTransactionMetric, numBuckets: 20 }); const { data: mainStatisticsData = initialData } = mainStatisticsFetch; const currentPageItems = (0, _order_service_items.orderServiceItems)({ items: mainStatisticsData.items, primarySortField: sortField, sortDirection, tiebreakerField }).slice(page * pageSize, (page + 1) * pageSize); const comparisonFetch = (0, _use_progressive_fetcher.useProgressiveFetcher)(callApmApi => { if (start && end && currentPageItems.length && mainStatisticsFetch.status === _use_fetcher.FETCH_STATUS.SUCCESS && dataSourceOptions) { return callApmApi('POST /internal/apm/services/detailed_statistics', { params: { query: { environment, kuery, start, end, offset: comparisonEnabled && (0, _get_comparison_options.isTimeComparison)(offset) ? offset : undefined, documentType: dataSourceOptions.source.documentType, rollupInterval: dataSourceOptions.source.rollupInterval, bucketSizeInSeconds: dataSourceOptions.bucketSizeInSeconds }, body: { serviceNames: JSON.stringify(currentPageItems.map(({ serviceName }) => serviceName) // Service name is sorted to guarantee the same order every time this API is called so the result can be cached. .sort()) } } }); } }, // only fetches detailed statistics when requestId is invalidated by main statistics api call or offset is changed // eslint-disable-next-line react-hooks/exhaustive-deps [mainStatisticsData.requestId, offset, comparisonEnabled], { preservePreviousData: false }); return { comparisonFetch }; } function ServiceInventory() { var _mainStatisticsFetch$, _mainStatisticsFetch$2, _mainStatisticsFetch$3, _mainStatisticsFetch$4, _mainStatisticsFetch$5; const { mainStatisticsFetch } = useServicesMainStatisticsFetcher(); const mainStatisticsItems = (_mainStatisticsFetch$ = (_mainStatisticsFetch$2 = mainStatisticsFetch.data) === null || _mainStatisticsFetch$2 === void 0 ? void 0 : _mainStatisticsFetch$2.items) !== null && _mainStatisticsFetch$ !== void 0 ? _mainStatisticsFetch$ : []; const displayHealthStatus = mainStatisticsItems.some(item => 'healthStatus' in item); const hasKibanaUiLimitRestrictedData = (_mainStatisticsFetch$3 = mainStatisticsFetch.data) === null || _mainStatisticsFetch$3 === void 0 ? void 0 : _mainStatisticsFetch$3.maxServiceCountExceeded; const serviceOverflowCount = (_mainStatisticsFetch$4 = (_mainStatisticsFetch$5 = mainStatisticsFetch.data) === null || _mainStatisticsFetch$5 === void 0 ? void 0 : _mainStatisticsFetch$5.serviceOverflowCount) !== null && _mainStatisticsFetch$4 !== void 0 ? _mainStatisticsFetch$4 : 0; const displayAlerts = mainStatisticsItems.some(item => _service_inventory.ServiceInventoryFieldName.AlertsCount in item); const tiebreakerField = _service_inventory.ServiceInventoryFieldName.Throughput; const initialSortField = displayHealthStatus ? _service_inventory.ServiceInventoryFieldName.HealthStatus : tiebreakerField; const initialSortDirection = 'desc'; const { comparisonFetch } = useServicesDetailedStatisticsFetcher({ mainStatisticsFetch, initialSortField, initialSortDirection, tiebreakerField }); const { anomalyDetectionSetupState } = (0, _use_anomaly_detection_jobs_context.useAnomalyDetectionJobsContext)(); const [userHasDismissedCallout, setUserHasDismissedCallout] = (0, _use_local_storage.useLocalStorage)(`apm.userHasDismissedServiceInventoryMlCallout.${anomalyDetectionSetupState}`, false); const displayMlCallout = !userHasDismissedCallout && (0, _ml_callout.shouldDisplayMlCallout)(anomalyDetectionSetupState); const isLoading = (0, _use_fetcher.isPending)(mainStatisticsFetch.status); const isFailure = mainStatisticsFetch.status === _use_fetcher.FETCH_STATUS.FAILURE; const noItemsMessage = /*#__PURE__*/_react.default.createElement(_eui.EuiEmptyPrompt, { title: /*#__PURE__*/_react.default.createElement("div", null, _i18n.i18n.translate('xpack.apm.servicesTable.notFoundLabel', { defaultMessage: 'No services found' })), titleSize: "s" }); const items = mainStatisticsItems; const mlCallout = /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, null, /*#__PURE__*/_react.default.createElement(_ml_callout.MLCallout, { isOnSettingsPage: false, anomalyDetectionSetupState: anomalyDetectionSetupState, onDismiss: () => setUserHasDismissedCallout(true) })); const kibanaUiServiceLimitCallout = /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, null, /*#__PURE__*/_react.default.createElement(_eui.EuiCallOut, { title: _i18n.i18n.translate('xpack.apm.serviceList.ui.limit.warning.calloutTitle', { defaultMessage: 'Number of services exceed the allowed maximum that are displayed (1,000)' }), color: "warning", iconType: "warning" }, /*#__PURE__*/_react.default.createElement(_eui.EuiText, { size: "s" }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { defaultMessage: "Max. number of services that can be viewed in Kibana has been reached. Try narrowing down results by using the query bar or consider using service groups.", id: "xpack.apm.serviceList.ui.limit.warning.calloutDescription" })))); return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_search_bar.SearchBar, { showTimeComparison: true }), /*#__PURE__*/_react.default.createElement(_eui.EuiFlexGroup, { direction: "column", gutterSize: "m" }, displayMlCallout && mlCallout, hasKibanaUiLimitRestrictedData && kibanaUiServiceLimitCallout, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, null, /*#__PURE__*/_react.default.createElement(_service_list.ServiceList, { isLoading: isLoading, isFailure: isFailure, items: items, comparisonDataLoading: comparisonFetch.status === _use_fetcher.FETCH_STATUS.LOADING, displayHealthStatus: displayHealthStatus, displayAlerts: displayAlerts, initialSortField: initialSortField, initialSortDirection: initialSortDirection, sortFn: (itemsToSort, sortField, sortDirection) => { return (0, _order_service_items.orderServiceItems)({ items: itemsToSort, primarySortField: sortField, sortDirection, tiebreakerField }); }, comparisonData: comparisonFetch === null || comparisonFetch === void 0 ? void 0 : comparisonFetch.data, noItemsMessage: noItemsMessage, initialPageSize: INITIAL_PAGE_SIZE, serviceOverflowCount: serviceOverflowCount })))); }