"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ExpandedRow = void 0; exports.useListItemsFormatter = useListItemsFormatter; var _react = _interopRequireWildcard(require("react")); var _lodash = require("lodash"); var _eui = require("@elastic/eui"); var _i18nReact = require("@kbn/i18n-react"); var _common = require("@kbn/field-formats-plugin/common"); var _mlIsPopulatedObject = require("@kbn/ml-is-populated-object"); var _mlIsDefined = require("@kbn/ml-is-defined"); var _mlTrainedModelsUtils = require("@kbn/ml-trained-models-utils"); var _job_map = require("../data_frame_analytics/pages/job_map"); var _pipelines = require("./pipelines"); var _allocated_models = require("../memory_usage/nodes_overview/allocated_models"); var _use_field_formatter = require("../contexts/kibana/use_field_formatter"); 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 useBadgeFormatter = () => { const xs = (0, _eui.useEuiPaddingSize)('xs'); function badgeFormatter(items) { if (items.length === 0) return; return /*#__PURE__*/_react.default.createElement("div", null, items.map(item => /*#__PURE__*/_react.default.createElement("span", { css: { marginRight: xs }, key: item }, /*#__PURE__*/_react.default.createElement(_eui.EuiBadge, { color: "hollow", css: { marginRight: xs } }, item)))); } return { badgeFormatter }; }; function useListItemsFormatter() { const bytesFormatter = (0, _use_field_formatter.useFieldFormatter)(_common.FIELD_FORMAT_IDS.BYTES); const dateFormatter = (0, _use_field_formatter.useFieldFormatter)(_common.FIELD_FORMAT_IDS.DATE); const { badgeFormatter } = useBadgeFormatter(); const formatterDictionary = (0, _react.useMemo)(() => ({ tags: badgeFormatter, roles: badgeFormatter, create_time: dateFormatter, timestamp: dateFormatter, model_size_bytes: bytesFormatter, required_native_memory_bytes: bytesFormatter }), // eslint-disable-next-line react-hooks/exhaustive-deps []); return (0, _react.useCallback)(items => { return Object.entries(items).filter(([, value]) => (0, _mlIsDefined.isDefined)(value)).map(([title, value]) => { if (title in formatterDictionary) { return { title, description: formatterDictionary[title](value) }; } return { title, description: typeof value === 'object' ? /*#__PURE__*/_react.default.createElement(_eui.EuiCodeBlock, { language: "json", fontSize: "s", paddingSize: "s", overflowHeight: 300, isCopyable: false }, JSON.stringify(value, null, 2)) : value.toString() }; }); }, [formatterDictionary]); } const ExpandedRow = ({ item }) => { const formatToListItems = useListItemsFormatter(); const { inference_config: inferenceConfig, stats, metadata, tags, version, // eslint-disable-next-line @typescript-eslint/naming-convention estimated_operations, // eslint-disable-next-line @typescript-eslint/naming-convention estimated_heap_memory_usage_bytes, // eslint-disable-next-line @typescript-eslint/naming-convention default_field_map, // eslint-disable-next-line @typescript-eslint/naming-convention license_level, pipelines, description } = item; const inferenceStats = (0, _react.useMemo)(() => { if (!(0, _mlIsPopulatedObject.isPopulatedObject)(stats.inference_stats) || item.model_type === _mlTrainedModelsUtils.TRAINED_MODEL_TYPE.PYTORCH) return; return stats.inference_stats; }, [stats.inference_stats, item.model_type]); const { analytics_config: analyticsConfig, ...restMetaData } = metadata !== null && metadata !== void 0 ? metadata : {}; const details = (0, _react.useMemo)(() => { return { description, tags, version, estimated_operations, estimated_heap_memory_usage_bytes, default_field_map, license_level }; }, [default_field_map, description, estimated_heap_memory_usage_bytes, estimated_operations, license_level, tags, version]); const deploymentStatItems = (0, _react.useMemo)(() => { const deploymentStats = stats.deployment_stats; const modelSizeStats = stats.model_size_stats; if (!deploymentStats || !modelSizeStats) return []; const items = deploymentStats.flatMap(perDeploymentStat => { return perDeploymentStat.nodes.map(n => { const nodeName = Object.values(n.node)[0].name; return { key: `${perDeploymentStat.deployment_id}_${nodeName}`, ...perDeploymentStat, ...modelSizeStats, node: { ...(0, _lodash.pick)(n, ['average_inference_time_ms', 'inference_count', 'routing_state', 'last_access', 'number_of_pending_requests', 'start_time', 'throughput_last_minute', 'number_of_allocations', 'threads_per_allocation', 'error_count']), name: nodeName } }; }); }); return items; }, [stats]); const tabs = (0, _react.useMemo)(() => { return [{ id: 'details', 'data-test-subj': 'mlTrainedModelDetails', name: /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.ml.trainedModels.modelsList.expandedRow.detailsTabLabel", defaultMessage: "Details" }), content: /*#__PURE__*/_react.default.createElement("div", { "data-test-subj": 'mlTrainedModelDetailsContent' }, /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: 's' }), /*#__PURE__*/_react.default.createElement(_eui.EuiFlexGrid, { columns: 2, gutterSize: 'm' }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, null, /*#__PURE__*/_react.default.createElement(_eui.EuiPanel, null, /*#__PURE__*/_react.default.createElement(_eui.EuiTitle, { size: 'xs' }, /*#__PURE__*/_react.default.createElement("h5", null, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.ml.trainedModels.modelsList.expandedRow.detailsTitle", defaultMessage: "Details" }))), /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: 'm' }), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionList, { compressed: true, type: "column", listItems: formatToListItems(details) }))), (0, _mlIsPopulatedObject.isPopulatedObject)(restMetaData) ? /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, null, /*#__PURE__*/_react.default.createElement(_eui.EuiPanel, null, /*#__PURE__*/_react.default.createElement(_eui.EuiTitle, { size: 'xs' }, /*#__PURE__*/_react.default.createElement("h5", null, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.ml.trainedModels.modelsList.expandedRow.metadataTitle", defaultMessage: "Metadata" }))), /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: 'm' }), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionList, { compressed: true, type: "column", listItems: formatToListItems(restMetaData) }))) : null)) }, ...(inferenceConfig ? [{ id: 'config', 'data-test-subj': 'mlTrainedModelInferenceConfig', name: /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.ml.trainedModels.modelsList.expandedRow.configTabLabel", defaultMessage: "Config" }), content: /*#__PURE__*/_react.default.createElement("div", { "data-test-subj": 'mlTrainedModelInferenceConfigContent' }, /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: 's' }), /*#__PURE__*/_react.default.createElement(_eui.EuiFlexGrid, { columns: 2, gutterSize: 'm' }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, null, /*#__PURE__*/_react.default.createElement(_eui.EuiPanel, null, /*#__PURE__*/_react.default.createElement(_eui.EuiTitle, { size: 'xs' }, /*#__PURE__*/_react.default.createElement("h5", null, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.ml.trainedModels.modelsList.expandedRow.inferenceConfigTitle", defaultMessage: "Inference configuration" }))), /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: 'm' }), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionList, { compressed: true, type: "column", listItems: formatToListItems(inferenceConfig[Object.keys(inferenceConfig)[0]]) }))), analyticsConfig && /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, null, /*#__PURE__*/_react.default.createElement(_eui.EuiPanel, null, /*#__PURE__*/_react.default.createElement(_eui.EuiTitle, { size: 'xs' }, /*#__PURE__*/_react.default.createElement("h5", null, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.ml.trainedModels.modelsList.expandedRow.analyticsConfigTitle", defaultMessage: "Analytics configuration" }))), /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: 'm' }), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionList, { compressed: true, type: "column", listItems: formatToListItems(analyticsConfig) }))))) }] : []), ...((0, _mlIsPopulatedObject.isPopulatedObject)((0, _lodash.omit)(stats, ['pipeline_count', 'ingest'])) ? [{ id: 'stats', 'data-test-subj': 'mlTrainedModelStats', name: /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.ml.trainedModels.modelsList.expandedRow.statsTabLabel", defaultMessage: "Stats" }), content: /*#__PURE__*/_react.default.createElement("div", { "data-test-subj": 'mlTrainedModelStatsContent' }, /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: 's' }), !!(deploymentStatItems !== null && deploymentStatItems !== void 0 && deploymentStatItems.length) ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_eui.EuiPanel, null, /*#__PURE__*/_react.default.createElement(_eui.EuiTitle, { size: 'xs' }, /*#__PURE__*/_react.default.createElement("h5", null, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.ml.trainedModels.modelsList.expandedRow.deploymentStatsTitle", defaultMessage: "Deployment stats" }))), /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: 'm' }), /*#__PURE__*/_react.default.createElement(_allocated_models.AllocatedModels, { models: deploymentStatItems, hideColumns: ['model_id'] })), /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: 's' })) : null, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexGrid, { columns: 2, gutterSize: 'm' }, inferenceStats ? /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, null, /*#__PURE__*/_react.default.createElement(_eui.EuiPanel, null, /*#__PURE__*/_react.default.createElement(_eui.EuiTitle, { size: 'xs' }, /*#__PURE__*/_react.default.createElement("h5", null, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.ml.trainedModels.modelsList.expandedRow.inferenceStatsTitle", defaultMessage: "Inference stats" }))), /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: 'm' }), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionList, { compressed: true, type: "column", listItems: formatToListItems(inferenceStats) }))) : null, (0, _mlIsPopulatedObject.isPopulatedObject)(stats.model_size_stats) && !(0, _mlIsPopulatedObject.isPopulatedObject)(inferenceStats) ? /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, null, /*#__PURE__*/_react.default.createElement(_eui.EuiPanel, null, /*#__PURE__*/_react.default.createElement(_eui.EuiTitle, { size: 'xs' }, /*#__PURE__*/_react.default.createElement("h5", null, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.ml.trainedModels.modelsList.expandedRow.modelSizeStatsTitle", defaultMessage: "Model size stats" }))), /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: 'm' }), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionList, { compressed: true, type: "column", listItems: formatToListItems(stats.model_size_stats) }))) : null)) }] : []), ...((0, _mlIsPopulatedObject.isPopulatedObject)(pipelines) && Object.keys(pipelines).length > 0 || stats.ingest ? [{ id: 'pipelines', 'data-test-subj': 'mlTrainedModelPipelines', name: /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.ml.trainedModels.modelsList.expandedRow.pipelinesTabLabel", defaultMessage: "Pipelines" }), (0, _mlIsPopulatedObject.isPopulatedObject)(pipelines) ? /*#__PURE__*/_react.default.createElement(_eui.EuiNotificationBadge, null, Object.keys(pipelines).length) : null), content: /*#__PURE__*/_react.default.createElement("div", { "data-test-subj": 'mlTrainedModelPipelinesContent' }, /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: 's' }), /*#__PURE__*/_react.default.createElement(_pipelines.ModelPipelines, { pipelines: pipelines, ingestStats: stats.ingest })) }] : []), { id: 'models_map', 'data-test-subj': 'mlTrainedModelsMap', name: /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.ml.trainedModels.modelsList.expandedRow.modelsMapLabel", defaultMessage: "Models map" }), content: /*#__PURE__*/_react.default.createElement("div", { "data-test-subj": 'mlTrainedModelDetailsContent' }, /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: 's' }), /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { css: { height: 300 } }, /*#__PURE__*/_react.default.createElement(_job_map.JobMap, { analyticsId: undefined, modelId: item.model_id, forceRefresh: false, defaultHeight: 200 }))) }]; }, [analyticsConfig, deploymentStatItems, details, formatToListItems, inferenceConfig, inferenceStats, pipelines, restMetaData, stats, item.model_id]); const initialSelectedTab = item.state === 'started' ? tabs.find(t => t.id === 'stats') : tabs[0]; return /*#__PURE__*/_react.default.createElement(_eui.EuiTabbedContent, { size: "s", css: { width: '100%' }, tabs: tabs, initialSelectedTab: initialSelectedTab, autoFocus: "selected", "data-test-subj": 'mlTrainedModelRowDetails' }); }; exports.ExpandedRow = ExpandedRow;