missingInstrumentation.tsx 4.3 KB

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