index.tsx 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import styled from '@emotion/styled';
  2. import Breadcrumbs from 'sentry/components/breadcrumbs';
  3. import FloatingFeedbackWidget from 'sentry/components/feedback/widget/floatingFeedbackWidget';
  4. import * as Layout from 'sentry/components/layouts/thirds';
  5. import {DatePageFilter} from 'sentry/components/organizations/datePageFilter';
  6. import {EnvironmentPageFilter} from 'sentry/components/organizations/environmentPageFilter';
  7. import PageFilterBar from 'sentry/components/organizations/pageFilterBar';
  8. import {ProjectPageFilter} from 'sentry/components/organizations/projectPageFilter';
  9. import {t} from 'sentry/locale';
  10. import {useLocation} from 'sentry/utils/useLocation';
  11. import useOrganization from 'sentry/utils/useOrganization';
  12. import {useParams} from 'sentry/utils/useParams';
  13. import {normalizeUrl} from 'sentry/utils/withDomainRequired';
  14. import ResourceInfo from 'sentry/views/performance/browser/resources/resourceSummaryPage/resourceInfo';
  15. import ResourceSummaryCharts from 'sentry/views/performance/browser/resources/resourceSummaryPage/resourceSummaryCharts';
  16. import ResourceSummaryTable from 'sentry/views/performance/browser/resources/resourceSummaryPage/resourceSummaryTable';
  17. import SampleImages from 'sentry/views/performance/browser/resources/resourceSummaryPage/sampleImages';
  18. import {FilterOptionsContainer} from 'sentry/views/performance/browser/resources/resourceView';
  19. import {IMAGE_FILE_EXTENSIONS} from 'sentry/views/performance/browser/resources/shared/constants';
  20. import RenderBlockingSelector from 'sentry/views/performance/browser/resources/shared/renderBlockingSelector';
  21. import {useResourceModuleFilters} from 'sentry/views/performance/browser/resources/utils/useResourceFilters';
  22. import {ModulePageProviders} from 'sentry/views/performance/database/modulePageProviders';
  23. import {useSpanMetrics} from 'sentry/views/starfish/queries/useSpanMetrics';
  24. import {SpanMetricsField} from 'sentry/views/starfish/types';
  25. import {SampleList} from 'sentry/views/starfish/views/spanSummaryPage/sampleList';
  26. const {
  27. SPAN_SELF_TIME,
  28. SPAN_DESCRIPTION,
  29. HTTP_DECODED_RESPONSE_CONTENT_LENGTH,
  30. HTTP_RESPONSE_CONTENT_LENGTH,
  31. HTTP_RESPONSE_TRANSFER_SIZE,
  32. RESOURCE_RENDER_BLOCKING_STATUS,
  33. } = SpanMetricsField;
  34. function ResourceSummary() {
  35. const organization = useOrganization();
  36. const {groupId} = useParams();
  37. const filters = useResourceModuleFilters();
  38. const {
  39. query: {transaction},
  40. } = useLocation();
  41. const {data} = useSpanMetrics(
  42. {
  43. 'span.group': groupId,
  44. },
  45. [
  46. `avg(${SPAN_SELF_TIME})`,
  47. `avg(${HTTP_RESPONSE_CONTENT_LENGTH})`,
  48. `avg(${HTTP_DECODED_RESPONSE_CONTENT_LENGTH})`,
  49. `avg(${HTTP_RESPONSE_TRANSFER_SIZE})`,
  50. `sum(${SPAN_SELF_TIME})`,
  51. 'spm()',
  52. SPAN_DESCRIPTION,
  53. 'time_spent_percentage()',
  54. ]
  55. );
  56. const spanMetrics = data[0] ?? {};
  57. const isImage = IMAGE_FILE_EXTENSIONS.includes(
  58. spanMetrics[SpanMetricsField.SPAN_DESCRIPTION]?.split('.').pop() || ''
  59. );
  60. return (
  61. <ModulePageProviders
  62. title={[t('Performance'), t('Resources'), t('Resource Summary')].join(' — ')}
  63. >
  64. <Layout.Header>
  65. <Layout.HeaderContent>
  66. <Breadcrumbs
  67. crumbs={[
  68. {
  69. label: 'Performance',
  70. to: normalizeUrl(`/organizations/${organization.slug}/performance/`),
  71. preservePageFilters: true,
  72. },
  73. {
  74. label: 'Resources',
  75. to: normalizeUrl(
  76. `/organizations/${organization.slug}/performance/browser/resources/`
  77. ),
  78. preservePageFilters: true,
  79. },
  80. {
  81. label: 'Resource Summary',
  82. },
  83. ]}
  84. />
  85. <Layout.Title>{spanMetrics[SpanMetricsField.SPAN_DESCRIPTION]}</Layout.Title>
  86. </Layout.HeaderContent>
  87. </Layout.Header>
  88. <Layout.Body>
  89. <Layout.Main fullWidth>
  90. <FloatingFeedbackWidget />
  91. <HeaderContainer>
  92. <FilterOptionsContainer columnCount={2}>
  93. <PageFilterBar condensed>
  94. <ProjectPageFilter />
  95. <EnvironmentPageFilter />
  96. <DatePageFilter />
  97. </PageFilterBar>
  98. <RenderBlockingSelector
  99. value={filters[RESOURCE_RENDER_BLOCKING_STATUS] || ''}
  100. />
  101. </FilterOptionsContainer>
  102. <ResourceInfo
  103. avgContentLength={spanMetrics[`avg(${HTTP_RESPONSE_CONTENT_LENGTH})`]}
  104. avgDecodedContentLength={
  105. spanMetrics[`avg(${HTTP_DECODED_RESPONSE_CONTENT_LENGTH})`]
  106. }
  107. avgTransferSize={spanMetrics[`avg(${HTTP_RESPONSE_TRANSFER_SIZE})`]}
  108. avgDuration={spanMetrics[`avg(${SPAN_SELF_TIME})`]}
  109. throughput={spanMetrics['spm()']}
  110. timeSpentTotal={spanMetrics[`sum(${SPAN_SELF_TIME})`]}
  111. timeSpentPercentage={spanMetrics[`time_spent_percentage()`]}
  112. />
  113. </HeaderContainer>
  114. {isImage && <SampleImages groupId={groupId} />}
  115. <ResourceSummaryCharts groupId={groupId} />
  116. <ResourceSummaryTable />
  117. <SampleList
  118. transactionRoute="/performance/browser/pageloads/"
  119. groupId={groupId}
  120. transactionName={transaction as string}
  121. additionalFields={[HTTP_RESPONSE_CONTENT_LENGTH]}
  122. />
  123. </Layout.Main>
  124. </Layout.Body>
  125. </ModulePageProviders>
  126. );
  127. }
  128. const HeaderContainer = styled('div')`
  129. display: flex;
  130. justify-content: space-between;
  131. flex-wrap: wrap;
  132. `;
  133. export default ResourceSummary;