[Infra UI] Display non-metric details on Node Detail page (#43551) (#46049)

* [Infra UI] Display non-metric details on Node Detail page

- Closes #42689
- Adds NodeDetails component

* clean things up a bit

* Change hook order

* Start of docs changes

* Making expand button more consitent

* Update docs for this minor change

* Changing handleClick to toggleIsOpen

* Optimizing fields slice
This commit is contained in:
Chris Cowan 2019-09-18 13:20:55 -07:00 committed by GitHub
parent e832c80137
commit d226c8c298
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 161 additions and 2 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 362 KiB

After

Width:  |  Height:  |  Size: 308 KiB

Before After
Before After

View file

@ -4,6 +4,7 @@
== Viewing infrastructure metrics
When you select *View Metrics* for a component in your infrastructure from the <<infra-ui, Infrastructure app in Kibana>>, 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]

View file

@ -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<boolean>(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 (
<NodeDetailsContainer>
<Controls>
<EuiButtonIcon
iconType={isOpen ? 'arrowUp' : 'arrowDown'}
onClick={toggleIsOpen}
aria-label={i18n.translate('xpack.infra.nodeDetails.labels.showMoreDetails', {
defaultMessage: 'Show more details',
})}
/>
</Controls>
<EuiFlexGrid columns={4} style={{ flexGrow: 1 }}>
{fields.map(field => (
<EuiFlexItem key={field.field} style={{ minWidth: 0 }}>
<EuiTitle size="xs">
<h4>{getLabelForField(field)}</h4>
</EuiTitle>
<EuiText>{getValueForField(metadata, field)}</EuiText>
</EuiFlexItem>
))}
</EuiFlexGrid>
</NodeDetailsContainer>
);
};
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};
`;

View file

@ -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 &&

View file

@ -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(
</MetricsTitleTimeRangeContainer>
</EuiPageHeaderSection>
</EuiPageHeader>
<NodeDetails metadata={metadata} />
<EuiPageContentWithRelative>
<Metrics
label={name}