index.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. import {Fragment} from 'react';
  2. // eslint-disable-next-line no-restricted-imports
  3. import {browserHistory, withRouter, WithRouterProps} from 'react-router';
  4. import {useTheme} from '@emotion/react';
  5. import {Location, Query} from 'history';
  6. import EventsRequest from 'sentry/components/charts/eventsRequest';
  7. import {HeaderTitleLegend} from 'sentry/components/charts/styles';
  8. import {getInterval, getSeriesSelection} from 'sentry/components/charts/utils';
  9. import {normalizeDateTimeParams} from 'sentry/components/organizations/pageFilters/parse';
  10. import QuestionTooltip from 'sentry/components/questionTooltip';
  11. import {t} from 'sentry/locale';
  12. import {OrganizationSummary} from 'sentry/types';
  13. import {getUtcToLocalDateObject} from 'sentry/utils/dates';
  14. import {getAggregateArg, getMeasurementSlug} from 'sentry/utils/discover/fields';
  15. import {WebVital} from 'sentry/utils/fields';
  16. import useApi from 'sentry/utils/useApi';
  17. import {ViewProps} from '../../../types';
  18. import Content from './content';
  19. type Props = WithRouterProps &
  20. ViewProps & {
  21. location: Location;
  22. organization: OrganizationSummary;
  23. queryExtra: Query;
  24. withoutZerofill: boolean;
  25. };
  26. function VitalsChart({
  27. project,
  28. environment,
  29. location,
  30. organization,
  31. query,
  32. statsPeriod,
  33. router,
  34. queryExtra,
  35. withoutZerofill,
  36. start: propsStart,
  37. end: propsEnd,
  38. }: Props) {
  39. const api = useApi();
  40. const theme = useTheme();
  41. const handleLegendSelectChanged = (legendChange: {
  42. name: string;
  43. selected: Record<string, boolean>;
  44. type: string;
  45. }) => {
  46. const {selected} = legendChange;
  47. const unselected = Object.keys(selected).filter(key => !selected[key]);
  48. const to = {
  49. ...location,
  50. query: {
  51. ...location.query,
  52. unselectedSeries: unselected,
  53. },
  54. };
  55. browserHistory.push(to);
  56. };
  57. const vitals = [WebVital.FCP, WebVital.LCP, WebVital.FID, WebVital.CLS];
  58. const start = propsStart ? getUtcToLocalDateObject(propsStart) : null;
  59. const end = propsEnd ? getUtcToLocalDateObject(propsEnd) : null;
  60. const utc = normalizeDateTimeParams(location.query).utc === 'true';
  61. const period = statsPeriod;
  62. const legend = {
  63. right: 10,
  64. top: 0,
  65. selected: getSeriesSelection(location),
  66. formatter: (seriesName: string) => {
  67. const arg = getAggregateArg(seriesName);
  68. if (arg !== null) {
  69. const slug = getMeasurementSlug(arg);
  70. if (slug !== null) {
  71. seriesName = slug.toUpperCase();
  72. }
  73. }
  74. return seriesName;
  75. },
  76. };
  77. const datetimeSelection = {start, end, period};
  78. const contentCommonProps = {
  79. theme,
  80. router,
  81. start,
  82. end,
  83. utc,
  84. legend,
  85. queryExtra,
  86. period,
  87. projects: project,
  88. environments: environment,
  89. onLegendSelectChanged: handleLegendSelectChanged,
  90. };
  91. const requestCommonProps = {
  92. api,
  93. start,
  94. end,
  95. project,
  96. environment,
  97. query,
  98. period,
  99. interval: getInterval(datetimeSelection, 'high'),
  100. };
  101. const header = (
  102. <HeaderTitleLegend>
  103. {t('Web Vitals Breakdown')}
  104. <QuestionTooltip
  105. size="sm"
  106. position="top"
  107. title={t(
  108. `Web Vitals Breakdown reflects the 75th percentile of web vitals over time.`
  109. )}
  110. />
  111. </HeaderTitleLegend>
  112. );
  113. const yAxis = vitals.map(v => `p75(${v})`);
  114. return (
  115. <Fragment>
  116. {header}
  117. <EventsRequest
  118. {...requestCommonProps}
  119. organization={organization}
  120. showLoading={false}
  121. includePrevious={false}
  122. yAxis={yAxis}
  123. partial
  124. withoutZerofill={withoutZerofill}
  125. referrer="api.performance.transaction-summary.vitals-chart"
  126. >
  127. {({results, errored, loading, reloading, timeframe: timeFrame}) => (
  128. <Content
  129. series={results}
  130. errored={errored}
  131. loading={loading}
  132. reloading={reloading}
  133. timeFrame={timeFrame}
  134. {...contentCommonProps}
  135. />
  136. )}
  137. </EventsRequest>
  138. </Fragment>
  139. );
  140. }
  141. export default withRouter(VitalsChart);