Skip to content

Commit

Permalink
[Infra UI] Implement telemetry for the asset details flyout (#163078)
Browse files Browse the repository at this point in the history
## Summary

This PR adds proper `data-test-subj` attributes to the Asset Details
component and adds a new custom telemetry event


<img width="623" alt="image"
src="https://github.com/elastic/kibana/assets/2767137/0e637e1a-4447-43c7-9e19-86974dbb13c0">

<img width="623" alt="image"
src="https://github.com/elastic/kibana/assets/2767137/881cd52d-8c94-49bb-a6cb-781293ec2ecb">



Besides that, I've renamed 2 props,`node` -> `asset` and `nodeType` ->
`assetType`, to make naming consistent with what we're naming these
attributes across asset-related stuff.


### How to test

- Setup a local Kibana instance
- Navigate to `Infrastructure` > `Hosts`
- Open the flyout
- Upon opening, an event called `Asset Details Flyout Viewed` should be
present in `kibana-browser` request
  - Click through the flyout and check the `kibana-browser` requests
- All automatic events in the flyout should contain the
`data-component-name` and `data-asset-type` attributes

---------

Co-authored-by: Kibana Machine <[email protected]>
  • Loading branch information
crespocarlos and kibanamachine authored Aug 10, 2023
1 parent 7353dc6 commit 4a56d20
Show file tree
Hide file tree
Showing 42 changed files with 304 additions and 196 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type { DataViewField, DataView } from '@kbn/data-views-plugin/common';
import { UseAssetDetailsStateProps } from '../../../hooks/use_asset_details_state';

export const assetDetailsState: UseAssetDetailsStateProps['state'] = {
node: {
asset: {
name: 'host1',
id: 'host1-macOS',
ip: '192.168.0.1',
Expand All @@ -29,7 +29,7 @@ export const assetDetailsState: UseAssetDetailsStateProps['state'] = {
showActionsColumn: true,
},
},
nodeType: 'host',
assetType: 'host',
dateRange: {
from: '2023-04-09T11:07:49Z',
to: '2023-04-09T11:23:49Z',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,42 +22,36 @@ const tabs: Tab[] = [
name: i18n.translate('xpack.infra.nodeDetails.tabs.overview.title', {
defaultMessage: 'Overview',
}),
'data-test-subj': 'hostsView-flyout-tabs-overview',
},
{
id: FlyoutTabIds.LOGS,
name: i18n.translate('xpack.infra.nodeDetails.tabs.logs', {
defaultMessage: 'Logs',
}),
'data-test-subj': 'hostsView-flyout-tabs-logs',
},
{
id: FlyoutTabIds.METADATA,
name: i18n.translate('xpack.infra.metrics.nodeDetails.tabs.metadata', {
defaultMessage: 'Metadata',
}),
'data-test-subj': 'hostsView-flyout-tabs-metadata',
},
{
id: FlyoutTabIds.PROCESSES,
name: i18n.translate('xpack.infra.metrics.nodeDetails.tabs.processes', {
defaultMessage: 'Processes',
}),
'data-test-subj': 'hostsView-flyout-tabs-processes',
},
{
id: FlyoutTabIds.ANOMALIES,
name: i18n.translate('xpack.infra.nodeDetails.tabs.anomalies', {
defaultMessage: 'Anomalies',
}),
'data-test-subj': 'hostsView-flyout-tabs-anomalies',
},
{
id: FlyoutTabIds.LINK_TO_APM,
name: i18n.translate('xpack.infra.infra.nodeDetails.apmTabLabel', {
defaultMessage: 'APM',
}),
'data-test-subj': 'hostsView-flyout-apm-link',
},
];

Expand Down Expand Up @@ -96,7 +90,7 @@ const FlyoutTemplate: Story<AssetDetailsProps> = (args) => {
Open flyout
</EuiButton>
<div hidden={!isOpen}>
{isOpen && <AssetDetails {...args} renderMode={{ showInFlyout: true, closeFlyout }} />}
{isOpen && <AssetDetails {...args} renderMode={{ mode: 'flyout', closeFlyout }} />}
</div>
</div>
);
Expand All @@ -107,7 +101,7 @@ export const Page = PageTemplate.bind({});
export const Flyout = FlyoutTemplate.bind({});
Flyout.args = {
renderMode: {
showInFlyout: true,
mode: 'flyout',
closeFlyout: () => {},
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@

import React from 'react';
import { EuiFlyout, EuiFlyoutHeader, EuiFlyoutBody } from '@elastic/eui';
import useEffectOnce from 'react-use/lib/useEffectOnce';
import type { AssetDetailsProps, RenderMode } from './types';
import { Content } from './content/content';
import { Header } from './header/header';
import { TabSwitcherProvider } from './hooks/use_tab_switcher';
import { AssetDetailsStateProvider } from './hooks/use_asset_details_state';
import { TabSwitcherProvider, useTabSwitcherContext } from './hooks/use_tab_switcher';
import {
AssetDetailsStateProvider,
useAssetDetailsStateContext,
} from './hooks/use_asset_details_state';
import { useKibanaContextForPlugin } from '../../hooks/use_kibana';
import { ASSET_DETAILS_FLYOUT_COMPONENT_NAME } from './constants';

interface ContentTemplateProps {
header: React.ReactElement;
Expand All @@ -20,8 +26,27 @@ interface ContentTemplateProps {
}

const ContentTemplate = ({ header, body, renderMode }: ContentTemplateProps) => {
return renderMode.showInFlyout ? (
<EuiFlyout onClose={renderMode.closeFlyout} ownFocus={false}>
const { assetType } = useAssetDetailsStateContext();
const { initialActiveTabId } = useTabSwitcherContext();
const {
services: { telemetry },
} = useKibanaContextForPlugin();

useEffectOnce(() => {
telemetry.reportAssetDetailsFlyoutViewed({
componentName: ASSET_DETAILS_FLYOUT_COMPONENT_NAME,
assetType,
tabId: initialActiveTabId,
});
});

return renderMode.mode === 'flyout' ? (
<EuiFlyout
onClose={renderMode.closeFlyout}
ownFocus={false}
data-component-name={ASSET_DETAILS_FLYOUT_COMPONENT_NAME}
data-asset-type={assetType}
>
<EuiFlyoutHeader hasBorder>{header}</EuiFlyoutHeader>
<EuiFlyoutBody>{body}</EuiFlyoutBody>
</EuiFlyout>
Expand All @@ -34,25 +59,27 @@ const ContentTemplate = ({ header, body, renderMode }: ContentTemplateProps) =>
};

export const AssetDetails = ({
node,
asset,
dateRange,
activeTabId,
overrides,
onTabsStateChange,
tabs = [],
links = [],
nodeType = 'host',
assetType = 'host',
renderMode = {
showInFlyout: false,
mode: 'page',
},
}: AssetDetailsProps) => {
return (
<AssetDetailsStateProvider state={{ node, nodeType, overrides, onTabsStateChange, dateRange }}>
<AssetDetailsStateProvider
state={{ asset, assetType, overrides, onTabsStateChange, dateRange }}
>
<TabSwitcherProvider
initialActiveTabId={tabs.length > 0 ? activeTabId ?? tabs[0].id : undefined}
>
<ContentTemplate
header={<Header compact={renderMode.showInFlyout} tabs={tabs} links={links} />}
header={<Header compact={renderMode.mode === 'flyout'} tabs={tabs} links={links} />}
body={<Content />}
renderMode={renderMode}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ export class AssetDetailsEmbeddable extends Embeddable<AssetDetailsEmbeddableInp
<LazyAssetDetailsWrapper
activeTabId={this.input.activeTabId}
dateRange={this.input.dateRange}
node={this.input.node}
nodeType={this.input.nodeType}
asset={this.input.asset}
assetType={this.input.assetType}
overrides={this.input.overrides}
renderMode={this.input.renderMode}
tabs={this.input.tabs}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const AlertsTooltipContent = React.memo(() => {
values={{
documentation: (
<EuiLink
data-test-subj="assetDetailsTooltipDocumentationLink"
data-test-subj="infraAssetDetailsTooltipDocumentationLink"
href={ALERTS_DOC_HREF}
target="_blank"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ export const ExpandableContent = (props: ExpandableContentProps) => {
{shouldShowMore && (
<>
{' ... '}
<EuiLink data-test-subj="infraExpandableContentCountMoreLink" onClick={toggle}>
<EuiLink
data-test-subj="infraAssetDetailsExpandableContentCountMoreLink"
onClick={toggle}
>
<FormattedMessage
id="xpack.infra.nodeDetails.tabs.metadata.seeMore"
defaultMessage="+{count} more"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
* 2.0.
*/

export const ASSET_DETAILS_FLYOUT_COMPONENT_NAME = 'infraAssetDetailsFlyout';
export const METRIC_CHART_HEIGHT = 300;
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
useEuiMinBreakpoint,
} from '@elastic/eui';
import { css } from '@emotion/react';
import { capitalize } from 'lodash';
import { AssetDetailsProps, FlyoutTabIds, LinkOptions, Tab, TabIds } from '../types';
import {
LinkToApmServices,
Expand All @@ -36,7 +37,7 @@ type Props = Pick<AssetDetailsProps, 'links' | 'tabs'> & {
const APM_FIELD = 'host.hostname';

export const Header = ({ tabs = [], links = [], compact }: Props) => {
const { node, nodeType, overrides, dateRange: timeRange } = useAssetDetailsStateContext();
const { asset, assetType, overrides, dateRange: timeRange } = useAssetDetailsStateContext();
const { euiTheme } = useEuiTheme();
const { showTab, activeTabId } = useTabSwitcherContext();

Expand All @@ -46,23 +47,23 @@ export const Header = ({ tabs = [], links = [], compact }: Props) => {

const tabLinkComponents = {
[FlyoutTabIds.LINK_TO_APM]: (tab: Tab) => (
<TabToApmTraces nodeName={node.name} apmField={APM_FIELD} {...tab} />
<TabToApmTraces assetName={asset.name} apmField={APM_FIELD} {...tab} />
),
[FlyoutTabIds.LINK_TO_UPTIME]: (tab: Tab) => (
<TabToUptime nodeName={node.name} nodeType={nodeType} nodeIp={node.ip} {...tab} />
<TabToUptime assetName={asset.name} assetType={assetType} nodeIp={asset.ip} {...tab} />
),
};

const topCornerLinkComponents: Record<LinkOptions, JSX.Element> = {
nodeDetails: (
<LinkToNodeDetails
nodeName={node.name}
nodeType={nodeType}
assetName={asset.name}
assetType={assetType}
currentTimestamp={toTimestampRange(timeRange).to}
/>
),
alertRule: <LinkToAlertsRule onClick={overrides?.alertRule?.onCreateRuleClick} />,
apmServices: <LinkToApmServices nodeName={node.name} apmField={APM_FIELD} />,
apmServices: <LinkToApmServices assetName={asset.name} apmField={APM_FIELD} />,
};

const tabEntries = tabs.map(({ name, ...tab }) => {
Expand All @@ -77,6 +78,7 @@ export const Header = ({ tabs = [], links = [], compact }: Props) => {
return (
<EuiTab
{...tab}
data-test-subj={`infraAssetDetails${capitalize(tab.id)}Tab`}
key={tab.id}
onClick={() => onTabClick(tab.id)}
isSelected={tab.id === activeTabId}
Expand All @@ -102,7 +104,7 @@ export const Header = ({ tabs = [], links = [], compact }: Props) => {
`}
>
<EuiTitle size={compact ? 'xs' : 'm'}>
{compact ? <h4>{node.name}</h4> : <h1>{node.name}</h1>}
{compact ? <h4>{asset.name}</h4> : <h1>{asset.name}</h1>}
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ const DEFAULT_DATE_RANGE = {
export interface UseAssetDetailsStateProps {
state: Pick<
AssetDetailsProps,
'node' | 'nodeType' | 'overrides' | 'dateRange' | 'onTabsStateChange'
'asset' | 'assetType' | 'overrides' | 'dateRange' | 'onTabsStateChange'
>;
}

export function useAssetDetailsState({ state }: UseAssetDetailsStateProps) {
const { node, nodeType, dateRange: rawDateRange, onTabsStateChange, overrides } = state;
const { asset, assetType, dateRange: rawDateRange, onTabsStateChange, overrides } = state;

const dateRange = useMemo(() => {
const { from = DEFAULT_DATE_RANGE.from, to = DEFAULT_DATE_RANGE.to } =
Expand All @@ -36,8 +36,8 @@ export function useAssetDetailsState({ state }: UseAssetDetailsStateProps) {
const dateRangeTs = toTimestampRange(dateRange);

return {
node,
nodeType,
asset,
assetType,
dateRange,
dateRangeTs,
onTabsStateChange,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export function useTabSwitcher({ initialActiveTabId }: TabSwitcherParams) {
};

return {
initialActiveTabId,
activeTabId,
renderedTabsSet,
showTab,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export interface LinkToAlertsRuleProps {
export const LinkToAlertsRule = ({ onClick }: LinkToAlertsRuleProps) => {
return (
<EuiButtonEmpty
data-test-subj="infraNodeContextPopoverCreateInventoryRuleButton"
data-test-subj="infraAssetDetailsCreateAlertsRuleButton"
onClick={onClick}
size="xs"
iconSide="left"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,18 @@ import { ALERTS_PATH } from '../../../common/alerts/constants';
import { useKibanaContextForPlugin } from '../../../hooks/use_kibana';

export interface LinkToAlertsPageProps {
nodeName: string;
queryField: string;
assetName: string;
dateRange: TimeRange;
queryField: string;
}

export const LinkToAlertsPage = ({ nodeName, queryField, dateRange }: LinkToAlertsPageProps) => {
export const LinkToAlertsPage = ({ assetName, queryField, dateRange }: LinkToAlertsPageProps) => {
const { services } = useKibanaContextForPlugin();
const { http } = services;

const linkToAlertsPage = http.basePath.prepend(
`${ALERTS_PATH}?_a=${encode({
kuery: `${queryField}:"${nodeName}"`,
kuery: `${queryField}:"${assetName}"`,
rangeFrom: dateRange.from,
rangeTo: dateRange.to,
status: 'all',
Expand All @@ -35,7 +35,7 @@ export const LinkToAlertsPage = ({ nodeName, queryField, dateRange }: LinkToAler
return (
<RedirectAppLinks coreStart={services}>
<EuiButtonEmpty
data-test-subj="assetDetails-flyout-alerts-link"
data-test-subj="infraAssetDetailsAlertsShowAllButton"
size="xs"
iconSide="right"
iconType="sortRight"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,18 @@ import { EuiButtonEmpty } from '@elastic/eui';
import { useKibanaContextForPlugin } from '../../../hooks/use_kibana';

export interface LinkToApmServicesProps {
nodeName: string;
assetName: string;
apmField: string;
}

export const LinkToApmServices = ({ nodeName, apmField }: LinkToApmServicesProps) => {
export const LinkToApmServices = ({ assetName, apmField }: LinkToApmServicesProps) => {
const { services } = useKibanaContextForPlugin();
const { http } = services;

const queryString = new URLSearchParams(
encode(
stringify({
kuery: `${apmField}:"${nodeName}"`,
kuery: `${apmField}:"${assetName}"`,
})
)
);
Expand All @@ -34,7 +34,7 @@ export const LinkToApmServices = ({ nodeName, apmField }: LinkToApmServicesProps
return (
<RedirectAppLinks coreStart={services}>
<EuiButtonEmpty
data-test-subj="hostsView-flyout-apm-services-link"
data-test-subj="infraAssetDetailsViewAPMServicesButton"
size="xs"
flush="both"
href={linkToApmServices}
Expand Down
Loading

0 comments on commit 4a56d20

Please sign in to comment.