Skip to content

Commit

Permalink
[Infra] Use asset details flyout overview and metadata for containers (
Browse files Browse the repository at this point in the history
…#183767)

Closes #183727
## Summary

This PR adds asset details flyout to the inventory containers view. The
feature flag `observability:enableInfrastructureContainerAssetView`
should be enabled to see it.
To handle the asset type switching in the asset details flyout this PR
adds asset type to the `assetDetailsFlyout` URL param

Before:

![image](https://github.com/elastic/kibana/assets/14139027/3b4fe8a1-d874-46a4-801f-2e0f91880034)

After: 
- Overview

![image](https://github.com/elastic/kibana/assets/14139027/df54cc5c-f80f-40c8-9189-9d390e2c4eff)
- Metadata

![image](https://github.com/elastic/kibana/assets/14139027/cd4a5ba9-33fc-428a-bb0f-571d820260fc)

## Testing 
- Enable `observability:enableInfrastructureContainerAssetView` in infra
settings
- Go to containers view, click on a container, and check the content


https://github.com/elastic/kibana/assets/14139027/5ba578e6-6cdd-4561-a1f6-27ff4962ef6f
  • Loading branch information
jennypavlova committed May 21, 2024
1 parent 742dff0 commit df74eb6
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ const dashboardsTab: Tab = {
),
};

const linkToApmTab: Tab = {
id: ContentTabIds.LINK_TO_APM,
name: i18n.translate('xpack.infra.assetDetails.tabs.linkToApm', {
defaultMessage: 'APM',
}),
};

export const hostDetailsTabs: Tab[] = [
overviewTab,
metadataTab,
Expand All @@ -101,8 +108,11 @@ export const hostDetailsTabs: Tab[] = [
osqueryTab,
dashboardsTab,
];
export const hostDetailsFlyoutTabs: Tab[] = [...hostDetailsTabs, linkToApmTab];

// Profiling and Logs tab would be added in next iteration
export const containerDetailsTabs: Tab[] = [overviewTab, metadataTab];
export const containerDetailsFlyoutTabs: Tab[] = [overviewTab, metadataTab, linkToApmTab];

export const getAssetDetailsTabs = (type: string): Tab[] => {
switch (type) {
Expand All @@ -114,3 +124,14 @@ export const getAssetDetailsTabs = (type: string): Tab[] => {
return [];
}
};

export const getAssetDetailsFlyoutTabs = (type: string): Tab[] => {
switch (type) {
case 'host':
return hostDetailsFlyoutTabs;
case 'container':
return containerDetailsFlyoutTabs;
default:
return [];
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@
* 2.0.
*/

import { INTEGRATION_NAME } from './types';
import { INTEGRATION_NAME, ASSET_DETAILS_ASSET_TYPE } from './types';

export const ASSET_DETAILS_FLYOUT_COMPONENT_NAME = 'infraAssetDetailsFlyout';
export const ASSET_DETAILS_PAGE_COMPONENT_NAME = 'infraAssetDetailsPage';

export const APM_HOST_FILTER_FIELD = 'host.hostname';
export const APM_CONTAINER_FILTER_FIELD = 'container.id';

export const APM_FILTER_FIELD_PER_ASSET_TYPE = {
[ASSET_DETAILS_ASSET_TYPE.container]: APM_CONTAINER_FILTER_FIELD,
[ASSET_DETAILS_ASSET_TYPE.host]: APM_HOST_FILTER_FIELD,
};

export const ASSET_DETAILS_URL_STATE_KEY = 'assetDetails';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ import { usePluginConfig } from '../../../containers/plugin_config_context';
import { useKibanaContextForPlugin } from '../../../hooks/use_kibana';
import { useProfilingIntegrationSetting } from '../../../hooks/use_profiling_integration_setting';
import { CreateAlertRuleButton } from '../../shared/alerts/links/create_alert_rule_button';
import { APM_HOST_FILTER_FIELD } from '../constants';
import { LinkToNodeDetails } from '../links';
import { ContentTabIds, type LinkOptions, type RouteState, type Tab, type TabIds } from '../types';
import { useAssetDetailsRenderPropsContext } from './use_asset_details_render_props';
import { useTabSwitcherContext } from './use_tab_switcher';
import { getApmField } from '../utils';

type TabItem = NonNullable<Pick<EuiPageHeaderProps, 'tabs'>['tabs']>[number];

Expand Down Expand Up @@ -157,7 +157,7 @@ const useTabs = (tabs: Tab[]) => {
app: 'apm',
hash: 'traces',
search: {
kuery: `${APM_HOST_FILTER_FIELD}:"${asset.name}"`,
kuery: `${getApmField(asset.type)}:"${asset.id}"`,
},
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,8 @@ export enum INTEGRATION_NAME {
kubernetesContainer = 'kubernetesContainer',
docker = 'docker',
}

export enum ASSET_DETAILS_ASSET_TYPE {
container = 'container',
host = 'host',
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
* 2.0.
*/

import type { InventoryItemType } from '@kbn/metrics-data-access-plugin/common';
import type { InfraMetadata } from '../../../common/http_api';
import { INTEGRATIONS } from './constants';
import { INTEGRATIONS, APM_FILTER_FIELD_PER_ASSET_TYPE } from './constants';

export const toTimestampRange = ({ from, to }: { from: string; to: string }) => {
const fromTs = new Date(from).getTime();
Expand Down Expand Up @@ -34,3 +35,14 @@ export const getIntegrationsAvailable = (metadata?: InfraMetadata | null) => {
.filter(([_, fields]) => metadata?.features?.some((f) => fields.includes(f.name)))
.map(([name]) => name);
};

export const getApmField = (assetType: InventoryItemType): string => {
switch (assetType) {
case 'host':
return APM_FILTER_FIELD_PER_ASSET_TYPE.host;
case 'container':
return APM_FILTER_FIELD_PER_ASSET_TYPE.container;
default:
return '';
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import { i18n } from '@kbn/i18n';
import { usePerformanceContext } from '@kbn/ebt-tools';
import React, { useCallback } from 'react';
import React, { useCallback, useMemo } from 'react';
import { useCurrentEuiBreakpoint } from '@elastic/eui';
import { euiStyled } from '@kbn/kibana-react-plugin/common';
import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common';
Expand Down Expand Up @@ -63,11 +63,20 @@ export const NodesOverview = ({
isAutoReloading,
}: Props) => {
const currentBreakpoint = useCurrentEuiBreakpoint();
const [{ detailsItemId }, setFlyoutUrlState] = useAssetDetailsFlyoutState();
const [{ detailsItemId, assetType }, setFlyoutUrlState] = useAssetDetailsFlyoutState();
const { onPageReady } = usePerformanceContext();

const nodeName = useMemo(
() => nodes.find((node) => node.path[0].value === detailsItemId)?.name,
[detailsItemId, nodes]
);

const closeFlyout = useCallback(
() => setFlyoutUrlState({ detailsItemId: null }),
() =>
setFlyoutUrlState({
detailsItemId: null,
assetType: null,
}),
[setFlyoutUrlState]
);

Expand Down Expand Up @@ -149,9 +158,10 @@ export const NodesOverview = ({
bottomMargin={bottomMargin}
staticHeight={isStatic}
/>
{nodeType === 'host' && detailsItemId && (
{nodeType === assetType && detailsItemId && (
<AssetDetailsFlyout
assetName={detailsItemId}
assetId={detailsItemId}
assetName={nodeName}
assetType={nodeType}
closeFlyout={closeFlyout}
currentTime={currentTime}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,16 @@
* 2.0.
*/

import { i18n } from '@kbn/i18n';
import React, { useMemo } from 'react';
import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common';
import type { InventoryItemType } from '@kbn/metrics-data-access-plugin/common';
import type { InfraWaffleMapOptions } from '../../../../../lib/lib';
import { ContentTabIds } from '../../../../../components/asset_details/types';
import { AssetDetails } from '../../../../../components/asset_details';
import { useSourceContext } from '../../../../../containers/metrics_source';
import { hostDetailsTabs } from '../../../../../common/asset_details_config/asset_details_tabs';
import { getAssetDetailsFlyoutTabs } from '../../../../../common/asset_details_config/asset_details_tabs';

interface Props {
assetName: string;
assetName?: string;
assetId: string;
assetType: InventoryItemType;
closeFlyout: () => void;
currentTime: number;
Expand All @@ -24,20 +23,11 @@ interface Props {
refreshInterval?: number;
}

const flyoutTabs = [
...hostDetailsTabs,
{
id: ContentTabIds.LINK_TO_APM,
name: i18n.translate('xpack.infra.assetDetails.tabs.linkToApm', {
defaultMessage: 'APM',
}),
},
];

const ONE_HOUR = 60 * 60 * 1000;

export const AssetDetailsFlyout = ({
assetName,
assetId,
assetType,
closeFlyout,
currentTime,
Expand All @@ -62,7 +52,7 @@ export const AssetDetailsFlyout = ({

return source ? (
<AssetDetails
assetId={assetName}
assetId={assetId}
assetName={assetName}
assetType={assetType}
overrides={{
Expand All @@ -73,7 +63,7 @@ export const AssetDetailsFlyout = ({
options,
},
}}
tabs={flyoutTabs}
tabs={getAssetDetailsFlyoutTabs(assetType)}
links={['nodeDetails']}
renderMode={{
mode: 'flyout',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { first } from 'lodash';
import { EuiPopover, EuiToolTip } from '@elastic/eui';
import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common';
import { useBoolean } from '@kbn/react-hooks';
import { useUiSetting } from '@kbn/kibana-react-plugin/public';
import { enableInfrastructureContainerAssetView } from '@kbn/observability-plugin/common';
import {
InfraWaffleMapBounds,
InfraWaffleMapNode,
Expand Down Expand Up @@ -54,9 +56,13 @@ export const Node = ({
const color = colorFromValue(options.legend, rawValue, bounds);
const value = formatter(rawValue);

const isContainerAssetViewEnabled = useUiSetting(enableInfrastructureContainerAssetView);

const showContainerAssetDetailPage = nodeType === 'container' && isContainerAssetViewEnabled;

const toggleAssetPopover = () => {
if (nodeType === 'host') {
setFlyoutUrlState({ detailsItemId: node.name });
if (nodeType === 'host' || showContainerAssetDetailPage) {
setFlyoutUrlState({ detailsItemId: node.id, assetType: nodeType });
} else {
togglePopover();
}
Expand All @@ -71,7 +77,7 @@ export const Node = ({
color={color}
nodeName={node.name}
value={value}
showBorder={detailsItemId === node.name || isPopoverOpen}
showBorder={detailsItemId === node.id || isPopoverOpen}
/>
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { useUrlState } from '../../../../utils/use_url_state';

export const GET_DEFAULT_PROPERTIES: AssetDetailsFlyoutProperties = {
detailsItemId: null,
assetType: null,
};

const ASSET_DETAILS_FLYOUT_URL_STATE_KEY = 'assetDetailsFlyout';
Expand All @@ -35,6 +36,7 @@ export const useAssetDetailsFlyoutState = (): [

const AssetDetailsFlyoutStateRT = rt.type({
detailsItemId: rt.union([rt.string, rt.null]),
assetType: rt.union([rt.string, rt.null]),
});

export type AssetDetailsFlyoutState = rt.TypeOf<typeof AssetDetailsFlyoutStateRT>;
Expand Down

0 comments on commit df74eb6

Please sign in to comment.