Skip to content

Commit 8c7b7bf

Browse files
JonasBac298lee
authored andcommitted
feat(trace): bring back profiling visualization for missing instrumentation spans (#68697)
![CleanShot 2024-04-11 at 10 45 22@2x](https://github.com/getsentry/sentry/assets/9317857/45ae5a9c-d08a-4451-8b2e-8dc3313328f5)
1 parent 8e20f26 commit 8c7b7bf

File tree

4 files changed

+397
-12
lines changed

4 files changed

+397
-12
lines changed

static/app/components/events/interfaces/spans/newTraceDetailsSpanDetails.tsx

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Fragment, useLayoutEffect, useMemo} from 'react';
1+
import {Fragment, useMemo} from 'react';
22
import styled from '@emotion/styled';
33
import omit from 'lodash/omit';
44
import * as qs from 'query-string';
@@ -99,19 +99,14 @@ function NewTraceDetailsSpanDetail(props: SpanDetailProps) {
9999
const issues = useMemo(() => {
100100
return [...props.node.errors, ...props.node.performance_issues];
101101
}, [props.node.errors, props.node.performance_issues]);
102+
102103
const {projects} = useProjects();
103104
const project = projects.find(p => p.id === props.event.projectID);
104105
const resolvedModule: ModuleName = resolveSpanModule(
105106
props.span.sentry_tags?.op,
106107
props.span.sentry_tags?.category
107108
);
108109

109-
useLayoutEffect(() => {
110-
if (!('op' in props.span)) {
111-
return;
112-
}
113-
}, [props.span]);
114-
115110
function renderTraversalButton(): React.ReactNode {
116111
if (!props.childTransactions) {
117112
// TODO: Amend size to use theme when we eventually refactor LoadingIndicator

static/app/views/performance/newTraceDetails/traceDrawer/details/missingInstrumentation.tsx

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
11
import {useTheme} from '@emotion/react';
22

33
import {Button} from 'sentry/components/button';
4+
import {TransactionToProfileButton} from 'sentry/components/profiling/transactionToProfileButton';
45
import {IconSpan} from 'sentry/icons';
56
import {t} from 'sentry/locale';
67
import {getDuration} from 'sentry/utils/formatters';
8+
import useProjects from 'sentry/utils/useProjects';
9+
import {ProfilePreview} from 'sentry/views/performance/newTraceDetails/traceDrawer/details/profiling/profilePreview';
710
import type {TraceTreeNodeDetailsProps} from 'sentry/views/performance/newTraceDetails/traceDrawer/tabs/traceTreeNodeDetails';
811
import {getTraceTabTitle} from 'sentry/views/performance/newTraceDetails/traceState/traceTabs';
912
import {Row} from 'sentry/views/performance/traceDetails/styles';
13+
import {ProfileGroupProvider} from 'sentry/views/profiling/profileGroupProvider';
14+
import {ProfileContext, ProfilesProvider} from 'sentry/views/profiling/profilesProvider';
1015

1116
import {
1217
makeTraceNodeBarColor,
@@ -19,9 +24,15 @@ export function MissingInstrumentationNodeDetails({
1924
node,
2025
onParentClick,
2126
onTabScrollToNode,
27+
organization,
2228
}: TraceTreeNodeDetailsProps<MissingInstrumentationNode>) {
2329
const theme = useTheme();
30+
const {projects} = useProjects();
31+
2432
const parentTransaction = node.parent_transaction;
33+
const event = node.previous.value.event || node.next.value.event || null;
34+
const project = projects.find(proj => proj.slug === event?.projectSlug);
35+
const profileId = event?.contexts?.profile?.profile_id ?? null;
2536

2637
return (
2738
<TraceDrawerComponents.DetailContainer>
@@ -42,6 +53,25 @@ export function MissingInstrumentationNodeDetails({
4253
</Button>
4354
</TraceDrawerComponents.Actions>
4455
</TraceDrawerComponents.HeaderContainer>
56+
{event.projectSlug ? (
57+
<ProfilesProvider
58+
orgSlug={organization.slug}
59+
projectSlug={event.projectSlug}
60+
profileId={profileId || ''}
61+
>
62+
<ProfileContext.Consumer>
63+
{profiles => (
64+
<ProfileGroupProvider
65+
type="flamechart"
66+
input={profiles?.type === 'resolved' ? profiles.data : null}
67+
traceID={profileId || ''}
68+
>
69+
<ProfilePreview event={event} node={node} />
70+
</ProfileGroupProvider>
71+
)}
72+
</ProfileContext.Consumer>
73+
</ProfilesProvider>
74+
) : null}
4575
<TraceDrawerComponents.Table className="table key-value">
4676
<tbody>
4777
{parentTransaction ? (
@@ -53,9 +83,25 @@ export function MissingInstrumentationNodeDetails({
5383
</td>
5484
</Row>
5585
) : null}
56-
<Row title={t('Gap Duration')}>
86+
<Row title={t('Duration')}>
5787
{getDuration(node.value.timestamp - node.value.start_timestamp, 2, true)}
5888
</Row>
89+
{profileId && project?.slug && (
90+
<Row
91+
title="Profile ID"
92+
extra={
93+
<TransactionToProfileButton
94+
size="xs"
95+
projectSlug={project.slug}
96+
event={event}
97+
>
98+
{t('View Profile')}
99+
</TransactionToProfileButton>
100+
}
101+
>
102+
{profileId}
103+
</Row>
104+
)}
59105
<Row title={t('Previous Span')}>
60106
{node.previous.value.op} - {node.previous.value.description}
61107
</Row>

0 commit comments

Comments
 (0)