mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
* [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:
parent
e832c80137
commit
d226c8c298
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 |
|
@ -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]
|
||||
|
|
|
@ -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};
|
||||
`;
|
|
@ -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 &&
|
||||
|
|
|
@ -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}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue