mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 01:13:23 -04:00
[Infrastructure UI] Hosts view: Add links to apm and uptime for a single host (#154269)
Closes #150985 ## Summary This PR adds links to APM Traces and Uptime. <img width="1909" alt="image" src="https://user-images.githubusercontent.com/14139027/229580612-a3d0c03a-4f68-4b09-b333-ffa79c8454e6.png"> # Testing 1. Open Hosts view 2. Click on the button to open the flyout for a single host - Click on the APM traces link and verify the query parameters are correct - Click on the uptime link and verify the query parameters are correct https://user-images.githubusercontent.com/14139027/229581672-3c50ea55-e834-4431-aac6-3ed3ff9f96cc.mov --------- Co-authored-by: Carlos Crespo <crespocarlos@users.noreply.github.com>
This commit is contained in:
parent
b8409c9173
commit
8c2ff54c96
7 changed files with 166 additions and 6 deletions
|
@ -6,13 +6,26 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { EuiFlyout, EuiFlyoutHeader, EuiTitle, EuiFlyoutBody } from '@elastic/eui';
|
||||
import { EuiSpacer, EuiTabs, EuiTab } from '@elastic/eui';
|
||||
import {
|
||||
EuiFlyout,
|
||||
EuiFlyoutHeader,
|
||||
EuiTitle,
|
||||
EuiFlyoutBody,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiTab,
|
||||
EuiSpacer,
|
||||
EuiTabs,
|
||||
useEuiTheme,
|
||||
} from '@elastic/eui';
|
||||
import { css } from '@emotion/react';
|
||||
import { useUnifiedSearchContext } from '../../hooks/use_unified_search';
|
||||
import { LinkToUptime } from './links/link_to_uptime';
|
||||
import { LinkToApmServices } from './links/link_to_apm_services';
|
||||
import { useLazyRef } from '../../../../../hooks/use_lazy_ref';
|
||||
import { metadataTab } from './metadata';
|
||||
import type { InventoryItemType } from '../../../../../../common/inventory_models/types';
|
||||
import type { HostNodeRow } from '../../hooks/use_hosts_table';
|
||||
import { useUnifiedSearchContext } from '../../hooks/use_unified_search';
|
||||
import { processesTab } from './processes';
|
||||
import { Metadata } from './metadata/metadata';
|
||||
import { Processes } from './processes/processes';
|
||||
|
@ -28,6 +41,7 @@ const NODE_TYPE = 'host' as InventoryItemType;
|
|||
|
||||
export const Flyout = ({ node, closeFlyout }: Props) => {
|
||||
const { getDateRangeAsTimestamp } = useUnifiedSearchContext();
|
||||
const { euiTheme } = useEuiTheme();
|
||||
|
||||
const currentTimeRange = {
|
||||
...getDateRangeAsTimestamp(),
|
||||
|
@ -57,9 +71,24 @@ export const Flyout = ({ node, closeFlyout }: Props) => {
|
|||
return (
|
||||
<EuiFlyout onClose={closeFlyout} ownFocus={false}>
|
||||
<EuiFlyoutHeader hasBorder>
|
||||
<EuiTitle size="xs">
|
||||
<h2>{node.name}</h2>
|
||||
</EuiTitle>
|
||||
<EuiFlexGroup justifyContent="spaceBetween">
|
||||
<EuiFlexItem>
|
||||
<EuiTitle size="xs">
|
||||
<h2>{node.name}</h2>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<LinkToApmServices hostName={node.name} apmField={'host.hostname'} />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem
|
||||
grow={false}
|
||||
css={css`
|
||||
margin-right: ${euiTheme.size.l};
|
||||
`}
|
||||
>
|
||||
<LinkToUptime nodeType={NODE_TYPE} node={node} />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiTabs style={{ marginBottom: '-25px' }} size="s">
|
||||
{tabEntries}
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { stringify } from 'querystring';
|
||||
import { encode } from '@kbn/rison';
|
||||
import { css } from '@emotion/react';
|
||||
import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app';
|
||||
import { EuiIcon, EuiLink, useEuiTheme } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { useKibanaContextForPlugin } from '../../../../../../hooks/use_kibana';
|
||||
|
||||
interface LinkToApmServicesProps {
|
||||
hostName: string;
|
||||
apmField: string;
|
||||
}
|
||||
|
||||
export const LinkToApmServices = ({ hostName, apmField }: LinkToApmServicesProps) => {
|
||||
const { services } = useKibanaContextForPlugin();
|
||||
const { http } = services;
|
||||
const { euiTheme } = useEuiTheme();
|
||||
|
||||
const queryString = new URLSearchParams(
|
||||
encode(
|
||||
stringify({
|
||||
kuery: `${apmField}:"${hostName}"`,
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
const linkToApmServices = http.basePath.prepend(`/app/apm/services?${queryString}`);
|
||||
|
||||
return (
|
||||
<RedirectAppLinks coreStart={services}>
|
||||
<EuiLink href={linkToApmServices} data-test-subj="hostsView-flyout-apm-services-link">
|
||||
<EuiIcon
|
||||
type="popout"
|
||||
css={css`
|
||||
margin-right: ${euiTheme.size.xs};
|
||||
`}
|
||||
/>
|
||||
<FormattedMessage
|
||||
id="xpack.infra.hostsViewPage.flyout.apmServicesLinkLabel"
|
||||
defaultMessage="APM Services"
|
||||
/>
|
||||
</EuiLink>
|
||||
</RedirectAppLinks>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { EuiLink, EuiIcon, useEuiTheme } from '@elastic/eui';
|
||||
import { css } from '@emotion/react';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { uptimeOverviewLocatorID } from '@kbn/observability-plugin/public';
|
||||
import { useKibanaContextForPlugin } from '../../../../../../hooks/use_kibana';
|
||||
import type { InventoryItemType } from '../../../../../../../common/inventory_models/types';
|
||||
import type { HostNodeRow } from '../../../hooks/use_hosts_table';
|
||||
|
||||
interface LinkTUptimeProps {
|
||||
nodeType: InventoryItemType;
|
||||
node: HostNodeRow;
|
||||
}
|
||||
|
||||
export const LinkToUptime = ({ nodeType, node }: LinkTUptimeProps) => {
|
||||
const { share } = useKibanaContextForPlugin().services;
|
||||
const { euiTheme } = useEuiTheme();
|
||||
|
||||
return (
|
||||
<EuiLink
|
||||
data-test-subj="hostsView-flyout-uptime-link"
|
||||
onClick={() =>
|
||||
share.url.locators
|
||||
.get(uptimeOverviewLocatorID)!
|
||||
.navigate({ [nodeType]: node.name, ip: node.ip })
|
||||
}
|
||||
>
|
||||
<EuiIcon
|
||||
type="popout"
|
||||
css={css`
|
||||
margin-right: ${euiTheme.size.xs};
|
||||
`}
|
||||
/>
|
||||
<FormattedMessage
|
||||
id="xpack.infra.hostsViewPage.flyout.uptimeLinkLabel"
|
||||
defaultMessage="Uptime"
|
||||
/>
|
||||
</EuiLink>
|
||||
);
|
||||
};
|
|
@ -73,6 +73,7 @@ describe('useHostTable hook', () => {
|
|||
{
|
||||
name: 'host-0',
|
||||
os: '-',
|
||||
ip: '',
|
||||
id: 'host-0-0',
|
||||
title: {
|
||||
cloudProvider: 'aws',
|
||||
|
@ -103,6 +104,7 @@ describe('useHostTable hook', () => {
|
|||
{
|
||||
name: 'host-1',
|
||||
os: 'macOS',
|
||||
ip: '243.86.94.22',
|
||||
id: 'host-1-1',
|
||||
title: {
|
||||
cloudProvider: null,
|
||||
|
|
|
@ -31,6 +31,7 @@ type HostMetrics = Record<HostMetric, SnapshotNodeMetric>;
|
|||
|
||||
export interface HostNodeRow extends HostMetrics {
|
||||
os?: string | null;
|
||||
ip?: string | null;
|
||||
servicesOnHost?: number | null;
|
||||
title: { name: string; cloudProvider?: CloudProvider | null };
|
||||
name: string;
|
||||
|
@ -53,6 +54,7 @@ const buildItemsList = (nodes: SnapshotNode[]) => {
|
|||
id: `${name}-${index}`,
|
||||
name,
|
||||
os: path.at(-1)?.os ?? '-',
|
||||
ip: path.at(-1)?.ip ?? '',
|
||||
title: {
|
||||
name,
|
||||
cloudProvider: path.at(-1)?.cloudProvider ?? null,
|
||||
|
|
|
@ -244,6 +244,26 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
expect(metadataTab).to.contain('Metadata');
|
||||
});
|
||||
|
||||
it('should navigate to Uptime after click', async () => {
|
||||
await pageObjects.infraHostsView.clickFlyoutUptimeLink();
|
||||
await pageObjects.infraHome.waitForLoading();
|
||||
const url = await browser.getCurrentUrl();
|
||||
expect(url).to.contain(
|
||||
'app/uptime/?search=host.name%3A%20%22Jennys-MBP.fritz.box%22%20OR%20host.ip%3A%20%22192.168.1.79%22'
|
||||
);
|
||||
await browser.goBack();
|
||||
await pageObjects.infraHome.waitForLoading();
|
||||
});
|
||||
|
||||
it('should navigate to APM services after click', async () => {
|
||||
await pageObjects.infraHostsView.clickFlyoutApmServicesLink();
|
||||
await pageObjects.infraHome.waitForLoading();
|
||||
const url = await browser.getCurrentUrl();
|
||||
expect(url).to.contain('app/apm/services?kuery=host.hostname%3A%22Jennys-MBP.fritz.box%22');
|
||||
await browser.goBack();
|
||||
await pageObjects.infraHome.waitForLoading();
|
||||
});
|
||||
|
||||
describe('should render processes tab', async () => {
|
||||
const processTitles = [
|
||||
'Total processes',
|
||||
|
|
|
@ -36,6 +36,14 @@ export function InfraHostsViewProvider({ getService }: FtrProviderContext) {
|
|||
return testSubjects.click('infraProcessRowButton');
|
||||
},
|
||||
|
||||
async clickFlyoutUptimeLink() {
|
||||
return testSubjects.click('hostsView-flyout-uptime-link');
|
||||
},
|
||||
|
||||
async clickFlyoutApmServicesLink() {
|
||||
return testSubjects.click('hostsView-flyout-apm-services-link');
|
||||
},
|
||||
|
||||
async getHostsLandingPageDisabled() {
|
||||
const container = await testSubjects.find('hostView-no-enable-access');
|
||||
const containerText = await container.getVisibleText();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue