Skip to content

Commit

Permalink
[Infra] Replacement of link-to links with infra locators (elastic#191578
Browse files Browse the repository at this point in the history
)

## Summary

Replacing `link-to` urls with infra locators, so that we can deprecate
`link-to` for infra.

### How to test

- Go to Infrastructure -> Inventory page.
- Choose either Hosts/Pods in the Show dropdown.
- Select List view instead of Default
- Click on an instance, select Metrics option on the popup

#### Expected Result

Should go to the assets detail page, for both Hosts (supported by new
assets details params) and Pods (not supported).

Closes elastic#176667

---------

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
  • Loading branch information
Bluefinger and elasticmachine committed Sep 9, 2024
1 parent f0164e7 commit 2f6be1b
Show file tree
Hide file tree
Showing 17 changed files with 269 additions and 117 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ import {
ALL_DATASETS_LOCATOR_ID,
} from '@kbn/deeplinks-observability/locators';
import { getLogsLocatorsFromUrlService } from '@kbn/logs-shared-plugin/common';
import {
ASSET_DETAILS_LOCATOR_ID,
type AssetDetailsLocatorParams,
} from '@kbn/observability-shared-plugin/common';
import { isJavaAgentName } from '../../../../../../common/agent_name';
import { SERVICE_NODE_NAME } from '../../../../../../common/es_fields/apm';
import { useApmPluginContext } from '../../../../../context/apm_plugin/use_apm_plugin_context';
Expand Down Expand Up @@ -55,6 +59,8 @@ export function InstanceActionsMenu({ serviceName, serviceNodeName, kuery, onClo
const allDatasetsLocator =
share.url.locators.get<AllDatasetsLocatorParams>(ALL_DATASETS_LOCATOR_ID)!;
const { nodeLogsLocator } = getLogsLocatorsFromUrlService(share.url);
const assetDetailsLocator =
share.url.locators.get<AssetDetailsLocatorParams>(ASSET_DETAILS_LOCATOR_ID);

if (isPending(status)) {
return (
Expand Down Expand Up @@ -95,6 +101,7 @@ export function InstanceActionsMenu({ serviceName, serviceNodeName, kuery, onClo
metricsHref,
allDatasetsLocator,
nodeLogsLocator,
assetDetailsLocator,
});

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import { AllDatasetsLocatorParams } from '@kbn/deeplinks-observability/locators'
import type { LocatorPublic } from '@kbn/share-plugin/public';
import { NodeLogsLocatorParams } from '@kbn/logs-shared-plugin/common';
import { findInventoryFields } from '@kbn/metrics-data-access-plugin/common';
import { type AssetDetailsLocator } from '@kbn/observability-shared-plugin/common';
import { APIReturnType } from '../../../../../services/rest/create_call_apm_api';
import { getInfraHref } from '../../../../shared/links/infra_link';
import {
Action,
getNonEmptySections,
Expand All @@ -25,14 +25,14 @@ type InstaceDetails =

function getInfraMetricsQuery(timestamp?: string) {
if (!timestamp) {
return { from: 0, to: 0 };
return undefined;
}
const timeInMilliseconds = new Date(timestamp).getTime();
const fiveMinutes = moment.duration(5, 'minutes').asMilliseconds();

return {
from: timeInMilliseconds - fiveMinutes,
to: timeInMilliseconds + fiveMinutes,
from: new Date(timeInMilliseconds - fiveMinutes).toISOString(),
to: new Date(timeInMilliseconds + fiveMinutes).toISOString(),
};
}

Expand All @@ -43,13 +43,15 @@ export function getMenuSections({
metricsHref,
allDatasetsLocator,
nodeLogsLocator,
assetDetailsLocator,
}: {
instanceDetails: InstaceDetails;
basePath: IBasePath;
onFilterByInstanceClick: () => void;
metricsHref: string;
allDatasetsLocator: LocatorPublic<AllDatasetsLocatorParams>;
nodeLogsLocator: LocatorPublic<NodeLogsLocatorParams>;
assetDetailsLocator?: AssetDetailsLocator;
}) {
const podId = instanceDetails.kubernetes?.pod?.uid;
const containerId = instanceDetails.container?.id;
Expand All @@ -70,6 +72,9 @@ export function getMenuSections({
time,
});

const hasPodLink = !!podId && !!assetDetailsLocator;
const hasContainerLink = !!containerId && !!assetDetailsLocator;

const podActions: Action[] = [
{
key: 'podLogs',
Expand All @@ -84,13 +89,14 @@ export function getMenuSections({
label: i18n.translate('xpack.apm.serviceOverview.instancesTable.actionMenus.podMetrics', {
defaultMessage: 'Pod metrics',
}),
href: getInfraHref({
app: 'metrics',
basePath,
path: `/link-to/pod-detail/${podId}`,
query: infraMetricsQuery,
}),
condition: !!podId,
href: hasPodLink
? assetDetailsLocator.getRedirectUrl({
assetId: podId,
assetType: 'pod',
assetDetails: { dateRange: infraMetricsQuery },
})
: undefined,
condition: hasPodLink,
},
];

Expand All @@ -109,13 +115,14 @@ export function getMenuSections({
'xpack.apm.serviceOverview.instancesTable.actionMenus.containerMetrics',
{ defaultMessage: 'Container metrics' }
),
href: getInfraHref({
app: 'metrics',
basePath,
path: `/link-to/container-detail/${containerId}`,
query: infraMetricsQuery,
}),
condition: !!containerId,
href: hasContainerLink
? assetDetailsLocator.getRedirectUrl({
assetId: containerId,
assetType: 'container',
assetDetails: { dateRange: infraMetricsQuery },
})
: undefined,
condition: hasContainerLink,
},
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@
*/

import { createMemoryHistory } from 'history';
import rison from '@kbn/rison';
import { IBasePath } from '@kbn/core/public';
import { Transaction } from '../../../../typings/es_schemas/ui/transaction';
import { getSections } from './sections';
import { apmRouter as apmRouterBase, ApmRouter } from '../../routing/apm_route_config';
import { logsLocatorsMock } from '../../../context/apm_plugin/mock_apm_plugin_context';
import { sharePluginMock } from '@kbn/share-plugin/public/mocks';
import {
AssetDetailsLocatorParams,
AssetDetailsLocator,
} from '@kbn/observability-shared-plugin/common';

const apmRouter = {
...apmRouterBase,
Expand All @@ -21,6 +26,15 @@ const apmRouter = {
const { nodeLogsLocator, traceLogsLocator } = logsLocatorsMock;
const uptimeLocator = sharePluginMock.createLocator();

const mockAssetDetailsLocator = {
getRedirectUrl: jest
.fn()
.mockImplementation(
({ assetId, assetType, assetDetails }: AssetDetailsLocatorParams) =>
`/node-mock/${assetType}/${assetId}?receivedParams=${rison.encodeUnknown(assetDetails)}`
),
} as unknown as jest.Mocked<AssetDetailsLocator>;

const expectLogsLocatorsToBeCalled = () => {
expect(nodeLogsLocator.getRedirectUrl).toBeCalledTimes(3);
expect(traceLogsLocator.getRedirectUrl).toBeCalledTimes(1);
Expand Down Expand Up @@ -69,6 +83,7 @@ describe('Transaction action menu', () => {
rangeTo: 'now',
environment: 'ENVIRONMENT_ALL',
dataViewId: 'apm_static_data_view_id_default',
assetDetailsLocator: mockAssetDetailsLocator,
})
).toEqual([
[
Expand Down Expand Up @@ -137,6 +152,7 @@ describe('Transaction action menu', () => {
rangeTo: 'now',
environment: 'ENVIRONMENT_ALL',
dataViewId: 'apm_static_data_view_id_default',
assetDetailsLocator: mockAssetDetailsLocator,
})
).toEqual([
[
Expand All @@ -153,7 +169,7 @@ describe('Transaction action menu', () => {
{
key: 'podMetrics',
label: 'Pod metrics',
href: 'some-basepath/app/metrics/link-to/pod-detail/123?from=1580986500000&to=1580987100000',
href: "/node-mock/pod/123?receivedParams=(dateRange:(from:'2020-02-06T10:55:00.000Z',to:'2020-02-06T11:05:00.000Z'))",
condition: true,
},
],
Expand Down Expand Up @@ -223,6 +239,7 @@ describe('Transaction action menu', () => {
rangeTo: 'now',
environment: 'ENVIRONMENT_ALL',
dataViewId: 'apm_static_data_view_id_default',
assetDetailsLocator: mockAssetDetailsLocator,
})
).toEqual([
[
Expand All @@ -239,7 +256,7 @@ describe('Transaction action menu', () => {
{
key: 'hostMetrics',
label: 'Host metrics',
href: 'some-basepath/app/metrics/link-to/host-detail/foo?from=1580986500000&to=1580987100000',
href: "/node-mock/host/foo?receivedParams=(dateRange:(from:'2020-02-06T10:55:00.000Z',to:'2020-02-06T11:05:00.000Z'))",
condition: true,
},
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ import moment from 'moment';
import type { getLogsLocatorsFromUrlService } from '@kbn/logs-shared-plugin/common';
import { findInventoryFields } from '@kbn/metrics-data-access-plugin/common';
import type { ProfilingLocators } from '@kbn/observability-shared-plugin/public';
import type { AssetDetailsLocator } from '@kbn/observability-shared-plugin/common';
import { LocatorPublic } from '@kbn/share-plugin/common';
import { SerializableRecord } from '@kbn/utility-types';
import { Environment } from '../../../../common/environment_rt';
import type { Transaction } from '../../../../typings/es_schemas/ui/transaction';
import { getDiscoverHref } from '../links/discover_links/discover_link';
import { getDiscoverQuery } from '../links/discover_links/discover_transaction_link';
import { getInfraHref } from '../links/infra_link';
import { SectionRecord, getNonEmptySections, Action } from './sections_helper';
import { HOST_NAME, TRACE_ID } from '../../../../common/es_fields/apm';
import { ApmRouter } from '../../routing/apm_route_config';
Expand All @@ -29,8 +29,8 @@ function getInfraMetricsQuery(transaction: Transaction) {
const fiveMinutes = moment.duration(5, 'minutes').asMilliseconds();

return {
from: timestamp - fiveMinutes,
to: timestamp + fiveMinutes,
from: new Date(timestamp - fiveMinutes).toISOString(),
to: new Date(timestamp + fiveMinutes).toISOString(),
};
}

Expand All @@ -47,6 +47,7 @@ export const getSections = ({
environment,
logsLocators,
dataViewId,
assetDetailsLocator,
}: {
transaction?: Transaction;
basePath: IBasePath;
Expand All @@ -60,6 +61,7 @@ export const getSections = ({
environment: Environment;
logsLocators: ReturnType<typeof getLogsLocatorsFromUrlService>;
dataViewId?: string;
assetDetailsLocator?: AssetDetailsLocator;
}) => {
if (!transaction) return [];

Expand Down Expand Up @@ -103,6 +105,10 @@ export const getSections = ({
time,
});

const hasPodLink = !!podId && infraLinksAvailable && !!assetDetailsLocator;
const hasContainerLink = !!containerId && infraLinksAvailable && !!assetDetailsLocator;
const hasHostLink = !!hostName && infraLinksAvailable && !!assetDetailsLocator;

const podActions: Action[] = [
{
key: 'podLogs',
Expand All @@ -117,13 +123,16 @@ export const getSections = ({
label: i18n.translate('xpack.apm.transactionActionMenu.showPodMetricsLinkLabel', {
defaultMessage: 'Pod metrics',
}),
href: getInfraHref({
app: 'metrics',
basePath,
path: `/link-to/pod-detail/${podId}`,
query: infraMetricsQuery,
}),
condition: !!podId && infraLinksAvailable,
href: hasPodLink
? assetDetailsLocator.getRedirectUrl({
assetId: podId,
assetType: 'pod',
assetDetails: {
dateRange: infraMetricsQuery,
},
})
: undefined,
condition: hasPodLink,
},
];

Expand All @@ -141,13 +150,14 @@ export const getSections = ({
label: i18n.translate('xpack.apm.transactionActionMenu.showContainerMetricsLinkLabel', {
defaultMessage: 'Container metrics',
}),
href: getInfraHref({
app: 'metrics',
basePath,
path: `/link-to/container-detail/${containerId}`,
query: infraMetricsQuery,
}),
condition: !!containerId && infraLinksAvailable,
href: hasContainerLink
? assetDetailsLocator.getRedirectUrl({
assetId: containerId,
assetType: 'container',
assetDetails: { dateRange: infraMetricsQuery },
})
: undefined,
condition: hasContainerLink,
},
];

Expand All @@ -165,13 +175,16 @@ export const getSections = ({
label: i18n.translate('xpack.apm.transactionActionMenu.showHostMetricsLinkLabel', {
defaultMessage: 'Host metrics',
}),
href: getInfraHref({
app: 'metrics',
basePath,
path: `/link-to/host-detail/${hostName}`,
query: infraMetricsQuery,
}),
condition: !!hostName && infraLinksAvailable,
href: hasHostLink
? assetDetailsLocator.getRedirectUrl({
assetId: hostName,
assetType: 'host',
assetDetails: {
dateRange: infraMetricsQuery,
},
})
: undefined,
condition: hasHostLink,
},
{
key: 'hostProfilingFlamegraph',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import React from 'react';
import { MemoryRouter } from 'react-router-dom';
import { createMemoryHistory } from 'history';
import { License } from '@kbn/licensing-plugin/common/license';
import rison from '@kbn/rison';
import {
LOGS_LOCATOR_ID,
NODE_LOGS_LOCATOR_ID,
Expand All @@ -32,6 +33,20 @@ import * as useAdHocApmDataView from '../../../hooks/use_adhoc_apm_data_view';
import { useProfilingIntegrationSetting } from '../../../hooks/use_profiling_integration_setting';
import { uptimeOverviewLocatorID } from '@kbn/observability-plugin/common';
import { sharePluginMock } from '@kbn/share-plugin/public/mocks';
import {
AssetDetailsLocator,
AssetDetailsLocatorParams,
ASSET_DETAILS_LOCATOR_ID,
} from '@kbn/observability-shared-plugin/common';

const mockAssetDetailsLocator = {
getRedirectUrl: jest
.fn()
.mockImplementation(
({ assetId, assetType, assetDetails }: AssetDetailsLocatorParams) =>
`/node-mock/${assetType}/${assetId}?receivedParams=${rison.encodeUnknown(assetDetails)}`
),
} as unknown as jest.Mocked<AssetDetailsLocator>;

const apmContextMock = {
...mockApmPluginContextValue,
Expand Down Expand Up @@ -63,6 +78,9 @@ const apmContextMock = {
),
};
}
if (id === ASSET_DETAILS_LOCATOR_ID) {
return mockAssetDetailsLocator;
}
},
},
},
Expand Down Expand Up @@ -185,7 +203,7 @@ describe('TransactionActionMenu ', () => {
const { getByText } = await renderTransaction(Transactions.transactionWithKubernetesData);

expect((getByText('Pod metrics').parentElement as HTMLAnchorElement).href).toEqual(
'http://localhost/basepath/app/metrics/link-to/pod-detail/pod123456abcdef?from=1545091770952&to=1545092370952'
'http://localhost/node-mock/pod/pod123456abcdef?receivedParams=(dateRange:(from:%272018-12-18T00:09:30.952Z%27,to:%272018-12-18T00:19:30.952Z%27))'
);
});
});
Expand Down Expand Up @@ -215,7 +233,7 @@ describe('TransactionActionMenu ', () => {
const { getByText } = await renderTransaction(Transactions.transactionWithContainerData);

expect((getByText('Container metrics').parentElement as HTMLAnchorElement).href).toEqual(
'http://localhost/basepath/app/metrics/link-to/container-detail/container123456abcdef?from=1545091770952&to=1545092370952'
'http://localhost/node-mock/container/container123456abcdef?receivedParams=(dateRange:(from:%272018-12-18T00:09:30.952Z%27,to:%272018-12-18T00:19:30.952Z%27))'
);
});
});
Expand Down Expand Up @@ -245,7 +263,7 @@ describe('TransactionActionMenu ', () => {
const { getByText } = await renderTransaction(Transactions.transactionWithHostData);

expect((getByText('Host metrics').parentElement as HTMLAnchorElement).href).toEqual(
'http://localhost/basepath/app/metrics/link-to/host-detail/227453131a17?from=1545091770952&to=1545092370952'
'http://localhost/node-mock/host/227453131a17?receivedParams=(dateRange:(from:%272018-12-18T00:09:30.952Z%27,to:%272018-12-18T00:19:30.952Z%27))'
);
});
});
Expand Down
Loading

0 comments on commit 2f6be1b

Please sign in to comment.