content.tsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import {Fragment} from 'react';
  2. import type {Location} from 'history';
  3. import IdBadge from 'sentry/components/idBadge';
  4. import * as Layout from 'sentry/components/layouts/thirds';
  5. import {t} from 'sentry/locale';
  6. import type {Organization, Project} from 'sentry/types';
  7. import type EventView from 'sentry/utils/discover/eventView';
  8. import type {SpanSlug} from 'sentry/utils/performance/suspectSpans/types';
  9. import useRouteAnalyticsEventNames from 'sentry/utils/routeAnalytics/useRouteAnalyticsEventNames';
  10. import useRouteAnalyticsParams from 'sentry/utils/routeAnalytics/useRouteAnalyticsParams';
  11. import {MutableSearch} from 'sentry/utils/tokenizeSearch';
  12. import {useParams} from 'sentry/utils/useParams';
  13. import Breadcrumb from 'sentry/views/performance/breadcrumb';
  14. import {SpanSummaryReferrer} from 'sentry/views/performance/transactionSummary/transactionSpans/spanSummary/referrers';
  15. import SpanSummaryCharts from 'sentry/views/performance/transactionSummary/transactionSpans/spanSummary/spanSummaryCharts';
  16. import SpanSummaryTable from 'sentry/views/performance/transactionSummary/transactionSpans/spanSummary/spanSummaryTable';
  17. import {getSelectedProjectPlatforms} from 'sentry/views/performance/utils';
  18. import {useSpanMetrics} from 'sentry/views/starfish/queries/useDiscover';
  19. import type {SpanMetricsQueryFilters} from 'sentry/views/starfish/types';
  20. import Tab from '../../tabs';
  21. import SpanSummaryControls from './spanSummaryControls';
  22. import SpanSummaryHeader from './spanSummaryHeader';
  23. type Props = {
  24. eventView: EventView;
  25. location: Location;
  26. organization: Organization;
  27. project: Project | undefined;
  28. spanSlug: SpanSlug;
  29. transactionName: string;
  30. };
  31. export default function SpanSummary(props: Props) {
  32. const {location, organization, eventView, project, transactionName, spanSlug} = props;
  33. // customize the route analytics event we send
  34. useRouteAnalyticsEventNames(
  35. 'performance_views.span_summary.view',
  36. 'Performance Views: Span Summary page viewed'
  37. );
  38. useRouteAnalyticsParams({
  39. project_platforms: project ? getSelectedProjectPlatforms(location, [project]) : '',
  40. });
  41. return (
  42. <Fragment>
  43. <Layout.Header>
  44. <Layout.HeaderContent>
  45. <Breadcrumb
  46. organization={organization}
  47. location={location}
  48. transaction={{
  49. project: project?.id ?? '',
  50. name: transactionName,
  51. }}
  52. tab={Tab.SPANS}
  53. spanSlug={spanSlug}
  54. />
  55. <Layout.Title>
  56. {project && (
  57. <IdBadge
  58. project={project}
  59. avatarSize={28}
  60. hideName
  61. avatarProps={{hasTooltip: true, tooltip: project.slug}}
  62. />
  63. )}
  64. {transactionName}
  65. </Layout.Title>
  66. </Layout.HeaderContent>
  67. </Layout.Header>
  68. <Layout.Body>
  69. <Layout.Main fullWidth>
  70. <SpanSummaryContent
  71. location={location}
  72. organization={organization}
  73. project={project}
  74. eventView={eventView}
  75. spanSlug={spanSlug}
  76. transactionName={transactionName}
  77. />
  78. </Layout.Main>
  79. </Layout.Body>
  80. </Fragment>
  81. );
  82. }
  83. type ContentProps = {
  84. eventView: EventView;
  85. location: Location;
  86. organization: Organization;
  87. project: Project | undefined;
  88. spanSlug: SpanSlug;
  89. transactionName: string;
  90. };
  91. function SpanSummaryContent(props: ContentProps) {
  92. const {transactionName, project} = props;
  93. const {spanSlug: spanParam} = useParams();
  94. const [spanOp, groupId] = spanParam.split(':');
  95. const filters: SpanMetricsQueryFilters = {
  96. 'span.group': groupId,
  97. 'span.op': spanOp,
  98. transaction: transactionName,
  99. };
  100. const {data: spanHeaderData} = useSpanMetrics(
  101. {
  102. search: MutableSearch.fromQueryObject(filters),
  103. // TODO: query average duration instead of self time before releasing this
  104. fields: [
  105. 'span.description',
  106. 'avg(span.self_time)',
  107. 'sum(span.self_time)',
  108. 'count()',
  109. ],
  110. enabled: Boolean(groupId),
  111. },
  112. SpanSummaryReferrer.SPAN_SUMMARY_HEADER_DATA
  113. );
  114. const description = spanHeaderData[0]?.['span.description'] ?? t('unknown');
  115. const timeSpent = spanHeaderData[0]?.['sum(span.self_time)'];
  116. const avgDuration = spanHeaderData[0]?.['avg(span.self_time)'];
  117. const spanCount = spanHeaderData[0]?.['count()'];
  118. return (
  119. <Fragment>
  120. <SpanSummaryControls />
  121. <SpanSummaryHeader
  122. spanOp={spanOp}
  123. spanDescription={description}
  124. avgDuration={avgDuration}
  125. timeSpent={timeSpent}
  126. spanCount={spanCount}
  127. />
  128. <SpanSummaryCharts />
  129. <SpanSummaryTable project={project} />
  130. </Fragment>
  131. );
  132. }