missingInstrumentation.tsx 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import {useTheme} from '@emotion/react';
  2. import {IconSpan} from 'sentry/icons';
  3. import {t} from 'sentry/locale';
  4. import getDuration from 'sentry/utils/duration/getDuration';
  5. import {generateProfileFlamechartRouteWithQuery} from 'sentry/utils/profiling/routes';
  6. import useProjects from 'sentry/utils/useProjects';
  7. import {ProfilePreview} from 'sentry/views/performance/newTraceDetails/traceDrawer/details/profiling/profilePreview';
  8. import type {TraceTreeNodeDetailsProps} from 'sentry/views/performance/newTraceDetails/traceDrawer/tabs/traceTreeNodeDetails';
  9. import {getTraceTabTitle} from 'sentry/views/performance/newTraceDetails/traceState/traceTabs';
  10. import {ProfileGroupProvider} from 'sentry/views/profiling/profileGroupProvider';
  11. import {ProfileContext, ProfilesProvider} from 'sentry/views/profiling/profilesProvider';
  12. import {
  13. makeTraceNodeBarColor,
  14. type MissingInstrumentationNode,
  15. } from '../../traceModels/traceTree';
  16. import {type SectionCardKeyValueList, TraceDrawerComponents} from './styles';
  17. export function MissingInstrumentationNodeDetails({
  18. node,
  19. onParentClick,
  20. onTabScrollToNode,
  21. organization,
  22. }: TraceTreeNodeDetailsProps<MissingInstrumentationNode>) {
  23. const theme = useTheme();
  24. const {projects} = useProjects();
  25. const parentTransaction = node.parent_transaction;
  26. const event = node.previous.value.event || node.next.value.event || null;
  27. const project = projects.find(proj => proj.slug === event?.projectSlug);
  28. const profileId = event?.contexts?.profile?.profile_id ?? null;
  29. const items: SectionCardKeyValueList = [
  30. {
  31. key: 'duration',
  32. subject: t('Duration'),
  33. value: getDuration(node.value.timestamp - node.value.start_timestamp, 2, true),
  34. },
  35. {
  36. key: 'previous_span',
  37. subject: t('Previous Span'),
  38. value: `${node.previous.value.op} - ${node.previous.value.description}`,
  39. },
  40. {
  41. key: 'next_span',
  42. subject: t('Next Span'),
  43. value: `${node.next.value.op} - ${node.next.value.description}`,
  44. },
  45. ];
  46. if (profileId && project?.slug) {
  47. items.push({
  48. key: 'profile_id',
  49. subject: 'Profile ID',
  50. value: (
  51. <TraceDrawerComponents.CopyableCardValueWithLink
  52. value={profileId}
  53. linkTarget={generateProfileFlamechartRouteWithQuery({
  54. orgSlug: organization.slug,
  55. projectSlug: project.slug,
  56. profileId,
  57. })}
  58. linkText={t('View Profile')}
  59. />
  60. ),
  61. });
  62. }
  63. if (parentTransaction) {
  64. items.push({
  65. key: 'parent_transaction',
  66. subject: t('Parent Transaction'),
  67. value: (
  68. <a onClick={() => onParentClick(parentTransaction)}>
  69. {getTraceTabTitle(parentTransaction)}
  70. </a>
  71. ),
  72. });
  73. }
  74. return (
  75. <TraceDrawerComponents.DetailContainer>
  76. <TraceDrawerComponents.HeaderContainer>
  77. <TraceDrawerComponents.Title>
  78. <TraceDrawerComponents.IconTitleWrapper>
  79. <TraceDrawerComponents.IconBorder
  80. backgroundColor={makeTraceNodeBarColor(theme, node)}
  81. >
  82. <IconSpan size="md" />
  83. </TraceDrawerComponents.IconBorder>
  84. <div style={{fontWeight: 'bold'}}>{t('Missing Instrumentation')}</div>
  85. </TraceDrawerComponents.IconTitleWrapper>
  86. </TraceDrawerComponents.Title>
  87. <TraceDrawerComponents.NodeActions
  88. organization={organization}
  89. node={node}
  90. onTabScrollToNode={onTabScrollToNode}
  91. />
  92. </TraceDrawerComponents.HeaderContainer>
  93. {event.projectSlug ? (
  94. <ProfilesProvider
  95. orgSlug={organization.slug}
  96. projectSlug={event.projectSlug}
  97. profileId={profileId || ''}
  98. >
  99. <ProfileContext.Consumer>
  100. {profiles => (
  101. <ProfileGroupProvider
  102. type="flamechart"
  103. input={profiles?.type === 'resolved' ? profiles.data : null}
  104. traceID={profileId || ''}
  105. >
  106. <ProfilePreview event={event} node={node} />
  107. </ProfileGroupProvider>
  108. )}
  109. </ProfileContext.Consumer>
  110. </ProfilesProvider>
  111. ) : null}
  112. <TraceDrawerComponents.SectionCard items={items} title={t('General')} />
  113. </TraceDrawerComponents.DetailContainer>
  114. );
  115. }