breakpointChart.tsx 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. import {ChartType} from 'sentry/chartcuterie/types';
  2. import TransitionChart from 'sentry/components/charts/transitionChart';
  3. import TransparentLoadingMask from 'sentry/components/charts/transparentLoadingMask';
  4. import type {Event, EventsStatsData} from 'sentry/types';
  5. import type {MetaType} from 'sentry/utils/discover/eventView';
  6. import EventView from 'sentry/utils/discover/eventView';
  7. import type {DiscoverQueryProps} from 'sentry/utils/discover/genericDiscoverQuery';
  8. import {useGenericDiscoverQuery} from 'sentry/utils/discover/genericDiscoverQuery';
  9. import {DiscoverDatasets} from 'sentry/utils/discover/types';
  10. import {useRelativeDateTime} from 'sentry/utils/profiling/hooks/useRelativeDateTime';
  11. import {useLocation} from 'sentry/utils/useLocation';
  12. import useOrganization from 'sentry/utils/useOrganization';
  13. import type {NormalizedTrendsTransaction} from 'sentry/views/performance/trends/types';
  14. import {DataSection} from '../styles';
  15. import {RELATIVE_DAYS_WINDOW} from './consts';
  16. import Chart from './lineChart';
  17. function camelToUnderscore(key: string) {
  18. return key.replace(/([A-Z\d])/g, '_$1').toLowerCase();
  19. }
  20. type EventBreakpointChartProps = {
  21. event: Event;
  22. };
  23. function EventBreakpointChart({event}: EventBreakpointChartProps) {
  24. const organization = useOrganization();
  25. const location = useLocation();
  26. const {transaction, breakpoint} = event?.occurrence?.evidenceData ?? {};
  27. const eventView = EventView.fromLocation(location);
  28. eventView.query = `event.type:transaction transaction:"${transaction}"`;
  29. eventView.dataset = DiscoverDatasets.METRICS;
  30. const datetime = useRelativeDateTime({
  31. anchor: breakpoint,
  32. relativeDays: RELATIVE_DAYS_WINDOW,
  33. });
  34. const {start: beforeDateTime, end: afterDateTime} = datetime;
  35. eventView.start = (beforeDateTime as Date).toISOString();
  36. eventView.end = (afterDateTime as Date).toISOString();
  37. eventView.statsPeriod = undefined;
  38. // The evidence data keys are returned to us in camelCase, but we need to
  39. // convert them to snake_case to match the NormalizedTrendsTransaction type
  40. const normalizedOccurrenceEvent = Object.keys(
  41. event?.occurrence?.evidenceData ?? []
  42. ).reduce((acc, key) => {
  43. acc[camelToUnderscore(key)] = event?.occurrence?.evidenceData?.[key];
  44. return acc;
  45. }, {}) as NormalizedTrendsTransaction;
  46. const {data, isLoading} = useGenericDiscoverQuery<
  47. {
  48. data: EventsStatsData;
  49. meta: MetaType;
  50. },
  51. DiscoverQueryProps
  52. >({
  53. route: 'events-stats',
  54. location,
  55. eventView,
  56. orgSlug: organization.slug,
  57. getRequestPayload: () => ({
  58. // Manually inject y-axis for events-stats because
  59. // getEventsAPIPayload doesn't pass it along
  60. ...eventView.getEventsAPIPayload(location),
  61. yAxis: ['p95(transaction.duration)', 'count()'],
  62. }),
  63. });
  64. return (
  65. <DataSection>
  66. <TransitionChart loading={isLoading} reloading>
  67. <TransparentLoadingMask visible={isLoading} />
  68. <Chart
  69. percentileData={data?.['p95(transaction.duration)']?.data ?? []}
  70. evidenceData={normalizedOccurrenceEvent}
  71. datetime={datetime}
  72. chartType={ChartType.SLACK_PERFORMANCE_ENDPOINT_REGRESSION}
  73. />
  74. </TransitionChart>
  75. </DataSection>
  76. );
  77. }
  78. export default EventBreakpointChart;