content.tsx 4.6 KB

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