"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.ElasticsearchPanel = ElasticsearchPanel; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _react = _interopRequireWildcard(require("react")); var _momentTimezone = _interopRequireDefault(require("moment-timezone")); var _lodash = require("lodash"); var _format_number = require("../../../lib/format_number"); var _helpers = require("./helpers"); var _eui = require("@elastic/eui"); var _i18n = require("@kbn/i18n"); var _i18nReact = require("@kbn/i18n-react"); var _reason = require("../../logs/reason"); var _tooltip = require("../../setup_mode/tooltip"); var _get_safe_for_external_link = require("../../../lib/get_safe_for_external_link"); var _constants = require("../../../../common/constants"); var _badge = require("../../../alerts/badge"); var _should_show_alert_badge = require("../../../alerts/lib/should_show_alert_badge"); var _enums = require("../../../../common/enums"); var _setup_mode = require("../../../lib/setup_mode"); var _setup_mode_context = require("../../setup_mode/setup_mode_context"); 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 calculateShards = shards => { const total = (0, _lodash.get)(shards, 'total', 0); let primaries = (0, _lodash.get)(shards, 'primaries', 'N/A'); let replicas = 'N/A'; // we subtract primaries from total to get replica count, so if we don't know primaries, then // we cannot know replicas (because we'd be showing the wrong number!) if (primaries !== 'N/A') { replicas = (0, _format_number.formatNumber)(total - primaries, 'int_commas'); primaries = (0, _format_number.formatNumber)(primaries, 'int_commas'); } return { primaries, replicas }; }; const formatDateLocal = input => _momentTimezone.default.tz(input, _momentTimezone.default.tz.guess()).format('LL'); function getBadgeColorFromLogLevel(level) { switch (level) { case 'warn': return 'warning'; case 'debug': return 'hollow'; case 'info': return 'default'; case 'error': return 'danger'; } } function renderLogs(props) { if (!props.logs.enabled) { return /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionList, null, /*#__PURE__*/_react.default.createElement(_reason.Reason, { reason: props.logs.reason })); } return /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionList, { type: "column" }, props.logs.types.map((log, index) => /*#__PURE__*/_react.default.createElement(_react.Fragment, { key: index }, /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionListTitle, { className: "eui-textBreakWord" }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.monitoring.cluster.overview.logsPanel.logTypeTitle", defaultMessage: "{type}", values: { type: (0, _lodash.capitalize)(log.type) } })), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionListDescription, null, renderLog(log)))), props.logs.types.length === 0 ? /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.monitoring.cluster.overview.logsPanel.noLogsFound", defaultMessage: "No logs found." }) : null); } const logLevelText = { info: _i18n.i18n.translate('xpack.monitoring.cluster.overview.esPanel.infoLogsTooltipText', { defaultMessage: 'The number of information logs' }), warn: _i18n.i18n.translate('xpack.monitoring.cluster.overview.esPanel.warnLogsTooltipText', { defaultMessage: 'The number of warning logs' }), debug: _i18n.i18n.translate('xpack.monitoring.cluster.overview.esPanel.debugLogsTooltipText', { defaultMessage: 'The number of debug logs' }), error: _i18n.i18n.translate('xpack.monitoring.cluster.overview.esPanel.errorLogsTooltipText', { defaultMessage: 'The number of error logs' }), fatal: _i18n.i18n.translate('xpack.monitoring.cluster.overview.esPanel.fatalLogsTooltipText', { defaultMessage: 'The number of fatal logs' }), unknown: _i18n.i18n.translate('xpack.monitoring.cluster.overview.esPanel.unknownLogsTooltipText', { defaultMessage: 'Unknown' }) }; function renderLog(log) { return /*#__PURE__*/_react.default.createElement(_eui.EuiFlexGroup, { wrap: true, responsive: false, gutterSize: "xs" }, log.levels.map((level, index) => /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: false, key: index }, /*#__PURE__*/_react.default.createElement(_eui.EuiToolTip, { position: "top", content: logLevelText[level.level] || logLevelText.unknown }, /*#__PURE__*/_react.default.createElement(_eui.EuiBadge, { color: getBadgeColorFromLogLevel(level.level) }, (0, _format_number.formatNumber)(level.count, 'int_commas')))))); } const OVERVIEW_PANEL_RULES = [_constants.RULE_CLUSTER_HEALTH, _constants.RULE_LICENSE_EXPIRATION, _constants.RULE_CCR_READ_EXCEPTIONS]; const NODES_PANEL_RULES = [_constants.RULE_CPU_USAGE, _constants.RULE_DISK_USAGE, _constants.RULE_THREAD_POOL_SEARCH_REJECTIONS, _constants.RULE_THREAD_POOL_WRITE_REJECTIONS, _constants.RULE_MEMORY_USAGE, _constants.RULE_NODES_CHANGED, _constants.RULE_ELASTICSEARCH_VERSION_MISMATCH, _constants.RULE_MISSING_MONITORING_DATA]; const INDICES_PANEL_RULES = [_constants.RULE_LARGE_SHARD_SIZE]; function ElasticsearchPanel(props) { const clusterStats = props.cluster_stats || {}; const nodes = clusterStats.nodes; const indices = clusterStats.indices; const setupMode = props.setupMode; const alerts = props.alerts; const setupModeContext = _react.default.useContext(_setup_mode_context.SetupModeContext); const goToElasticsearch = () => (0, _get_safe_for_external_link.getSafeForExternalLink)('#/elasticsearch'); const goToNodes = () => (0, _get_safe_for_external_link.getSafeForExternalLink)('#/elasticsearch/nodes'); const goToIndices = () => (0, _get_safe_for_external_link.getSafeForExternalLink)('#/elasticsearch/indices'); const { primaries, replicas } = calculateShards((0, _lodash.get)(props, 'cluster_stats.indices.shards', {})); const setupModeData = (0, _lodash.get)(setupMode.data, 'elasticsearch'); const setupModeMetricbeatMigrationTooltip = (0, _setup_mode.isSetupModeFeatureEnabled)(_enums.SetupModeFeature.MetricbeatMigration) ? /*#__PURE__*/_react.default.createElement(_tooltip.SetupModeTooltip, { setupModeData: setupModeData, productName: _constants.ELASTICSEARCH_SYSTEM_ID, badgeClickLink: goToNodes() }) : null; const showMlJobs = () => { // if license doesn't support ML, then `ml === null` if (props.ml) { const gotoURL = (0, _get_safe_for_external_link.getSafeForExternalLink)('#/elasticsearch/ml_jobs'); return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionListTitle, { className: "eui-textBreakWord" }, /*#__PURE__*/_react.default.createElement(_helpers.DisabledIfNoDataAndInSetupModeLink, { setupModeEnabled: setupMode.enabled, setupModeData: setupModeData, href: gotoURL }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.monitoring.cluster.overview.esPanel.jobsLabel", defaultMessage: "Machine learning jobs" }))), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionListDescription, { "data-test-subj": "esMlJobs" }, /*#__PURE__*/_react.default.createElement(_helpers.DisabledIfNoDataAndInSetupModeLink, { setupModeEnabled: setupMode.enabled, setupModeData: setupModeData, href: gotoURL }, props.ml.jobs))); } return null; }; const showLicense = () => { if (!props.showLicenseExpiration) { return null; } return /*#__PURE__*/_react.default.createElement(_react.Fragment, null, /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionListTitle, { className: "eui-textBreakWord" }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.monitoring.cluster.overview.esPanel.licenseLabel", defaultMessage: "License" })), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionListDescription, { "data-test-subj": "esLicenseType" }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexGroup, { direction: "column", gutterSize: "xs" }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: false }, /*#__PURE__*/_react.default.createElement(_eui.EuiLink, { href: (0, _get_safe_for_external_link.getSafeForExternalLink)('#/license') }, (0, _lodash.capitalize)(props.license.type))), /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: false }, /*#__PURE__*/_react.default.createElement(_eui.EuiText, { size: "s" }, props.license.expiry_date_in_millis === undefined ? '' : /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.monitoring.cluster.overview.esPanel.expireDateText", defaultMessage: "expires on {expiryDate}", values: { expiryDate: formatDateLocal(props.license.expiry_date_in_millis) } })))))); }; const statusColorMap = { green: 'success', yellow: 'warning', red: 'danger' }; let nodesAlertStatus = null; if ((0, _should_show_alert_badge.shouldShowAlertBadge)(alerts, NODES_PANEL_RULES, setupModeContext)) { const alertsList = NODES_PANEL_RULES.map(alertType => alerts[alertType]); nodesAlertStatus = /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: false }, /*#__PURE__*/_react.default.createElement(_badge.AlertsBadge, { alerts: alertsList })); } let overviewAlertStatus = null; if ((0, _should_show_alert_badge.shouldShowAlertBadge)(alerts, OVERVIEW_PANEL_RULES, setupModeContext)) { const alertsList = OVERVIEW_PANEL_RULES.map(alertType => alerts[alertType]); overviewAlertStatus = /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: false }, /*#__PURE__*/_react.default.createElement(_badge.AlertsBadge, { alerts: alertsList })); } let indicesAlertStatus = null; if ((0, _should_show_alert_badge.shouldShowAlertBadge)(alerts, INDICES_PANEL_RULES, setupModeContext)) { const alertsList = INDICES_PANEL_RULES.map(alertType => alerts[alertType]); indicesAlertStatus = /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: false }, /*#__PURE__*/_react.default.createElement(_badge.AlertsBadge, { alerts: alertsList })); } return /*#__PURE__*/_react.default.createElement(_helpers.ClusterItemContainer, (0, _extends2.default)({}, props, { url: "elasticsearch", title: "Elasticsearch" }), /*#__PURE__*/_react.default.createElement(_eui.EuiFlexGrid, { columns: 4 }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, null, /*#__PURE__*/_react.default.createElement(_eui.EuiPanel, { paddingSize: "m" }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexGroup, { justifyContent: "spaceBetween", gutterSize: "s", alignItems: "center" }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: false }, /*#__PURE__*/_react.default.createElement(_eui.EuiTitle, { size: "s" }, /*#__PURE__*/_react.default.createElement("h3", null, /*#__PURE__*/_react.default.createElement(_helpers.DisabledIfNoDataAndInSetupModeLink, { setupModeEnabled: setupMode.enabled, setupModeData: setupModeData, href: goToElasticsearch(), "aria-label": _i18n.i18n.translate('xpack.monitoring.cluster.overview.esPanel.overviewLinkAriaLabel', { defaultMessage: 'Elasticsearch Overview' }), "data-test-subj": "esOverview" }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.monitoring.cluster.overview.esPanel.overviewLinkLabel", defaultMessage: "Overview" }))))), overviewAlertStatus), /*#__PURE__*/_react.default.createElement(_eui.EuiHorizontalRule, { margin: "m" }), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionList, { type: "column" }, /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionListTitle, { className: "eui-textBreakWord" }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.monitoring.cluster.overview.esPanel.healthLabel", defaultMessage: "Health" })), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionListDescription, null, /*#__PURE__*/_react.default.createElement(_eui.EuiHealth, { color: statusColorMap[clusterStats.status], "data-test-subj": "statusIcon" }, /*#__PURE__*/_react.default.createElement(_helpers.HealthLabel, { status: clusterStats.status, product: 'es' }))), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionListTitle, { className: "eui-textBreakWord" }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.monitoring.cluster.overview.esPanel.versionLabel", defaultMessage: "Version" })), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionListDescription, { "data-test-subj": "esVersion" }, props.version || _i18n.i18n.translate('xpack.monitoring.cluster.overview.esPanel.versionNotAvailableDescription', { defaultMessage: 'N/A' })), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionListTitle, { className: "eui-textBreakWord" }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.monitoring.cluster.overview.esPanel.uptimeLabel", defaultMessage: "Uptime" })), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionListDescription, { "data-test-subj": "esUptime" }, (0, _format_number.formatNumber)((0, _lodash.get)(nodes, 'jvm.max_uptime_in_millis'), 'time_since')), showMlJobs(), showLicense()))), /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, null, /*#__PURE__*/_react.default.createElement(_eui.EuiPanel, { paddingSize: "m" }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexGroup, { justifyContent: "spaceBetween", gutterSize: "s", alignItems: "center" }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: false }, /*#__PURE__*/_react.default.createElement(_eui.EuiTitle, { size: "s" }, /*#__PURE__*/_react.default.createElement("h3", null, /*#__PURE__*/_react.default.createElement(_eui.EuiLink, { "data-test-subj": "esNumberOfNodes", href: goToNodes() }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.monitoring.cluster.overview.esPanel.nodesTotalLinkLabel", defaultMessage: "Nodes: {nodesTotal}", values: { nodesTotal: (0, _format_number.formatNumber)((0, _lodash.get)(nodes, 'count.total'), 'int_commas') } }))))), /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: false }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexGroup, { gutterSize: "s", alignItems: "center" }, setupModeMetricbeatMigrationTooltip, nodesAlertStatus))), /*#__PURE__*/_react.default.createElement(_eui.EuiHorizontalRule, { margin: "m" }), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionList, { type: "column" }, /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionListTitle, { className: "eui-textBreakWord" }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.monitoring.cluster.overview.esPanel.diskAvailableLabel", defaultMessage: "Disk Available" })), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionListDescription, { "data-test-subj": "esDiskAvailable" }, /*#__PURE__*/_react.default.createElement(_helpers.BytesPercentageUsage, { usedBytes: (0, _lodash.get)(nodes, 'fs.available.bytes', (0, _lodash.get)(nodes, 'fs.available_in_bytes')), maxBytes: (0, _lodash.get)(nodes, 'fs.total.bytes', (0, _lodash.get)(nodes, 'fs.total_in_bytes')) })), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionListTitle, { className: "eui-textBreakWord" }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.monitoring.cluster.overview.esPanel.jvmHeapLabel", defaultMessage: "{javaVirtualMachine} Heap", values: { javaVirtualMachine: 'JVM' } })), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionListDescription, { "data-test-subj": "esJvmHeap" }, /*#__PURE__*/_react.default.createElement(_helpers.BytesPercentageUsage, { usedBytes: (0, _lodash.get)(nodes, 'jvm.mem.heap.used.bytes', (0, _lodash.get)(nodes, 'jvm.mem.heap_used_in_bytes')), maxBytes: (0, _lodash.get)(nodes, 'jvm.mem.heap.max.bytes', (0, _lodash.get)(nodes, 'jvm.mem.heap_max_in_bytes')) }))))), /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, null, /*#__PURE__*/_react.default.createElement(_eui.EuiPanel, { paddingSize: "m" }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexGroup, { justifyContent: "spaceBetween", gutterSize: "s", alignItems: "center" }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: false }, /*#__PURE__*/_react.default.createElement(_eui.EuiTitle, { size: "s" }, /*#__PURE__*/_react.default.createElement("h3", null, /*#__PURE__*/_react.default.createElement(_helpers.DisabledIfNoDataAndInSetupModeLink, { setupModeEnabled: setupMode.enabled, setupModeData: setupModeData, href: goToIndices(), "data-test-subj": "esNumberOfIndices", "aria-label": _i18n.i18n.translate('xpack.monitoring.cluster.overview.esPanel.indicesCountLinkAriaLabel', { defaultMessage: 'Elasticsearch Indices: {indicesCount}', values: { indicesCount: (0, _format_number.formatNumber)((0, _lodash.get)(indices, 'count'), 'int_commas') } }) }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.monitoring.cluster.overview.esPanel.indicesCountLinkLabel", defaultMessage: "Indices: {indicesCount}", values: { indicesCount: (0, _format_number.formatNumber)((0, _lodash.get)(indices, 'count'), 'int_commas') } }))))), indicesAlertStatus), /*#__PURE__*/_react.default.createElement(_eui.EuiHorizontalRule, { margin: "m" }), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionList, { type: "column" }, /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionListTitle, { className: "eui-textBreakWord" }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.monitoring.cluster.overview.esPanel.documentsLabel", defaultMessage: "Documents" })), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionListDescription, { "data-test-subj": "esDocumentsCount", className: "eui-textBreakWord" }, (0, _format_number.formatNumber)((0, _lodash.get)(indices, 'docs.total', (0, _lodash.get)(indices, 'docs.count')), 'int_commas')), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionListTitle, { className: "eui-textBreakWord" }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.monitoring.cluster.overview.esPanel.diskUsageLabel", defaultMessage: "Disk Usage" })), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionListDescription, { "data-test-subj": "esDiskUsage" }, (0, _format_number.formatNumber)((0, _lodash.get)(indices, 'store.size.bytes', (0, _lodash.get)(indices, 'store.size_in_bytes')), 'byte')), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionListTitle, { className: "eui-textBreakWord" }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.monitoring.cluster.overview.esPanel.primaryShardsLabel", defaultMessage: "Primary Shards" })), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionListDescription, { "data-test-subj": "esPrimaryShards" }, primaries), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionListTitle, { className: "eui-textBreakWord" }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.monitoring.cluster.overview.esPanel.replicaShardsLabel", defaultMessage: "Replica Shards" })), /*#__PURE__*/_react.default.createElement(_eui.EuiDescriptionListDescription, { "data-test-subj": "esReplicaShards" }, replicas)))), /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, null, /*#__PURE__*/_react.default.createElement(_eui.EuiPanel, { paddingSize: "m" }, /*#__PURE__*/_react.default.createElement(_eui.EuiTitle, { size: "s" }, /*#__PURE__*/_react.default.createElement("h3", null, /*#__PURE__*/_react.default.createElement(_helpers.DisabledIfNoDataAndInSetupModeLink, { setupModeEnabled: setupMode.enabled, setupModeData: setupModeData, href: goToElasticsearch(), "aria-label": _i18n.i18n.translate('xpack.monitoring.cluster.overview.esPanel.logsLinkAriaLabel', { defaultMessage: 'Elasticsearch Logs' }), "data-test-subj": "esLogs" }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.monitoring.cluster.overview.esPanel.logsLinkLabel", defaultMessage: "Logs" })))), /*#__PURE__*/_react.default.createElement(_eui.EuiHorizontalRule, { margin: "m" }), renderLogs(props))))); }