Skip to content

Commit d8e950e

Browse files
Bluefingerkibanamachine
authored andcommitted
[Discover][APM] Add trace waterfall section to traces doc viewer (elastic#217568)
## Summary Enables the Trace section for the summary tab in the Traces Doc Viewer. This PR focuses on just bringing the section with the widget, not for adjusting the widget styles/look to be closer to the intended designs. That is for follow-up work. Closes elastic#217067 ![Screenshot Trace Waterfall 3 2025-04-08 183800](https://github.com/user-attachments/assets/ef57a3c5-38a8-4aa0-854a-be483a6ebde3) ## How to test * Add the following to your `kibana.dev.yml`: ```yaml discover.experimental.enabledProfiles: - observability-traces-data-source-profile - observability-traces-transaction-document-profile - observability-traces-span-document-profile ``` * Ensure you are on an Observability root profile space * Go to Discover, use or create a Data View profiles targetting `traces-*` (such as `remote_cluster:traces-*`). * Click on a span/transaction to expand the doc viewer * The trace waterfall section should be present on the summary tab. --------- Co-authored-by: kibanamachine <[email protected]>
1 parent d2b0efc commit d8e950e

File tree

9 files changed

+166
-41
lines changed

9 files changed

+166
-41
lines changed

src/platform/packages/shared/kbn-discover-utils/src/data_types/traces/traces_context_service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { createRegExpPatternFrom, testPatternAgainstAllowedList } from '@kbn/dat
1212
import { containsIndexPattern } from '../../utils';
1313

1414
export interface TracesContextService {
15-
getAllTracesIndexPattern(): string | undefined;
15+
getAllTracesIndexPattern(): string;
1616
isTracesIndexPattern(indexPattern: unknown): boolean;
1717
containsTracesIndexPattern(indexPattern: unknown): boolean;
1818
}

src/platform/plugins/shared/discover/public/context_awareness/profile_providers/observability/traces_document_profile/span_document_profile/profile.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export const createObservabilityTracesSpanDocumentProfileProvider = ({
2323
isExperimental: true,
2424
profileId: OBSERVABILITY_TRACES_SPAN_DOCUMENT_PROFILE_ID,
2525
profile: {
26-
getDocViewer: createGetDocViewer(tracesContextService.getAllTracesIndexPattern() || ''),
26+
getDocViewer: createGetDocViewer(tracesContextService.getAllTracesIndexPattern()),
2727
},
2828
resolve: ({ record, rootContext }) => {
2929
const isObservabilitySolutionView = rootContext.profileId === OBSERVABILITY_ROOT_PROFILE_ID;

src/platform/plugins/shared/unified_doc_viewer/kibana.jsonc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
"requiredPlugins": [
1515
"data",
1616
"fieldFormats",
17-
"share"
17+
"share",
18+
"embeddable"
1819
],
1920
"optionalPlugins": [
2021
"fieldsMetadata"
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
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", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
import React, { useCallback, useMemo } from 'react';
11+
import { ReactEmbeddableRenderer } from '@kbn/embeddable-plugin/public';
12+
import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiTitle } from '@elastic/eui';
13+
import { i18n } from '@kbn/i18n';
14+
import { traceFields } from '../doc_viewer_span_overview/resources/fields';
15+
import { SpanSummaryField } from '../doc_viewer_span_overview/sub_components/span_summary_field';
16+
import { TransactionSummaryField } from '../doc_viewer_transaction_overview/sub_components/transaction_summary_field';
17+
import { getUnifiedDocViewerServices } from '../../../../plugin';
18+
import { FieldConfiguration } from '../resources/get_field_configuration';
19+
20+
export interface TraceProps {
21+
fields: Record<string, FieldConfiguration>;
22+
serviceName: string;
23+
traceId: string;
24+
transactionId?: string;
25+
displayType: 'span' | 'transaction';
26+
displayLimit?: number;
27+
}
28+
29+
export const Trace = ({
30+
serviceName,
31+
traceId,
32+
transactionId,
33+
fields,
34+
displayType,
35+
displayLimit = 5,
36+
}: TraceProps) => {
37+
const { data } = getUnifiedDocViewerServices();
38+
39+
const { absoluteTimeRange } = data.query.timefilter.timefilter.useTimefilter();
40+
41+
const { rangeFrom, rangeTo } = useMemo(
42+
() => ({
43+
rangeFrom: new Date(absoluteTimeRange.start).toISOString(),
44+
rangeTo: new Date(absoluteTimeRange.end).toISOString(),
45+
}),
46+
[absoluteTimeRange]
47+
);
48+
49+
const getParentApi = useCallback(
50+
() => ({
51+
getSerializedStateForChild: () => ({
52+
rawState: {
53+
serviceName,
54+
traceId,
55+
entryTransactionId: transactionId,
56+
rangeFrom,
57+
rangeTo,
58+
displayLimit,
59+
},
60+
}),
61+
}),
62+
[rangeFrom, rangeTo, displayLimit, serviceName, traceId, transactionId]
63+
);
64+
65+
return (
66+
<>
67+
<EuiTitle size="s">
68+
<h2>
69+
{i18n.translate('unifiedDocViewer.observability.traces.trace.title', {
70+
defaultMessage: 'Trace',
71+
})}
72+
</h2>
73+
</EuiTitle>
74+
<EuiSpacer size="m" />
75+
<EuiFlexGroup direction="column">
76+
<EuiFlexItem>
77+
{traceFields.map((fieldId: string) => {
78+
const props = {
79+
key: fieldId,
80+
fieldId,
81+
fieldConfiguration: fields[fieldId],
82+
};
83+
84+
return displayType === 'span' ? (
85+
<SpanSummaryField {...props} />
86+
) : (
87+
<TransactionSummaryField {...props} />
88+
);
89+
})}
90+
</EuiFlexItem>
91+
</EuiFlexGroup>
92+
<EuiSpacer size="m" />
93+
<ReactEmbeddableRenderer
94+
type="APM_TRACE_WATERFALL_EMBEDDABLE"
95+
getParentApi={getParentApi}
96+
hidePanelChrome={true}
97+
/>
98+
</>
99+
);
100+
};

src/platform/plugins/shared/unified_doc_viewer/public/components/observability/traces/doc_viewer_span_overview/resources/fields.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ import {
2121

2222
export const spanFields = [
2323
SPAN_NAME_FIELD,
24-
TRANSACTION_NAME_FIELD,
2524
SERVICE_NAME_FIELD,
26-
TRACE_ID_FIELD,
2725
SPAN_DESTINATION_SERVICE_RESOURCE_FIELD,
2826
TIMESTAMP_FIELD,
2927
HTTP_RESPONSE_STATUS_CODE_FIELD,
3028
SPAN_TYPE_FIELD,
3129
SPAN_SUBTYPE_FIELD,
3230
];
31+
32+
export const traceFields = [TRACE_ID_FIELD, TRANSACTION_NAME_FIELD];

src/platform/plugins/shared/unified_doc_viewer/public/components/observability/traces/doc_viewer_span_overview/span_overview.tsx

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@
77
* License v3.0 only", or the "Server Side Public License, v 1".
88
*/
99

10-
import React from 'react';
10+
import React, { useMemo } from 'react';
1111
import { DocViewRenderProps } from '@kbn/unified-doc-viewer/types';
1212
import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui';
1313
import { i18n } from '@kbn/i18n';
1414
import {
15+
SERVICE_NAME_FIELD,
1516
SPAN_DURATION_FIELD,
17+
TRACE_ID_FIELD,
1618
TRANSACTION_ID_FIELD,
1719
getTraceDocumentOverview,
1820
} from '@kbn/discover-utils';
@@ -22,6 +24,7 @@ import { spanFields } from './resources/fields';
2224
import { getSpanFieldConfiguration } from './resources/get_span_field_configuration';
2325
import { SpanSummaryField } from './sub_components/span_summary_field';
2426
import { SpanDurationSummary } from './sub_components/span_duration_summary';
27+
import { Trace } from '../components/trace';
2528

2629
export type SpanOverviewProps = DocViewRenderProps & {
2730
transactionIndexPattern: string;
@@ -35,14 +38,13 @@ export function SpanOverview({
3538
onRemoveColumn,
3639
transactionIndexPattern,
3740
}: SpanOverviewProps) {
38-
const parsedDoc = getTraceDocumentOverview(hit);
41+
const parsedDoc = useMemo(() => getTraceDocumentOverview(hit), [hit]);
3942
const spanDuration = parsedDoc[SPAN_DURATION_FIELD];
43+
const transactionId = parsedDoc[TRANSACTION_ID_FIELD];
44+
const fieldConfigurations = useMemo(() => getSpanFieldConfiguration(parsedDoc), [parsedDoc]);
4045

4146
return (
42-
<TransactionProvider
43-
transactionId={parsedDoc[TRANSACTION_ID_FIELD]}
44-
indexPattern={transactionIndexPattern}
45-
>
47+
<TransactionProvider transactionId={transactionId} indexPattern={transactionIndexPattern}>
4648
<FieldActionsProvider
4749
columns={columns}
4850
filter={filter}
@@ -59,24 +61,32 @@ export function SpanOverview({
5961
</h2>
6062
</EuiTitle>
6163
<EuiSpacer size="m" />
62-
{spanFields.map((fieldId) => {
63-
const fieldConfiguration = getSpanFieldConfiguration(parsedDoc)[fieldId];
64-
65-
return (
66-
<SpanSummaryField
67-
key={fieldId}
68-
fieldId={fieldId}
69-
fieldConfiguration={fieldConfiguration}
70-
/>
71-
);
72-
})}
64+
{spanFields.map((fieldId) => (
65+
<SpanSummaryField
66+
key={fieldId}
67+
fieldId={fieldId}
68+
fieldConfiguration={fieldConfigurations[fieldId]}
69+
/>
70+
))}
7371

7472
{spanDuration && (
7573
<>
7674
<EuiSpacer size="m" />
7775
<SpanDurationSummary duration={spanDuration} />
7876
</>
7977
)}
78+
{transactionId && (
79+
<>
80+
<EuiSpacer size="m" />
81+
<Trace
82+
fields={fieldConfigurations}
83+
serviceName={parsedDoc[SERVICE_NAME_FIELD]}
84+
traceId={parsedDoc[TRACE_ID_FIELD]}
85+
transactionId={transactionId}
86+
displayType="span"
87+
/>
88+
</>
89+
)}
8090
</EuiPanel>
8191
</FieldActionsProvider>
8292
</TransactionProvider>

src/platform/plugins/shared/unified_doc_viewer/public/components/observability/traces/doc_viewer_transaction_overview/resources/fields.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,12 @@ import {
1111
HTTP_RESPONSE_STATUS_CODE_FIELD,
1212
SERVICE_NAME_FIELD,
1313
TIMESTAMP_FIELD,
14-
TRACE_ID_FIELD,
15-
TRANSACTION_NAME_FIELD,
1614
USER_AGENT_NAME_FIELD,
1715
USER_AGENT_VERSION_FIELD,
1816
} from '@kbn/discover-utils';
1917

2018
export const transactionFields = [
21-
TRANSACTION_NAME_FIELD,
2219
SERVICE_NAME_FIELD,
23-
TRACE_ID_FIELD,
2420
TIMESTAMP_FIELD,
2521
HTTP_RESPONSE_STATUS_CODE_FIELD,
2622
USER_AGENT_NAME_FIELD,

src/platform/plugins/shared/unified_doc_viewer/public/components/observability/traces/doc_viewer_transaction_overview/transaction_overview.tsx

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@
77
* License v3.0 only", or the "Server Side Public License, v 1".
88
*/
99

10-
import React from 'react';
10+
import React, { useMemo } from 'react';
1111
import { DocViewRenderProps } from '@kbn/unified-doc-viewer/types';
1212
import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui';
1313
import { i18n } from '@kbn/i18n';
1414
import {
15+
SERVICE_NAME_FIELD,
1516
TRACE_ID_FIELD,
1617
TRANSACTION_DURATION_FIELD,
18+
TRANSACTION_ID_FIELD,
1719
getTraceDocumentOverview,
1820
} from '@kbn/discover-utils';
1921
import { FieldActionsProvider } from '../../../../hooks/use_field_actions';
@@ -22,6 +24,8 @@ import { getTransactionFieldConfiguration } from './resources/get_transaction_fi
2224
import { TransactionSummaryField } from './sub_components/transaction_summary_field';
2325
import { TransactionDurationSummary } from './sub_components/transaction_duration_summary';
2426
import { RootTransactionProvider } from './hooks/use_root_transaction';
27+
import { Trace } from '../components/trace';
28+
2529
export type TransactionOverviewProps = DocViewRenderProps & {
2630
tracesIndexPattern: string;
2731
};
@@ -34,8 +38,13 @@ export function TransactionOverview({
3438
onRemoveColumn,
3539
tracesIndexPattern,
3640
}: TransactionOverviewProps) {
37-
const parsedDoc = getTraceDocumentOverview(hit);
41+
const parsedDoc = useMemo(() => getTraceDocumentOverview(hit), [hit]);
3842
const transactionDuration = parsedDoc[TRANSACTION_DURATION_FIELD];
43+
const traceId = parsedDoc[TRACE_ID_FIELD];
44+
const fieldConfigurations = useMemo(
45+
() => getTransactionFieldConfiguration(parsedDoc),
46+
[parsedDoc]
47+
);
3948

4049
const detailTitle = i18n.translate(
4150
'unifiedDocViewer.observability.traces.transactionOverview.title',
@@ -45,7 +54,7 @@ export function TransactionOverview({
4554
);
4655

4756
return (
48-
<RootTransactionProvider traceId={parsedDoc[TRACE_ID_FIELD]} indexPattern={tracesIndexPattern}>
57+
<RootTransactionProvider traceId={traceId} indexPattern={tracesIndexPattern}>
4958
<FieldActionsProvider
5059
columns={columns}
5160
filter={filter}
@@ -58,24 +67,32 @@ export function TransactionOverview({
5867
<h2>{detailTitle}</h2>
5968
</EuiTitle>
6069
<EuiSpacer size="m" />
61-
{transactionFields.map((fieldId) => {
62-
const fieldConfiguration = getTransactionFieldConfiguration(parsedDoc)[fieldId];
63-
64-
return (
65-
<TransactionSummaryField
66-
key={fieldId}
67-
fieldId={fieldId}
68-
fieldConfiguration={fieldConfiguration}
69-
/>
70-
);
71-
})}
70+
{transactionFields.map((fieldId) => (
71+
<TransactionSummaryField
72+
key={fieldId}
73+
fieldId={fieldId}
74+
fieldConfiguration={fieldConfigurations[fieldId]}
75+
/>
76+
))}
7277

7378
{transactionDuration && (
7479
<>
7580
<EuiSpacer size="m" />
7681
<TransactionDurationSummary duration={transactionDuration} />
7782
</>
7883
)}
84+
{traceId && (
85+
<>
86+
<EuiSpacer size="m" />
87+
<Trace
88+
fields={fieldConfigurations}
89+
serviceName={parsedDoc[SERVICE_NAME_FIELD]}
90+
traceId={traceId}
91+
transactionId={parsedDoc[TRANSACTION_ID_FIELD]}
92+
displayType="transaction"
93+
/>
94+
</>
95+
)}
7996
</EuiPanel>
8097
</FieldActionsProvider>
8198
</RootTransactionProvider>

src/platform/plugins/shared/unified_doc_viewer/tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@
4242
"@kbn/elastic-agent-utils",
4343
"@kbn/data-view-utils",
4444
"@kbn/apm-ui-shared",
45-
"@kbn/react-hooks"
45+
"@kbn/react-hooks",
46+
"@kbn/embeddable-plugin"
4647
],
4748
"exclude": ["target/**/*"]
4849
}

0 commit comments

Comments
 (0)