Skip to content

Commit 84e1af4

Browse files
[APM] Add link-to/transaction route (#101731) (#101754)
Co-authored-by: Dario Gieselaar <dario.gieselaar@elastic.co>
1 parent 2098aec commit 84e1af4

File tree

4 files changed

+98
-6
lines changed

4 files changed

+98
-6
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import { EuiEmptyPrompt } from '@elastic/eui';
9+
import React from 'react';
10+
import { Redirect, RouteComponentProps } from 'react-router-dom';
11+
import { euiStyled } from '../../../../../../../src/plugins/kibana_react/common';
12+
import { FETCH_STATUS, useFetcher } from '../../../hooks/use_fetcher';
13+
import { useUrlParams } from '../../../context/url_params_context/use_url_params';
14+
import { getRedirectToTransactionDetailPageUrl } from '../TraceLink/get_redirect_to_transaction_detail_page_url';
15+
16+
const CentralizedContainer = euiStyled.div`
17+
height: 100%;
18+
display: flex;
19+
`;
20+
21+
export function TransactionLink({
22+
match,
23+
}: RouteComponentProps<{ transactionId: string }>) {
24+
const { transactionId } = match.params;
25+
const { urlParams } = useUrlParams();
26+
const { rangeFrom, rangeTo } = urlParams;
27+
28+
const { data = { transaction: null }, status } = useFetcher(
29+
(callApmApi) => {
30+
if (transactionId) {
31+
return callApmApi({
32+
endpoint: 'GET /api/apm/transactions/{transactionId}',
33+
params: {
34+
path: {
35+
transactionId,
36+
},
37+
},
38+
});
39+
}
40+
},
41+
[transactionId]
42+
);
43+
if (transactionId && status === FETCH_STATUS.SUCCESS) {
44+
if (data.transaction) {
45+
return (
46+
<Redirect
47+
to={getRedirectToTransactionDetailPageUrl({
48+
transaction: data.transaction,
49+
rangeFrom,
50+
rangeTo,
51+
})}
52+
/>
53+
);
54+
}
55+
56+
return <CentralizedContainer />;
57+
}
58+
59+
return (
60+
<CentralizedContainer>
61+
<EuiEmptyPrompt
62+
iconType="apmTrace"
63+
title={<h2>Fetching transaction...</h2>}
64+
/>
65+
</CentralizedContainer>
66+
);
67+
}

x-pack/plugins/apm/public/components/routing/apm_route_config.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { AnomalyDetection } from '../app/Settings/anomaly_detection';
2020
import { ApmIndices } from '../app/Settings/ApmIndices';
2121
import { CustomizeUI } from '../app/Settings/CustomizeUI';
2222
import { TraceLink } from '../app/TraceLink';
23+
import { TransactionLink } from '../app/transaction_link';
2324
import { TransactionDetails } from '../app/transaction_details';
2425
import { enableServiceOverview } from '../../../common/ui_settings_keys';
2526
import { redirectTo } from './redirect_to';
@@ -510,6 +511,12 @@ export const apmRouteConfig: APMRouteDefinition[] = [
510511
component: TraceLink,
511512
breadcrumb: null,
512513
},
514+
{
515+
exact: true,
516+
path: '/link-to/transaction/:transactionId',
517+
component: TransactionLink,
518+
breadcrumb: null,
519+
},
513520
];
514521

515522
function RedirectToDefaultServiceRouteView(

x-pack/plugins/apm/server/lib/transactions/get_transaction/index.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ export function getTransaction({
2121
setup,
2222
}: {
2323
transactionId: string;
24-
traceId: string;
25-
setup: Setup & SetupTimeRange;
24+
traceId?: string;
25+
setup: Setup | (Setup & SetupTimeRange);
2626
}) {
2727
return withApmSpan('get_transaction', async () => {
28-
const { start, end, apmEventClient } = setup;
28+
const { apmEventClient } = setup;
2929

3030
const resp = await apmEventClient.search({
3131
apm: {
@@ -37,8 +37,8 @@ export function getTransaction({
3737
bool: {
3838
filter: asMutableArray([
3939
{ term: { [TRANSACTION_ID]: transactionId } },
40-
{ term: { [TRACE_ID]: traceId } },
41-
...rangeQuery(start, end),
40+
...(traceId ? [{ term: { [TRACE_ID]: traceId } }] : []),
41+
...('start' in setup ? rangeQuery(setup.start, setup.end) : []),
4242
]),
4343
},
4444
},

x-pack/plugins/apm/server/routes/traces.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { environmentRt, kueryRt, rangeRt } from './default_api_types';
1414
import { getSearchAggregatedTransactions } from '../lib/helpers/aggregated_transactions';
1515
import { getRootTransactionByTraceId } from '../lib/transactions/get_transaction_by_trace';
1616
import { createApmServerRouteRepository } from './create_apm_server_route_repository';
17+
import { getTransaction } from '../lib/transactions/get_transaction';
1718

1819
const tracesRoute = createApmServerRoute({
1920
endpoint: 'GET /api/apm/traces',
@@ -70,7 +71,24 @@ const rootTransactionByTraceIdRoute = createApmServerRoute({
7071
},
7172
});
7273

74+
const transactionByIdRoute = createApmServerRoute({
75+
endpoint: 'GET /api/apm/transactions/{transactionId}',
76+
params: t.type({
77+
path: t.type({
78+
transactionId: t.string,
79+
}),
80+
}),
81+
options: { tags: ['access:apm'] },
82+
handler: async (resources) => {
83+
const { params } = resources;
84+
const { transactionId } = params.path;
85+
const setup = await setupRequest(resources);
86+
return { transaction: await getTransaction({ transactionId, setup }) };
87+
},
88+
});
89+
7390
export const traceRouteRepository = createApmServerRouteRepository()
7491
.add(tracesByIdRoute)
7592
.add(tracesRoute)
76-
.add(rootTransactionByTraceIdRoute);
93+
.add(rootTransactionByTraceIdRoute)
94+
.add(transactionByIdRoute);

0 commit comments

Comments
 (0)