diff --git a/x-pack/plugins/infra/public/common/visualizations/constants.ts b/x-pack/plugins/infra/public/common/visualizations/constants.ts index e66414691b001..66f0cb1e1c422 100644 --- a/x-pack/plugins/infra/public/common/visualizations/constants.ts +++ b/x-pack/plugins/infra/public/common/visualizations/constants.ts @@ -42,3 +42,5 @@ export const visualizationTypes = { lineChart: LineChart, metricChart: MetricChart, }; + +export const HOST_METRICS_DOC_HREF = 'https://ela.st/docs-infra-host-metrics'; diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/chart/chart_loader.tsx b/x-pack/plugins/infra/public/common/visualizations/lens/chart_loader.tsx similarity index 100% rename from x-pack/plugins/infra/public/pages/metrics/hosts/components/chart/chart_loader.tsx rename to x-pack/plugins/infra/public/common/visualizations/lens/chart_loader.tsx diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/kpi_grid_config.ts b/x-pack/plugins/infra/public/common/visualizations/lens/kpi_grid_config.ts new file mode 100644 index 0000000000000..6849bceaa7148 --- /dev/null +++ b/x-pack/plugins/infra/public/common/visualizations/lens/kpi_grid_config.ts @@ -0,0 +1,61 @@ +/* + * 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. + */ + +import { i18n } from '@kbn/i18n'; +import { HostsLensMetricChartFormulas } from '../types'; +import { TOOLTIP } from './translations'; + +export interface KPIChartProps { + title: string; + subtitle?: string; + trendLine?: boolean; + backgroundColor: string; + type: HostsLensMetricChartFormulas; + decimals?: number; + toolTip: string; +} + +export const KPI_CHARTS: Array> = [ + { + type: 'cpuUsage', + trendLine: true, + backgroundColor: '#F1D86F', + title: i18n.translate('xpack.infra.hostsViewPage.metricTrend.cpuUsage.title', { + defaultMessage: 'CPU Usage', + }), + toolTip: TOOLTIP.cpuUsage, + }, + { + type: 'normalizedLoad1m', + trendLine: true, + backgroundColor: '#79AAD9', + title: i18n.translate('xpack.infra.hostsViewPage.metricTrend.normalizedLoad1m.title', { + defaultMessage: 'Normalized Load', + }), + toolTip: TOOLTIP.rx, + }, + { + type: 'memoryUsage', + trendLine: true, + backgroundColor: '#A987D1', + title: i18n.translate('xpack.infra.hostsViewPage.metricTrend.memoryUsage.title', { + defaultMessage: 'Memory Usage', + }), + toolTip: i18n.translate('xpack.infra.hostsViewPage.metricTrend.memoryUsage.tooltip', { + defaultMessage: 'Main memory usage excluding page cache.', + }), + }, + { + type: 'diskSpaceUsage', + trendLine: true, + backgroundColor: '#F5A35C', + title: i18n.translate('xpack.infra.hostsViewPage.metricTrend.diskSpaceUsage.title', { + defaultMessage: 'Disk Space Usage', + }), + toolTip: TOOLTIP.tx, + }, +]; diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/chart/lens_wrapper.tsx b/x-pack/plugins/infra/public/common/visualizations/lens/lens_wrapper.tsx similarity index 93% rename from x-pack/plugins/infra/public/pages/metrics/hosts/components/chart/lens_wrapper.tsx rename to x-pack/plugins/infra/public/common/visualizations/lens/lens_wrapper.tsx index aef672418376e..08948d788fbe3 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/components/chart/lens_wrapper.tsx +++ b/x-pack/plugins/infra/public/common/visualizations/lens/lens_wrapper.tsx @@ -10,10 +10,10 @@ import { Action } from '@kbn/ui-actions-plugin/public'; import { ViewMode } from '@kbn/embeddable-plugin/public'; import { BrushTriggerEvent } from '@kbn/charts-plugin/public'; import { Filter, Query, TimeRange } from '@kbn/es-query'; -import { useKibanaContextForPlugin } from '../../../../../hooks/use_kibana'; -import { useIntersectedOnce } from '../../../../../hooks/use_intersection_once'; -import { LensAttributes } from '../../../../../common/visualizations'; +import { useIntersectedOnce } from '../../../hooks/use_intersection_once'; +import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; import { ChartLoader } from './chart_loader'; +import type { LensAttributes } from '../types'; export interface LensWrapperProps { id: string; diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/translations.ts b/x-pack/plugins/infra/public/common/visualizations/lens/translations.ts new file mode 100644 index 0000000000000..e2820d4d88a99 --- /dev/null +++ b/x-pack/plugins/infra/public/common/visualizations/lens/translations.ts @@ -0,0 +1,45 @@ +/* + * 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. + */ + +import { i18n } from '@kbn/i18n'; + +export const TOOLTIP = { + hostCount: i18n.translate('xpack.infra.hostsViewPage.metrics.tooltip.hostCount', { + defaultMessage: 'Number of hosts returned by your search criteria.', + }), + + cpuUsage: i18n.translate('xpack.infra.hostsViewPage.metrics.tooltip.cpuUsage', { + defaultMessage: + 'Percentage of CPU time spent in states other than Idle and IOWait, normalized by the number of CPU cores. This includes both time spent on user space and kernel space.', + }), + diskSpaceUsage: i18n.translate('xpack.infra.hostsViewPage.metrics.tooltip.diskSpaceUsage', { + defaultMessage: 'Percentage of disk space used.', + }), + diskLatency: i18n.translate('xpack.infra.hostsViewPage.metrics.tooltip.diskLatency', { + defaultMessage: 'Time spent to service disk requests.', + }), + memoryFree: i18n.translate('xpack.infra.hostsViewPage.metrics.tooltip.memoryFree', { + defaultMessage: 'Total available memory including page cache.', + }), + memoryTotal: i18n.translate('xpack.infra.hostsViewPage.metrics.tooltip.memoryTotal', { + defaultMessage: 'Total memory capacity.', + }), + memoryUsage: i18n.translate('xpack.infra.hostsViewPage.metrics.tooltip.memoryUsage', { + defaultMessage: 'Percentage of main memory usage excluding page cache.', + }), + normalizedLoad1m: i18n.translate('xpack.infra.hostsViewPage.metrics.tooltip.normalizedLoad1m', { + defaultMessage: '1 minute load average normalized by the number of CPU cores. ', + }), + rx: i18n.translate('xpack.infra.hostsViewPage.metrics.tooltip.rx', { + defaultMessage: + 'Number of bytes which have been received per second on the public interfaces of the hosts.', + }), + tx: i18n.translate('xpack.infra.hostsViewPage.metrics.tooltip.tx', { + defaultMessage: + 'Number of bytes which have been sent per second on the public interfaces of the hosts.', + }), +}; diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/metric_explanation/host_metrics_docs_link.tsx b/x-pack/plugins/infra/public/common/visualizations/metric_explanation/host_metrics_docs_link.tsx similarity index 93% rename from x-pack/plugins/infra/public/pages/metrics/hosts/components/metric_explanation/host_metrics_docs_link.tsx rename to x-pack/plugins/infra/public/common/visualizations/metric_explanation/host_metrics_docs_link.tsx index 0a9fa8ea576be..eefb88f061440 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/components/metric_explanation/host_metrics_docs_link.tsx +++ b/x-pack/plugins/infra/public/common/visualizations/metric_explanation/host_metrics_docs_link.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { EuiLink, EuiText } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; -import { HOST_METRICS_DOC_HREF } from '../../constants'; +import { HOST_METRICS_DOC_HREF } from '../constants'; export const HostMetricsDocsLink = () => { return ( diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/metric_explanation/tooltip_content.tsx b/x-pack/plugins/infra/public/common/visualizations/metric_explanation/tooltip_content.tsx similarity index 97% rename from x-pack/plugins/infra/public/pages/metrics/hosts/components/metric_explanation/tooltip_content.tsx rename to x-pack/plugins/infra/public/common/visualizations/metric_explanation/tooltip_content.tsx index 44ac644cbb5ec..19b8cd34cf475 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/components/metric_explanation/tooltip_content.tsx +++ b/x-pack/plugins/infra/public/common/visualizations/metric_explanation/tooltip_content.tsx @@ -9,7 +9,7 @@ import React, { HTMLAttributes } from 'react'; import { EuiText, EuiLink } from '@elastic/eui'; import { css } from '@emotion/react'; import { FormattedMessage } from '@kbn/i18n-react'; -import { HOST_METRICS_DOC_HREF } from '../../constants'; +import { HOST_METRICS_DOC_HREF } from '../constants'; interface Props extends Pick, 'style'> { description: string; diff --git a/x-pack/plugins/infra/public/components/asset_details/__stories__/decorator.tsx b/x-pack/plugins/infra/public/components/asset_details/__stories__/decorator.tsx index d8a1bf5bced73..4a4eaa740230f 100644 --- a/x-pack/plugins/infra/public/components/asset_details/__stories__/decorator.tsx +++ b/x-pack/plugins/infra/public/components/asset_details/__stories__/decorator.tsx @@ -93,6 +93,10 @@ export const DecorateWithKibanaContext: DecoratorFn = (story) => { }, }, }, + lens: { + navigateToPrefilledEditor: () => {}, + stateHelperApi: () => new Promise(() => {}), + }, }; return ( diff --git a/x-pack/plugins/infra/public/components/asset_details/asset_details.stories.tsx b/x-pack/plugins/infra/public/components/asset_details/asset_details.stories.tsx index 8b715dd3bd467..e2156876ed7ae 100644 --- a/x-pack/plugins/infra/public/components/asset_details/asset_details.stories.tsx +++ b/x-pack/plugins/infra/public/components/asset_details/asset_details.stories.tsx @@ -9,6 +9,8 @@ import React, { useState } from 'react'; import { EuiButton } from '@elastic/eui'; import type { Meta, Story } from '@storybook/react/types-6-0'; import { i18n } from '@kbn/i18n'; +import type { DataViewField } from '@kbn/data-views-plugin/public'; +import type { DataView } from '@kbn/data-views-plugin/public'; import { AssetDetails } from './asset_details'; import { decorateWithGlobalStorybookThemeProviders } from '../../test_utils/use_global_storybook_theme'; import { FlyoutTabIds, Tab, type AssetDetailsProps } from './types'; @@ -16,6 +18,13 @@ import { DecorateWithKibanaContext } from './__stories__/decorator'; const links: AssetDetailsProps['links'] = ['alertRule', 'nodeDetails', 'apmServices', 'uptime']; const tabs: Tab[] = [ + { + id: FlyoutTabIds.OVERVIEW, + name: i18n.translate('xpack.infra.nodeDetails.tabs.overview.title', { + defaultMessage: 'Overview', + }), + 'data-test-subj': 'hostsView-flyout-tabs-overview', + }, { id: FlyoutTabIds.METRICS, name: i18n.translate('xpack.infra.nodeDetails.tabs.metrics', { @@ -98,6 +107,16 @@ const stories: Meta = { memoryFree: 34359738368, }, overrides: { + overview: { + dataView: { + id: 'default', + getFieldByName: () => 'hostname' as unknown as DataViewField, + } as unknown as DataView, + dateRange: { + from: '168363046800', + to: '168363046900', + }, + }, metadata: { showActionsColumn: true, }, diff --git a/x-pack/plugins/infra/public/components/asset_details/asset_details.tsx b/x-pack/plugins/infra/public/components/asset_details/asset_details.tsx index f6b64ea5777ab..b745a80cc48e4 100644 --- a/x-pack/plugins/infra/public/components/asset_details/asset_details.tsx +++ b/x-pack/plugins/infra/public/components/asset_details/asset_details.tsx @@ -48,6 +48,7 @@ export const AssetDetails = ({ return ( 0 ? activeTabId ?? tabs[0].id : undefined} + onTabsStateChange={onTabsStateChange} > } body={ diff --git a/x-pack/plugins/infra/public/components/asset_details/components/expandable_content.tsx b/x-pack/plugins/infra/public/components/asset_details/components/expandable_content.tsx new file mode 100644 index 0000000000000..60f487d52d0ea --- /dev/null +++ b/x-pack/plugins/infra/public/components/asset_details/components/expandable_content.tsx @@ -0,0 +1,58 @@ +/* + * 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. + */ + +import { EuiFlexGroup, EuiFlexItem, EuiLink } from '@elastic/eui'; + +import { i18n } from '@kbn/i18n'; +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n-react'; +import useToggle from 'react-use/lib/useToggle'; + +interface ExpandableContentProps { + values: string | string[] | undefined; +} +export const ExpandableContent = (props: ExpandableContentProps) => { + const { values } = props; + const [isExpanded, toggle] = useToggle(false); + + const list = Array.isArray(values) ? values : [values]; + const [first, ...others] = list; + const hasOthers = others.length > 0; + const shouldShowMore = hasOthers && !isExpanded; + + return ( + +
+ {first} + {shouldShowMore && ( + <> + {' ... '} + + + + + )} +
+ {isExpanded && others.map((item, index) => {item})} + {hasOthers && isExpanded && ( + + + {i18n.translate('xpack.infra.nodeDetails.tabs.metadata.seeLess', { + defaultMessage: 'Show less', + })} + + + )} +
+ ); +}; diff --git a/x-pack/plugins/infra/public/components/asset_details/content/content.tsx b/x-pack/plugins/infra/public/components/asset_details/content/content.tsx index e1675ab46c741..b108781fbd4a3 100644 --- a/x-pack/plugins/infra/public/components/asset_details/content/content.tsx +++ b/x-pack/plugins/infra/public/components/asset_details/content/content.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { useTabSwitcherContext } from '../hooks/use_tab_switcher'; -import { Anomalies, Metadata, Processes, Osquery, Metrics, Logs } from '../tabs'; +import { Anomalies, Metadata, Processes, Osquery, Metrics, Logs, Overview } from '../tabs'; import { FlyoutTabIds, type TabState, type AssetDetailsProps } from '../types'; type Props = Pick< @@ -19,8 +19,8 @@ export const Content = ({ overrides, currentTimeRange, node, - nodeType = 'host', onTabsStateChange, + nodeType = 'host', }: Props) => { const onChange = (state: TabState) => { if (!onTabsStateChange) { @@ -35,6 +35,15 @@ export const Content = ({ + + + & { compact: boolean; }; @@ -45,16 +45,11 @@ export const Header = ({ compact, currentTimeRange, overrides, - onTabsStateChange, }: Props) => { const { euiTheme } = useEuiTheme(); const { showTab, activeTabId } = useTabSwitcherContext(); const onTabClick = (tabId: TabIds) => { - if (onTabsStateChange) { - onTabsStateChange({ activeTabId: tabId }); - } - showTab(tabId); }; diff --git a/x-pack/plugins/infra/public/components/asset_details/hooks/use_tab_switcher.tsx b/x-pack/plugins/infra/public/components/asset_details/hooks/use_tab_switcher.tsx index f6f7757bb062f..a529b6f38609c 100644 --- a/x-pack/plugins/infra/public/components/asset_details/hooks/use_tab_switcher.tsx +++ b/x-pack/plugins/infra/public/components/asset_details/hooks/use_tab_switcher.tsx @@ -8,9 +8,14 @@ import { useState } from 'react'; import createContainer from 'constate'; import { useLazyRef } from '../../../hooks/use_lazy_ref'; -import type { TabIds } from '../types'; +import type { TabIds, TabsStateChangeFn } from '../types'; -export function useTabSwitcher({ initialActiveTabId }: { initialActiveTabId?: TabIds }) { +interface TabSwitcherParams { + initialActiveTabId?: TabIds; + onTabsStateChange?: TabsStateChangeFn; +} + +export function useTabSwitcher({ initialActiveTabId, onTabsStateChange }: TabSwitcherParams) { const [activeTabId, setActiveTabId] = useState(initialActiveTabId); // This set keeps track of which tabs content have been rendered the first time. @@ -20,6 +25,10 @@ export function useTabSwitcher({ initialActiveTabId }: { initialActiveTabId?: Ta const showTab = (tabId: TabIds) => { renderedTabsSet.current.add(tabId); // On a tab click, mark the tab content as allowed to be rendered setActiveTabId(tabId); + + if (onTabsStateChange) { + onTabsStateChange({ activeTabId: tabId }); + } }; return { diff --git a/x-pack/plugins/infra/public/components/asset_details/tabs/index.ts b/x-pack/plugins/infra/public/components/asset_details/tabs/index.ts index 1bdd76d06676e..9d16e2fcbe8fd 100644 --- a/x-pack/plugins/infra/public/components/asset_details/tabs/index.ts +++ b/x-pack/plugins/infra/public/components/asset_details/tabs/index.ts @@ -11,3 +11,4 @@ export { Processes } from './processes/processes'; export { Osquery } from './osquery/osquery'; export { Metrics } from './metrics/metrics'; export { Logs } from './logs/logs'; +export { Overview } from './overview/overview'; diff --git a/x-pack/plugins/infra/public/components/asset_details/tabs/metadata/table.tsx b/x-pack/plugins/infra/public/components/asset_details/tabs/metadata/table.tsx index 544af40a414a3..5fe888c26e8bf 100644 --- a/x-pack/plugins/infra/public/components/asset_details/tabs/metadata/table.tsx +++ b/x-pack/plugins/infra/public/components/asset_details/tabs/metadata/table.tsx @@ -7,9 +7,6 @@ import { EuiText, - EuiFlexGroup, - EuiFlexItem, - EuiLink, EuiIcon, EuiInMemoryTable, EuiSearchBarProps, @@ -17,12 +14,11 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { useCallback, useMemo, useState } from 'react'; -import { FormattedMessage } from '@kbn/i18n-react'; -import useToggle from 'react-use/lib/useToggle'; import { debounce } from 'lodash'; import { Query } from '@elastic/eui'; import useLocalStorage from 'react-use/lib/useLocalStorage'; import { AddMetadataFilterButton } from './add_metadata_filter_button'; +import { ExpandableContent } from '../../components/expandable_content'; import { type Field, getRowsWithPins } from './utils'; import { AddMetadataPinToRow } from './add_pin_to_row'; @@ -194,54 +190,3 @@ export const Table = ({ loading, rows, onSearchChange, search, showActionsColumn /> ); }; - -interface ExpandableContentProps { - values: string | string[] | undefined; -} -const ExpandableContent = (props: ExpandableContentProps) => { - const { values } = props; - const [isExpanded, toggle] = useToggle(false); - - const list = Array.isArray(values) ? values : [values]; - const [first, ...others] = list; - const hasOthers = others.length > 0; - const shouldShowMore = hasOthers && !isExpanded; - - return ( - -
- {first} - {shouldShowMore && ( - <> - {' ... '} - - - - - )} -
- {isExpanded && others.map((item, index) => {item})} - {hasOthers && isExpanded && ( - - - {i18n.translate('xpack.infra.nodeDetails.tabs.metadata.seeLess', { - defaultMessage: 'Show less', - })} - - - )} -
- ); -}; diff --git a/x-pack/plugins/infra/public/components/asset_details/tabs/overview/kpi_grid.tsx b/x-pack/plugins/infra/public/components/asset_details/tabs/overview/kpi_grid.tsx new file mode 100644 index 0000000000000..89bb6b636a98e --- /dev/null +++ b/x-pack/plugins/infra/public/components/asset_details/tabs/overview/kpi_grid.tsx @@ -0,0 +1,38 @@ +/* + * 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. + */ +import React from 'react'; + +import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; +import { Tile } from './tile'; +import { KPI_CHARTS } from '../../../../common/visualizations/lens/kpi_grid_config'; +import type { KPIProps } from './overview'; +import type { StringDateRange } from '../../types'; + +export interface KPIGridProps extends KPIProps { + nodeName: string; + dateRange: StringDateRange; +} + +export const KPIGrid = React.memo(({ nodeName, dataView, dateRange }: KPIGridProps) => { + return ( + <> + + + {KPI_CHARTS.map(({ ...chartProp }) => ( + + + + ))} + + + ); +}); diff --git a/x-pack/plugins/infra/public/components/asset_details/tabs/overview/metadata_summary.tsx b/x-pack/plugins/infra/public/components/asset_details/tabs/overview/metadata_summary.tsx new file mode 100644 index 0000000000000..6354ab3355992 --- /dev/null +++ b/x-pack/plugins/infra/public/components/asset_details/tabs/overview/metadata_summary.tsx @@ -0,0 +1,109 @@ +/* + * 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. + */ + +import { + EuiButtonEmpty, + EuiDescriptionListTitle, + EuiFlexGroup, + EuiFlexItem, + EuiDescriptionList, + EuiDescriptionListDescription, + EuiHorizontalRule, + EuiLoadingSpinner, +} from '@elastic/eui'; +import { css } from '@emotion/react'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n-react'; +import type { InfraMetadata } from '../../../../../common/http_api'; +import { NOT_AVAILABLE_LABEL } from '../../translations'; +import { useTabSwitcherContext } from '../../hooks/use_tab_switcher'; +import { FlyoutTabIds } from '../../types'; +import { ExpandableContent } from '../../components/expandable_content'; + +const columnTitles = { + hostIp: i18n.translate('xpack.infra.assetDetailsEmbeddable.overview.metadataHostIpHeading', { + defaultMessage: 'Host IP', + }), + hostOsVersion: i18n.translate( + 'xpack.infra.assetDetailsEmbeddable.overview.metadataHostOsVersionHeading', + { + defaultMessage: 'Host OS version', + } + ), +}; + +type MetadataFields = 'hostIp' | 'hostOsVersion'; + +const metadataData = (metadataInfo: InfraMetadata['info']) => [ + { + field: 'hostIp', + value: metadataInfo?.host?.ip, + }, + { + field: 'hostOsVersion', + value: metadataInfo?.host?.os?.version, + }, +]; + +interface MetadataSummaryProps { + metadata: InfraMetadata | null; + metadataLoading: boolean; +} + +export const MetadataSummary = ({ metadata, metadataLoading }: MetadataSummaryProps) => { + const { showTab } = useTabSwitcherContext(); + + const onClick = () => { + showTab(FlyoutTabIds.METADATA); + }; + + return ( + <> + + + {metadataData(metadata?.info).map((metadataValue) => ( + + + + {columnTitles[metadataValue.field as MetadataFields]} + + + {metadataLoading ? ( + + ) : ( + + )} + + + + ))} + + + + + + + + + + ); +}; diff --git a/x-pack/plugins/infra/public/components/asset_details/tabs/overview/overview.tsx b/x-pack/plugins/infra/public/components/asset_details/tabs/overview/overview.tsx new file mode 100644 index 0000000000000..04f76c3c4de80 --- /dev/null +++ b/x-pack/plugins/infra/public/components/asset_details/tabs/overview/overview.tsx @@ -0,0 +1,100 @@ +/* + * 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. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiCallOut, EuiFlexGroup, EuiFlexItem, EuiLink } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import type { DataView } from '@kbn/data-views-plugin/public'; +import type { InventoryItemType } from '../../../../../common/inventory_models/types'; +import { findInventoryModel } from '../../../../../common/inventory_models'; +import type { MetricsTimeInput } from '../../../../pages/metrics/metric_detail/hooks/use_metrics_time'; +import { useMetadata } from '../../hooks/use_metadata'; +import { useSourceContext } from '../../../../containers/metrics_source'; +import { MetadataSummary } from './metadata_summary'; +import { KPIGrid } from './kpi_grid'; +import type { StringDateRange } from '../../types'; + +export interface MetadataSearchUrlState { + metadataSearchUrlState: string; + setMetadataSearchUrlState: (metadataSearch: { metadataSearch?: string }) => void; +} + +export interface KPIProps { + dateRange?: StringDateRange; + dataView?: DataView; +} +export interface OverviewProps extends KPIProps { + currentTimeRange: MetricsTimeInput; + nodeName: string; + nodeType: InventoryItemType; +} + +const DEFAULT_DATE_RANGE = { + from: 'now-15m', + to: 'now', + mode: 'absolute' as const, +}; + +export const Overview = ({ + nodeName, + currentTimeRange, + nodeType, + dateRange, + dataView, +}: OverviewProps) => { + const inventoryModel = findInventoryModel(nodeType); + const { sourceId } = useSourceContext(); + const { + loading: metadataLoading, + error: fetchMetadataError, + metadata, + } = useMetadata(nodeName, nodeType, inventoryModel.requiredMetrics, sourceId, currentTimeRange); + + return ( + + + + + + {fetchMetadataError ? ( + + window.location.reload()} + > + {i18n.translate('xpack.infra.assetDetailsEmbeddable.overview.errorAction', { + defaultMessage: 'reload the page', + })} + + ), + }} + /> + + ) : ( + + )} + + + ); +}; diff --git a/x-pack/plugins/infra/public/components/asset_details/tabs/overview/tile.tsx b/x-pack/plugins/infra/public/components/asset_details/tabs/overview/tile.tsx new file mode 100644 index 0000000000000..18ae64ad8ee6a --- /dev/null +++ b/x-pack/plugins/infra/public/components/asset_details/tabs/overview/tile.tsx @@ -0,0 +1,134 @@ +/* + * 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. + */ +import React, { useMemo } from 'react'; + +import { i18n } from '@kbn/i18n'; +import { + EuiIcon, + EuiPanel, + EuiFlexGroup, + EuiFlexItem, + EuiText, + EuiI18n, + EuiToolTip, +} from '@elastic/eui'; +import styled from 'styled-components'; +import type { Action } from '@kbn/ui-actions-plugin/public'; +import type { KPIChartProps } from '../../../../common/visualizations/lens/kpi_grid_config'; +import { useLensAttributes } from '../../../../hooks/use_lens_attributes'; +import { LensWrapper } from '../../../../common/visualizations/lens/lens_wrapper'; +import { buildCombinedHostsFilter } from '../../../../utils/filters/build'; +import { TooltipContent } from '../../../../common/visualizations/metric_explanation/tooltip_content'; +import type { KPIGridProps } from './kpi_grid'; + +const MIN_HEIGHT = 150; + +export const Tile = ({ + title, + type, + backgroundColor, + toolTip, + decimals = 1, + trendLine = false, + nodeName, + dateRange, + dataView, +}: KPIChartProps & KPIGridProps) => { + const getSubtitle = () => + i18n.translate('xpack.infra.assetDetailsEmbeddable.overview.metricTrend.subtitle.average', { + defaultMessage: 'Average', + }); + + const { formula, attributes, getExtraActions, error } = useLensAttributes({ + type, + dataView, + options: { + backgroundColor, + decimals, + subtitle: getSubtitle(), + showTrendLine: trendLine, + showTitle: false, + title, + }, + visualizationType: 'metricChart', + }); + + const filters = useMemo(() => { + return [ + buildCombinedHostsFilter({ + field: 'host.name', + values: [nodeName], + dataView, + }), + ]; + }, [dataView, nodeName]); + + const extraActions: Action[] = useMemo( + () => + getExtraActions({ + timeRange: dateRange, + filters, + }), + [filters, getExtraActions, dateRange] + ); + + const loading = !attributes; + + return ( + + {error ? ( + + + + + + + + + + + ) : ( + } + anchorClassName="eui-fullWidth" + > + + + )} + + ); +}; + +const EuiPanelStyled = styled(EuiPanel)` + .echMetric { + border-radius: ${({ theme }) => theme.eui.euiBorderRadius}; + pointer-events: none; + } +`; diff --git a/x-pack/plugins/infra/public/components/asset_details/tabs/processes/summary_table.tsx b/x-pack/plugins/infra/public/components/asset_details/tabs/processes/summary_table.tsx index 6cbf25013f876..57814aa7bacc2 100644 --- a/x-pack/plugins/infra/public/components/asset_details/tabs/processes/summary_table.tsx +++ b/x-pack/plugins/infra/public/components/asset_details/tabs/processes/summary_table.tsx @@ -20,6 +20,7 @@ import { import { euiStyled } from '@kbn/kibana-react-plugin/common'; import type { ProcessListAPIResponse } from '../../../../../common/http_api'; import { STATE_NAMES } from './states'; +import { NOT_AVAILABLE_LABEL } from '../../translations'; interface Props { processSummary: ProcessListAPIResponse['summary']; @@ -30,10 +31,6 @@ type SummaryRecord = { total: number; } & Record; -const NOT_AVAILABLE_LABEL = i18n.translate('xpack.infra.notAvailableLabel', { - defaultMessage: 'N/A', -}); - const processSummaryNotAvailable = { total: NOT_AVAILABLE_LABEL, running: NOT_AVAILABLE_LABEL, diff --git a/x-pack/plugins/infra/public/components/asset_details/translations.ts b/x-pack/plugins/infra/public/components/asset_details/translations.ts new file mode 100644 index 0000000000000..a77dbc727ccc2 --- /dev/null +++ b/x-pack/plugins/infra/public/components/asset_details/translations.ts @@ -0,0 +1,58 @@ +/* + * 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. + */ + +import { i18n } from '@kbn/i18n'; + +export const TOOLTIP = { + hostCount: i18n.translate('xpack.infra.assetDetailsEmbeddable.metrics.tooltip.hostCount', { + defaultMessage: 'Number of hosts returned by your search criteria.', + }), + + cpuUsage: i18n.translate('xpack.infra.assetDetailsEmbeddable.metrics.tooltip.cpuUsage', { + defaultMessage: + 'Percentage of CPU time spent in states other than Idle and IOWait, normalized by the number of CPU cores. This includes both time spent on user space and kernel space.', + }), + diskSpaceUsage: i18n.translate( + 'xpack.infra.assetDetailsEmbeddable.metrics.tooltip.diskSpaceUsage', + { + defaultMessage: 'Percentage of disk space used.', + } + ), + diskLatency: i18n.translate('xpack.infra.assetDetailsEmbeddable.metrics.tooltip.diskLatency', { + defaultMessage: 'Time spent to service disk requests.', + }), + memoryFree: i18n.translate('xpack.infra.assetDetailsEmbeddable.metrics.tooltip.memoryFree', { + defaultMessage: 'Total available memory including page cache.', + }), + memoryTotal: i18n.translate('xpack.infra.assetDetailsEmbeddable.metrics.tooltip.memoryTotal', { + defaultMessage: 'Total memory capacity.', + }), + memoryUsage: i18n.translate('xpack.infra.assetDetailsEmbeddable.metrics.tooltip.memoryUsage', { + defaultMessage: 'Percentage of main memory usage excluding page cache.', + }), + normalizedLoad1m: i18n.translate( + 'xpack.infra.assetDetailsEmbeddable.metrics.tooltip.normalizedLoad1m', + { + defaultMessage: '1 minute load average normalized by the number of CPU cores. ', + } + ), + rx: i18n.translate('xpack.infra.assetDetailsEmbeddable.metrics.tooltip.rx', { + defaultMessage: + 'Number of bytes which have been received per second on the public interfaces of the hosts.', + }), + tx: i18n.translate('xpack.infra.assetDetailsEmbeddable.metrics.tooltip.tx', { + defaultMessage: + 'Number of bytes which have been sent per second on the public interfaces of the hosts.', + }), +}; + +export const NOT_AVAILABLE_LABEL = i18n.translate( + 'xpack.infra.assetDetailsEmbeddable.notApplicableLabel', + { + defaultMessage: 'N/A', + } +); diff --git a/x-pack/plugins/infra/public/components/asset_details/types.ts b/x-pack/plugins/infra/public/components/asset_details/types.ts index a3d519641da3a..f4e2e0cf9b3f8 100644 --- a/x-pack/plugins/infra/public/components/asset_details/types.ts +++ b/x-pack/plugins/infra/public/components/asset_details/types.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { LogViewReference } from '@kbn/logs-shared-plugin/common'; +import type { DataView } from '@kbn/data-views-plugin/public'; +import type { LogViewReference } from '@kbn/logs-shared-plugin/common'; import type { InventoryItemType } from '../../../common/inventory_models/types'; import type { InfraAssetMetricType, SnapshotCustomMetricInput } from '../../../common/http_api'; @@ -25,6 +26,7 @@ export type HostNodeRow = HostMetadata & }; export enum FlyoutTabIds { + OVERVIEW = 'overview', METRICS = 'metrics', METADATA = 'metadata', PROCESSES = 'processes', @@ -37,7 +39,17 @@ export enum FlyoutTabIds { export type TabIds = `${FlyoutTabIds}`; +export interface StringDateRange { + from: string; + to: string; + mode?: 'absolute' | 'relative' | undefined; +} + export interface TabState { + overview?: { + dateRange: StringDateRange; + dataView?: DataView; + }; metadata?: { query?: string; showActionsColumn?: boolean; diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/chart/metric_chart_wrapper.tsx b/x-pack/plugins/infra/public/pages/metrics/hosts/components/chart/metric_chart_wrapper.tsx index c663aac2fe5cb..f25a26044fe25 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/components/chart/metric_chart_wrapper.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/components/chart/metric_chart_wrapper.tsx @@ -8,7 +8,7 @@ import React, { useEffect, useRef, CSSProperties } from 'react'; import { Chart, Metric, type MetricWNumber, type MetricWTrend } from '@elastic/charts'; import { EuiPanel, EuiToolTip } from '@elastic/eui'; import styled from 'styled-components'; -import { ChartLoader } from './chart_loader'; +import { ChartLoader } from '../../../../../common/visualizations/lens/chart_loader'; export interface Props extends Pick { id: string; diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/host_details_flyout/flyout_wrapper.tsx b/x-pack/plugins/infra/public/pages/metrics/hosts/components/host_details_flyout/flyout_wrapper.tsx index 6d288a54b664e..ea1131bef27b0 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/components/host_details_flyout/flyout_wrapper.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/components/host_details_flyout/flyout_wrapper.tsx @@ -13,6 +13,7 @@ import { HostFlyout, useHostFlyoutUrlState } from '../../hooks/use_host_flyout_u import { AssetDetails } from '../../../../../components/asset_details/asset_details'; import { orderedFlyoutTabs } from './tabs'; import { useLogViewReference } from '../../hooks/use_log_view_reference'; +import { useMetricsDataViewContext } from '../../hooks/use_data_view'; export interface Props { node: HostNodeRow; @@ -23,6 +24,8 @@ const NODE_TYPE = 'host' as InventoryItemType; export const FlyoutWrapper = ({ node, closeFlyout }: Props) => { const { getDateRangeAsTimestamp } = useUnifiedSearchContext(); + const { searchCriteria } = useUnifiedSearchContext(); + const { dataView } = useMetricsDataViewContext(); const { logViewReference, loading } = useLogViewReference({ id: 'hosts-flyout-logs-view', }); @@ -43,6 +46,10 @@ export const FlyoutWrapper = ({ node, closeFlyout }: Props) => { currentTimeRange={currentTimeRange} activeTabId={hostFlyoutState?.tabId} overrides={{ + overview: { + dateRange: searchCriteria.dateRange, + dataView, + }, metadata: { query: hostFlyoutState?.metadataSearch, showActionsColumn: true, diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/host_details_flyout/tabs.ts b/x-pack/plugins/infra/public/pages/metrics/hosts/components/host_details_flyout/tabs.ts index cc1ce8ad39768..66f4f848b5742 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/components/host_details_flyout/tabs.ts +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/components/host_details_flyout/tabs.ts @@ -9,6 +9,13 @@ import { i18n } from '@kbn/i18n'; import { FlyoutTabIds, type Tab } from '../../../../../components/asset_details/types'; export const orderedFlyoutTabs: Tab[] = [ + { + id: FlyoutTabIds.OVERVIEW, + name: i18n.translate('xpack.infra.nodeDetails.tabs.overview.title', { + defaultMessage: 'Overview', + }), + 'data-test-subj': 'hostsView-flyout-tabs-overview', + }, { id: FlyoutTabIds.METADATA, name: i18n.translate('xpack.infra.nodeDetails.tabs.metadata.title', { diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/kpis/hosts_tile.tsx b/x-pack/plugins/infra/public/pages/metrics/hosts/components/kpis/hosts_tile.tsx index 2fad8c0602745..9cfb67a88c3b0 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/components/kpis/hosts_tile.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/components/kpis/hosts_tile.tsx @@ -9,10 +9,10 @@ import React from 'react'; import { hostLensFormulas } from '../../../../../common/visualizations'; import { useHostCountContext } from '../../hooks/use_host_count'; import { useUnifiedSearchContext } from '../../hooks/use_unified_search'; -import { TOOLTIP } from '../../translations'; +import { TOOLTIP } from '../../../../../common/visualizations/lens/translations'; import { type Props, MetricChartWrapper } from '../chart/metric_chart_wrapper'; -import { TooltipContent } from '../metric_explanation/tooltip_content'; +import { TooltipContent } from '../../../../../common/visualizations/metric_explanation/tooltip_content'; import { KPIChartProps } from './tile'; const HOSTS_CHART: Omit = { diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/kpis/kpi_grid.tsx b/x-pack/plugins/infra/public/pages/metrics/hosts/components/kpis/kpi_grid.tsx index 3e0ead3ff689f..5914be028ab8b 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/components/kpis/kpi_grid.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/components/kpis/kpi_grid.tsx @@ -7,60 +7,18 @@ import React, { CSSProperties } from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; import { EuiSpacer } from '@elastic/eui'; -import { KPIChartProps, Tile } from './tile'; +import { HostMetricsDocsLink } from '../../../../../common/visualizations/metric_explanation/host_metrics_docs_link'; +import { Tile } from './tile'; import { HostCountProvider } from '../../hooks/use_host_count'; -import { TOOLTIP } from '../../translations'; import { HostsTile } from './hosts_tile'; -import { HostMetricsDocsLink } from '../metric_explanation/host_metrics_docs_link'; import { KPI_CHART_MIN_HEIGHT } from '../../constants'; +import { KPI_CHARTS } from '../../../../../common/visualizations/lens/kpi_grid_config'; const lensStyle: CSSProperties = { height: KPI_CHART_MIN_HEIGHT, }; -const KPI_CHARTS: Array> = [ - { - type: 'cpuUsage', - trendLine: true, - backgroundColor: '#F1D86F', - title: i18n.translate('xpack.infra.hostsViewPage.metricTrend.cpuUsage.title', { - defaultMessage: 'CPU Usage', - }), - toolTip: TOOLTIP.cpuUsage, - }, - { - type: 'normalizedLoad1m', - trendLine: true, - backgroundColor: '#79AAD9', - title: i18n.translate('xpack.infra.hostsViewPage.metricTrend.normalizedLoad1m.title', { - defaultMessage: 'Normalized Load', - }), - toolTip: TOOLTIP.rx, - }, - { - type: 'memoryUsage', - trendLine: true, - backgroundColor: '#A987D1', - title: i18n.translate('xpack.infra.hostsViewPage.metricTrend.memoryUsage.title', { - defaultMessage: 'Memory Usage', - }), - toolTip: i18n.translate('xpack.infra.hostsViewPage.metricTrend.memoryUsage.tooltip', { - defaultMessage: 'Main memory usage excluding page cache.', - }), - }, - { - type: 'diskSpaceUsage', - trendLine: true, - backgroundColor: '#F5A35C', - title: i18n.translate('xpack.infra.hostsViewPage.metricTrend.diskSpaceUsage.title', { - defaultMessage: 'Disk Space Usage', - }), - toolTip: TOOLTIP.tx, - }, -]; - export const KPIGrid = () => { return ( diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/kpis/tile.tsx b/x-pack/plugins/infra/public/pages/metrics/hosts/components/kpis/tile.tsx index 0c1d254342b84..5890442358113 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/components/kpis/tile.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/components/kpis/tile.tsx @@ -24,11 +24,11 @@ import { useMetricsDataViewContext } from '../../hooks/use_data_view'; import { useUnifiedSearchContext } from '../../hooks/use_unified_search'; import { HostsLensMetricChartFormulas } from '../../../../../common/visualizations'; import { useHostsViewContext } from '../../hooks/use_hosts_view'; -import { LensWrapper } from '../chart/lens_wrapper'; -import { buildCombinedHostsFilter } from '../../utils'; +import { LensWrapper } from '../../../../../common/visualizations/lens/lens_wrapper'; +import { buildCombinedHostsFilter } from '../../../../../utils/filters/build'; import { useHostCountContext } from '../../hooks/use_host_count'; import { useAfterLoadedState } from '../../hooks/use_after_loaded_state'; -import { TooltipContent } from '../metric_explanation/tooltip_content'; +import { TooltipContent } from '../../../../../common/visualizations/metric_explanation/tooltip_content'; import { KPI_CHART_MIN_HEIGHT } from '../../constants'; export interface KPIChartProps { diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/table/column_header.tsx b/x-pack/plugins/infra/public/pages/metrics/hosts/components/table/column_header.tsx index 90d0383ca97d7..e23275598f990 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/components/table/column_header.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/components/table/column_header.tsx @@ -8,8 +8,8 @@ import React, { useState, useRef, useCallback, useLayoutEffect } from 'react'; import { EuiPopover, EuiIcon, EuiFlexGroup, useEuiTheme } from '@elastic/eui'; import { css } from '@emotion/react'; import { APP_WRAPPER_CLASS } from '@kbn/core/public'; +import { TooltipContent } from '../../../../../common/visualizations/metric_explanation/tooltip_content'; import { useBoolean } from '../../../../../hooks/use_boolean'; -import { TooltipContent } from '../metric_explanation/tooltip_content'; interface Props { label: string; diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/logs/logs_tab_content.tsx b/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/logs/logs_tab_content.tsx index 66cbc9d1c1b1b..15ab7b9f0eca6 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/logs/logs_tab_content.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/logs/logs_tab_content.tsx @@ -15,7 +15,7 @@ import { useUnifiedSearchContext } from '../../../hooks/use_unified_search'; import { useLogsSearchUrlState } from '../../../hooks/use_logs_search_url_state'; import { LogsLinkToStream } from './logs_link_to_stream'; import { LogsSearchBar } from './logs_search_bar'; -import { buildCombinedHostsFilter } from '../../../utils'; +import { buildCombinedHostsFilter } from '../../../../../../utils/filters/build'; import { useLogViewReference } from '../../../hooks/use_log_view_reference'; export const LogsTabContent = () => { diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/metrics/metric_chart.tsx b/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/metrics/metric_chart.tsx index 5d7e946f25e2a..06498d6b26fb5 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/metrics/metric_chart.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/metrics/metric_chart.tsx @@ -22,9 +22,9 @@ import { useMetricsDataViewContext } from '../../../hooks/use_data_view'; import { useUnifiedSearchContext } from '../../../hooks/use_unified_search'; import { HostsLensLineChartFormulas } from '../../../../../../common/visualizations'; import { useHostsViewContext } from '../../../hooks/use_hosts_view'; -import { buildCombinedHostsFilter } from '../../../utils'; +import { buildCombinedHostsFilter } from '../../../../../../utils/filters/build'; import { useHostsTableContext } from '../../../hooks/use_hosts_table'; -import { LensWrapper } from '../../chart/lens_wrapper'; +import { LensWrapper } from '../../../../../../common/visualizations/lens/lens_wrapper'; import { useAfterLoadedState } from '../../../hooks/use_after_loaded_state'; import { METRIC_CHART_MIN_HEIGHT } from '../../../constants'; diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/metrics/metrics_grid.tsx b/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/metrics/metrics_grid.tsx index 33f45072ee105..4b2ec7a6867e4 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/metrics/metrics_grid.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/metrics/metrics_grid.tsx @@ -9,8 +9,8 @@ import React from 'react'; import { EuiFlexGrid, EuiFlexItem } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { EuiSpacer } from '@elastic/eui'; +import { HostMetricsDocsLink } from '../../../../../../common/visualizations/metric_explanation/host_metrics_docs_link'; import { MetricChart, MetricChartProps } from './metric_chart'; -import { HostMetricsDocsLink } from '../../metric_explanation/host_metrics_docs_link'; const DEFAULT_BREAKDOWN_SIZE = 20; const CHARTS_IN_ORDER: Array & { fullRow?: boolean }> = [ diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/hooks/use_alerts_query.ts b/x-pack/plugins/infra/public/pages/metrics/hosts/hooks/use_alerts_query.ts index d79ee39498386..46ef8c62d3ed7 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/hooks/use_alerts_query.ts +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/hooks/use_alerts_query.ts @@ -15,7 +15,7 @@ import { HostsState } from './use_unified_search_url_state'; import { useHostsViewContext } from './use_hosts_view'; import { AlertStatus } from '../types'; import { ALERT_STATUS_QUERY } from '../constants'; -import { buildCombinedHostsFilter } from '../utils'; +import { buildCombinedHostsFilter } from '../../../../utils/filters/build'; export interface AlertsEsQuery { bool: BoolQuery; diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/hooks/use_host_flyout_url_state.ts b/x-pack/plugins/infra/public/pages/metrics/hosts/hooks/use_host_flyout_url_state.ts index 82568aed4cf96..65d81ce415bea 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/hooks/use_host_flyout_url_state.ts +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/hooks/use_host_flyout_url_state.ts @@ -16,7 +16,7 @@ import { useUrlState } from '../../../../utils/use_url_state'; export const DEFAULT_STATE: HostFlyout = { itemId: '', - tabId: FlyoutTabIds.METADATA, + tabId: FlyoutTabIds.OVERVIEW, processSearch: undefined, metadataSearch: undefined, }; @@ -45,6 +45,7 @@ export const useHostFlyoutUrlState = (): [HostFlyoutUrl, SetHostFlyoutState] => }; const FlyoutTabIdRT = rt.union([ + rt.literal(FlyoutTabIds.OVERVIEW), rt.literal(FlyoutTabIds.METADATA), rt.literal(FlyoutTabIds.PROCESSES), rt.literal(FlyoutTabIds.LOGS), diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/hooks/use_hosts_table.tsx b/x-pack/plugins/infra/public/pages/metrics/hosts/hooks/use_hosts_table.tsx index 4eaf8a400c461..18310ad2317c0 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/hooks/use_hosts_table.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/hooks/use_hosts_table.tsx @@ -30,8 +30,9 @@ import { useHostsViewContext } from './use_hosts_view'; import { useUnifiedSearchContext } from './use_unified_search'; import { useMetricsDataViewContext } from './use_data_view'; import { ColumnHeader } from '../components/table/column_header'; -import { TOOLTIP, TABLE_COLUMN_LABEL } from '../translations'; -import { buildCombinedHostsFilter } from '../utils'; +import { TABLE_COLUMN_LABEL } from '../translations'; +import { TOOLTIP } from '../../../../common/visualizations/lens/translations'; +import { buildCombinedHostsFilter } from '../../../../utils/filters/build'; /** * Columns and items types diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/hooks/use_log_view_reference.ts b/x-pack/plugins/infra/public/pages/metrics/hosts/hooks/use_log_view_reference.ts index 46a062001bb74..379f9ff39da9a 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/hooks/use_log_view_reference.ts +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/hooks/use_log_view_reference.ts @@ -5,7 +5,6 @@ * 2.0. */ -// import { useMemo } from 'react'; import useAsync from 'react-use/lib/useAsync'; import { v4 as uuidv4 } from 'uuid'; import { DEFAULT_LOG_VIEW, LogViewReference } from '@kbn/logs-shared-plugin/common'; diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/hooks/use_unified_search.ts b/x-pack/plugins/infra/public/pages/metrics/hosts/hooks/use_unified_search.ts index f261f231e2a81..d67388cf40951 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/hooks/use_unified_search.ts +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/hooks/use_unified_search.ts @@ -22,7 +22,7 @@ import { type HostsState, type StringDateRangeTimestamp, } from './use_unified_search_url_state'; -import { retrieveFieldsFromFilter } from '../utils'; +import { retrieveFieldsFromFilter } from '../../../../utils/filters/build'; const buildQuerySubmittedPayload = ( hostState: HostsState & { parsedDateRange: StringDateRangeTimestamp } diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/translations.ts b/x-pack/plugins/infra/public/pages/metrics/hosts/translations.ts index cb97ae5498061..9a2860b224031 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/translations.ts +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/translations.ts @@ -7,43 +7,6 @@ import { i18n } from '@kbn/i18n'; -export const TOOLTIP = { - hostCount: i18n.translate('xpack.infra.hostsViewPage.metrics.tooltip.hostCount', { - defaultMessage: 'Number of hosts returned by your search criteria.', - }), - - cpuUsage: i18n.translate('xpack.infra.hostsViewPage.metrics.tooltip.cpuUsage', { - defaultMessage: - 'Percentage of CPU time spent in states other than Idle and IOWait, normalized by the number of CPU cores. This includes both time spent on user space and kernel space.', - }), - diskSpaceUsage: i18n.translate('xpack.infra.hostsViewPage.metrics.tooltip.diskSpaceUsage', { - defaultMessage: 'Percentage of disk space used.', - }), - diskLatency: i18n.translate('xpack.infra.hostsViewPage.metrics.tooltip.diskLatency', { - defaultMessage: 'Time spent to service disk requests.', - }), - memoryFree: i18n.translate('xpack.infra.hostsViewPage.metrics.tooltip.memoryFree', { - defaultMessage: 'Total available memory including page cache.', - }), - memoryTotal: i18n.translate('xpack.infra.hostsViewPage.metrics.tooltip.memoryTotal', { - defaultMessage: 'Total memory capacity.', - }), - memoryUsage: i18n.translate('xpack.infra.hostsViewPage.metrics.tooltip.memoryUsage', { - defaultMessage: 'Percentage of main memory usage excluding page cache.', - }), - normalizedLoad1m: i18n.translate('xpack.infra.hostsViewPage.metrics.tooltip.normalizedLoad1m', { - defaultMessage: '1 minute load average normalized by the number of CPU cores. ', - }), - rx: i18n.translate('xpack.infra.hostsViewPage.metrics.tooltip.rx', { - defaultMessage: - 'Number of bytes which have been received per second on the public interfaces of the hosts.', - }), - tx: i18n.translate('xpack.infra.hostsViewPage.metrics.tooltip.tx', { - defaultMessage: - 'Number of bytes which have been sent per second on the public interfaces of the hosts.', - }), -}; - export const TABLE_COLUMN_LABEL = { title: i18n.translate('xpack.infra.hostsViewPage.table.nameColumnHeader', { defaultMessage: 'Name', diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/utils.ts b/x-pack/plugins/infra/public/utils/filters/build.ts similarity index 100% rename from x-pack/plugins/infra/public/pages/metrics/hosts/utils.ts rename to x-pack/plugins/infra/public/utils/filters/build.ts diff --git a/x-pack/test/functional/apps/infra/hosts_view.ts b/x-pack/test/functional/apps/infra/hosts_view.ts index 2427b0617637e..f04fb3dc0740a 100644 --- a/x-pack/test/functional/apps/infra/hosts_view.ts +++ b/x-pack/test/functional/apps/infra/hosts_view.ts @@ -266,10 +266,41 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); }); + describe('Overview Tab', () => { + it('should render 4 metrics trend tiles', async () => { + const hosts = await pageObjects.infraHostsView.getAllKPITiles(); + expect(hosts.length).to.equal(5); + }); + + [ + { metric: 'cpuUsage', value: '13.9%' }, + { metric: 'normalizedLoad1m', value: '18.8%' }, + { metric: 'memoryUsage', value: '94.9%' }, + { metric: 'diskSpaceUsage', value: 'N/A' }, + ].forEach(({ metric, value }) => { + it(`${metric} tile should show ${value}`, async () => { + await retry.try(async () => { + const tileValue = await pageObjects.infraHostsView.getAssetDetailsKPITileValue( + metric + ); + expect(tileValue).to.eql(value); + }); + }); + }); + it('should navigate to metadata tab', async () => { + await pageObjects.infraHostsView.clickShowAllMetadataOverviewTab(); + await pageObjects.header.waitUntilLoadingHasFinished(); + await pageObjects.infraHostsView.metadataTableExist(); + }); + }); + describe('Metadata Tab', () => { it('should render metadata tab, pin/unpin row, add and remove filter', async () => { + await pageObjects.infraHostsView.clickMetadataFlyoutTab(); + const metadataTab = await pageObjects.infraHostsView.getMetadataTabName(); expect(metadataTab).to.contain('Metadata'); + await pageObjects.infraHostsView.metadataTableExist(); // Add Pin await pageObjects.infraHostsView.clickAddMetadataPin(); diff --git a/x-pack/test/functional/page_objects/infra_hosts_view.ts b/x-pack/test/functional/page_objects/infra_hosts_view.ts index 244967174ebf6..e8986e4d04507 100644 --- a/x-pack/test/functional/page_objects/infra_hosts_view.ts +++ b/x-pack/test/functional/page_objects/infra_hosts_view.ts @@ -40,10 +40,18 @@ export function InfraHostsViewProvider({ getService }: FtrProviderContext) { return testSubjects.click('euiFlyoutCloseButton'); }, + async clickMetadataFlyoutTab() { + return testSubjects.click('hostsView-flyout-tabs-metadata'); + }, + async clickProcessesFlyoutTab() { return testSubjects.click('hostsView-flyout-tabs-processes'); }, + async clickShowAllMetadataOverviewTab() { + return testSubjects.click('infraMetadataSummaryShowAllMetadataButton'); + }, + async clickLogsFlyoutTab() { return testSubjects.click('hostsView-flyout-tabs-logs'); }, @@ -188,10 +196,21 @@ export function InfraHostsViewProvider({ getService }: FtrProviderContext) { }, // Flyout Tabs + async getAssetDetailsKPITileValue(type: string) { + const container = await testSubjects.find('assetDetailsKPIGrid'); + const element = await container.findByTestSubject(`assetDetailsKPI-${type}`); + const div = await element.findByClassName('echMetricText__value'); + return div.getAttribute('title'); + }, + getMetadataTab() { return testSubjects.find('hostsView-flyout-tabs-metadata'); }, + metadataTableExist() { + return testSubjects.exists('infraMetadataTable'); + }, + async getMetadataTabName() { const tabElement = await this.getMetadataTab(); const tabTitle = await tabElement.findByClassName('euiTab__content');