diff --git a/docs/infrastructure/images/infra-view-metrics.png b/docs/infrastructure/images/infra-view-metrics.png index d4ee287c234be..9ad862ec6515d 100644 Binary files a/docs/infrastructure/images/infra-view-metrics.png and b/docs/infrastructure/images/infra-view-metrics.png differ diff --git a/docs/infrastructure/view-metrics.asciidoc b/docs/infrastructure/view-metrics.asciidoc index fffa998b530fc..229d91ae5aae4 100644 --- a/docs/infrastructure/view-metrics.asciidoc +++ b/docs/infrastructure/view-metrics.asciidoc @@ -4,6 +4,7 @@ == Viewing infrastructure metrics When you select *View Metrics* for a component in your infrastructure from the <>, you can view detailed metrics for that component, and for any related components. +You can also view additional component metadata. [role="screenshot"] image::infrastructure/images/infra-view-metrics.png[Infrastructure View Metrics in Kibana] diff --git a/x-pack/legacy/plugins/infra/public/components/metrics/node_details.tsx b/x-pack/legacy/plugins/infra/public/components/metrics/node_details.tsx new file mode 100644 index 0000000000000..41331ed73afce --- /dev/null +++ b/x-pack/legacy/plugins/infra/public/components/metrics/node_details.tsx @@ -0,0 +1,156 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useState, useCallback, useMemo } from 'react'; +import { EuiButtonIcon, EuiFlexGrid, EuiFlexItem, EuiTitle, EuiText } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { get } from 'lodash'; +import { InfraMetadata } from '../../../common/http_api'; +import euiStyled from '../../../../../common/eui_styled_components'; + +interface Props { + metadata?: InfraMetadata | null; +} + +interface FieldDef { + field: string; + label: string; + isBoolean?: boolean; +} + +const FIELDS = [ + { + field: 'cloud.instance.id', + label: i18n.translate('xpack.infra.nodeDetails.labels.instanceId', { + defaultMessage: 'Instance ID', + }), + }, + { + field: 'cloud.provider', + label: i18n.translate('xpack.infra.nodeDetails.labels.cloudProvider', { + defaultMessage: 'Cloud Provider', + }), + }, + { + field: 'host.os.name', + label: i18n.translate('xpack.infra.nodeDetails.labels.operatinSystem', { + defaultMessage: 'Operating System', + }), + }, + { + field: 'host.os.kernel', + label: i18n.translate('xpack.infra.nodeDetails.labels.kernelVersion', { + defaultMessage: 'Kernel Version', + }), + }, + { + field: 'host.hostname', + label: i18n.translate('xpack.infra.nodeDetails.labels.hostname', { + defaultMessage: 'Hostname', + }), + }, + { + field: 'host.containerized', + label: i18n.translate('xpack.infra.nodeDetails.labels.containerized', { + defaultMessage: 'Containerized', + }), + isBoolean: true, + }, + { + field: 'cloud.project.id', + label: i18n.translate('xpack.infra.nodeDetails.labels.projectId', { + defaultMessage: 'Project ID', + }), + }, + { + field: 'cloud.availability_zone', + label: i18n.translate('xpack.infra.nodeDetails.labels.availabilityZone', { + defaultMessage: 'Availability Zone', + }), + }, + { + field: 'cloud.machine.type', + label: i18n.translate('xpack.infra.nodeDetails.labels.machineType', { + defaultMessage: 'Machine Type', + }), + }, + { + field: 'cloud.instance.name', + label: i18n.translate('xpack.infra.nodeDetails.labels.instanceName', { + defaultMessage: 'Instance Name', + }), + }, +] as FieldDef[]; + +const getLabelForField = ({ field }: FieldDef) => { + const fieldDef = FIELDS.find(f => f.field === field); + if (!fieldDef) return field; + return fieldDef.label; +}; + +const getValueForField = (metadata: InfraMetadata, { field, isBoolean }: FieldDef) => { + if (isBoolean) { + return get(metadata.info, field, false) + ? i18n.translate('xpack.infra.nodeDetails.yes', { defaultMessage: 'Yes' }) + : i18n.translate('xpack.infra.nodeDetails.no', { defaultMessage: 'No' }); + } + const value = get(metadata.info, field, '--'); + return value; +}; + +export const NodeDetails = ({ metadata }: Props) => { + const [isOpen, setControlState] = useState(false); + + const toggleIsOpen = useCallback( + () => (isOpen ? setControlState(false) : setControlState(true)), + [isOpen] + ); + + const fields = useMemo(() => (isOpen ? FIELDS : FIELDS.slice(0, 4)), [isOpen]); + + if (!metadata) { + return null; + } + + return ( + + + + + + {fields.map(field => ( + + +

{getLabelForField(field)}

+
+ {getValueForField(metadata, field)} +
+ ))} +
+
+ ); +}; + +const NodeDetailsContainer = euiStyled.div` +border-top: ${props => props.theme.eui.euiBorderWidthThin} solid ${props => + props.theme.eui.euiBorderColor}; +border-bottom: ${props => props.theme.eui.euiBorderWidthThin} solid ${props => + props.theme.eui.euiBorderColor}; +padding: ${props => props.theme.eui.paddingSizes.m} 0; +margin-bottom: ${props => props.theme.eui.paddingSizes.m}; +display: flex; +`; + +const Controls = euiStyled.div` +flex-grow: 0; +margin-right: ${props => props.theme.eui.paddingSizes.m}; +`; diff --git a/x-pack/legacy/plugins/infra/public/containers/metadata/use_metadata.ts b/x-pack/legacy/plugins/infra/public/containers/metadata/use_metadata.ts index 24d93a5e8121f..593b296497c2b 100644 --- a/x-pack/legacy/plugins/infra/public/containers/metadata/use_metadata.ts +++ b/x-pack/legacy/plugins/infra/public/containers/metadata/use_metadata.ts @@ -50,6 +50,7 @@ export function useMetadata( filteredLayouts: (response && getFilteredLayouts(layouts, response.features)) || [], error: (error && error.message) || null, loading, + metadata: response, cloudId: (response && response.info && diff --git a/x-pack/legacy/plugins/infra/public/pages/metrics/index.tsx b/x-pack/legacy/plugins/infra/public/pages/metrics/index.tsx index fbfd0af867f48..e73c1c787e38f 100644 --- a/x-pack/legacy/plugins/infra/public/pages/metrics/index.tsx +++ b/x-pack/legacy/plugins/infra/public/pages/metrics/index.tsx @@ -41,6 +41,7 @@ import { withMetricPageProviders } from './page_providers'; import { useMetadata } from '../../containers/metadata/use_metadata'; import { Source } from '../../containers/source'; import { InfraLoadingPanel } from '../../components/loading'; +import { NodeDetails } from '../../components/metrics/node_details'; const DetailPageContent = euiStyled(PageContent)` overflow: auto; @@ -87,7 +88,7 @@ export const MetricDetail = withMetricPageProviders( } const { sourceId } = useContext(Source.Context); const layouts = layoutCreator(theme); - const { name, filteredLayouts, loading: metadataLoading, cloudId } = useMetadata( + const { name, filteredLayouts, loading: metadataLoading, cloudId, metadata } = useMetadata( nodeId, nodeType, layouts, @@ -230,7 +231,7 @@ export const MetricDetail = withMetricPageProviders( - +