resourceView.tsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import {Fragment} from 'react';
  2. import styled from '@emotion/styled';
  3. import {CompactSelect} from 'sentry/components/compactSelect';
  4. import {t} from 'sentry/locale';
  5. import {space} from 'sentry/styles/space';
  6. import {trackAnalytics} from 'sentry/utils/analytics';
  7. import {browserHistory} from 'sentry/utils/browserHistory';
  8. import {useLocation} from 'sentry/utils/useLocation';
  9. import useOrganization from 'sentry/utils/useOrganization';
  10. import {getResourceTypeFilter} from 'sentry/views/insights/browser/common/queries/useResourcesQuery';
  11. import RenderBlockingSelector from 'sentry/views/insights/browser/resources/components/renderBlockingSelector';
  12. import ResourceTable from 'sentry/views/insights/browser/resources/components/tables/resourceTable';
  13. import {
  14. FONT_FILE_EXTENSIONS,
  15. IMAGE_FILE_EXTENSIONS,
  16. } from 'sentry/views/insights/browser/resources/constants';
  17. import {
  18. DEFAULT_RESOURCE_TYPES,
  19. RESOURCE_THROUGHPUT_UNIT,
  20. } from 'sentry/views/insights/browser/resources/settings';
  21. import {ResourceSpanOps} from 'sentry/views/insights/browser/resources/types';
  22. import {
  23. BrowserStarfishFields,
  24. useResourceModuleFilters,
  25. } from 'sentry/views/insights/browser/resources/utils/useResourceFilters';
  26. import {useResourceSort} from 'sentry/views/insights/browser/resources/utils/useResourceSort';
  27. import {QueryParameterNames} from 'sentry/views/insights/common/views/queryParameters';
  28. import {TransactionSelector} from 'sentry/views/insights/common/views/spans/selectors/transactionSelector';
  29. import {SpanTimeCharts} from 'sentry/views/insights/common/views/spans/spanTimeCharts';
  30. import type {ModuleFilters} from 'sentry/views/insights/common/views/spans/useModuleFilters';
  31. import {ModuleName} from 'sentry/views/insights/types';
  32. const {
  33. SPAN_OP: RESOURCE_TYPE,
  34. SPAN_DOMAIN,
  35. TRANSACTION,
  36. RESOURCE_RENDER_BLOCKING_STATUS,
  37. USER_GEO_SUBREGION,
  38. } = BrowserStarfishFields;
  39. type Option = {
  40. label: string | React.ReactElement;
  41. value: string;
  42. };
  43. function ResourceView() {
  44. const filters = useResourceModuleFilters();
  45. const sort = useResourceSort();
  46. const spanTimeChartsFilters: ModuleFilters = {
  47. 'span.op': `[${DEFAULT_RESOURCE_TYPES.join(',')}]`,
  48. ...(filters[SPAN_DOMAIN] ? {[SPAN_DOMAIN]: filters[SPAN_DOMAIN]} : {}),
  49. };
  50. const extraQuery = [
  51. ...getResourceTypeFilter(undefined, DEFAULT_RESOURCE_TYPES),
  52. ...(filters[USER_GEO_SUBREGION]
  53. ? [`user.geo.subregion:[${filters[USER_GEO_SUBREGION].join(',')}]`]
  54. : []),
  55. ];
  56. return (
  57. <Fragment>
  58. <SpanTimeChartsContainer>
  59. <SpanTimeCharts
  60. moduleName={ModuleName.RESOURCE}
  61. appliedFilters={spanTimeChartsFilters}
  62. throughputUnit={RESOURCE_THROUGHPUT_UNIT}
  63. extraQuery={extraQuery}
  64. />
  65. </SpanTimeChartsContainer>
  66. <DropdownContainer>
  67. <ResourceTypeSelector value={filters[RESOURCE_TYPE] || ''} />
  68. <TransactionSelector
  69. value={filters[TRANSACTION] || ''}
  70. defaultResourceTypes={DEFAULT_RESOURCE_TYPES}
  71. />
  72. <RenderBlockingSelector value={filters[RESOURCE_RENDER_BLOCKING_STATUS] || ''} />
  73. </DropdownContainer>
  74. <ResourceTable sort={sort} defaultResourceTypes={DEFAULT_RESOURCE_TYPES} />
  75. </Fragment>
  76. );
  77. }
  78. function ResourceTypeSelector({value}: {value?: string}) {
  79. const location = useLocation();
  80. const organization = useOrganization();
  81. const hasImageView = organization.features.includes('insights-initial-modules');
  82. const options: Option[] = [
  83. {value: '', label: 'All'},
  84. {value: 'resource.script', label: `${t('JavaScript')} (.js)`},
  85. {value: 'resource.css', label: `${t('Stylesheet')} (.css)`},
  86. {
  87. value: 'resource.font',
  88. label: `${t('Font')} (${FONT_FILE_EXTENSIONS.map(e => `.${e}`).join(', ')})`,
  89. },
  90. ...(hasImageView
  91. ? [
  92. {
  93. value: ResourceSpanOps.IMAGE,
  94. label: `${t('Image')} (${IMAGE_FILE_EXTENSIONS.map(e => `.${e}`).join(', ')})`,
  95. },
  96. ]
  97. : []),
  98. ];
  99. return (
  100. <CompactSelect
  101. style={{maxWidth: '200px'}}
  102. triggerProps={{prefix: `${t('Type')}`}}
  103. options={options}
  104. value={value ?? ''}
  105. onChange={newValue => {
  106. trackAnalytics('insight.asset.filter_by_type', {
  107. organization,
  108. filter: newValue?.value,
  109. });
  110. browserHistory.push({
  111. ...location,
  112. query: {
  113. ...location.query,
  114. [RESOURCE_TYPE]: newValue?.value,
  115. [QueryParameterNames.SPANS_CURSOR]: undefined,
  116. },
  117. });
  118. }}
  119. />
  120. );
  121. }
  122. export const SpanTimeChartsContainer = styled('div')`
  123. margin-bottom: ${space(2)};
  124. `;
  125. const DropdownContainer = styled('div')`
  126. display: flex;
  127. gap: ${space(2)};
  128. margin-bottom: ${space(2)};
  129. flex-wrap: wrap;
  130. `;
  131. export default ResourceView;