breakpointChartOptions.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import type {Theme} from '@emotion/react';
  2. import type {FunctionRegressionPercentileData} from 'sentry/chartcuterie/performance';
  3. import {ChartType} from 'sentry/chartcuterie/types';
  4. import VisualMap from 'sentry/components/charts/components/visualMap';
  5. import type {LineChart as EChartsLineChart} from 'sentry/components/charts/lineChart';
  6. import type {EventsStatsData} from 'sentry/types/organization';
  7. import {
  8. axisLabelFormatter,
  9. getDurationUnit,
  10. tooltipFormatter,
  11. } from 'sentry/utils/discover/charts';
  12. import {aggregateOutputType} from 'sentry/utils/discover/fields';
  13. import {
  14. type NormalizedTrendsTransaction,
  15. TrendFunctionField,
  16. } from 'sentry/views/performance/trends/types';
  17. import generateTrendFunctionAsString from 'sentry/views/performance/trends/utils/generateTrendFunctionAsString';
  18. import transformEventStats from 'sentry/views/performance/trends/utils/transformEventStats';
  19. import {getIntervalLine} from 'sentry/views/performance/utils/getIntervalLine';
  20. export type EventBreakpointChartData = {
  21. evidenceData: NormalizedTrendsTransaction;
  22. percentileData: EventsStatsData | FunctionRegressionPercentileData;
  23. };
  24. function getBreakpointChartOptionsFromData(
  25. {percentileData, evidenceData}: EventBreakpointChartData,
  26. chartType: ChartType,
  27. theme: Theme
  28. ) {
  29. const trendFunctionName: Partial<{[key in ChartType]: string}> = {
  30. [ChartType.SLACK_PERFORMANCE_ENDPOINT_REGRESSION]: 'transaction.duration',
  31. [ChartType.SLACK_PERFORMANCE_FUNCTION_REGRESSION]: 'function.duration',
  32. };
  33. const defaultTransform = stats => stats;
  34. const transformFunctionStats = (stats: any) => {
  35. const rawData = stats?.data?.data?.find(({axis}) => axis === 'p95()');
  36. const timestamps = stats?.data?.timestamps;
  37. if (!timestamps) {
  38. return [];
  39. }
  40. return timestamps.map((timestamp, i) => [timestamp, [{count: rawData.values[i]}]]);
  41. };
  42. // Mapping from BreakpointType to transformation functions
  43. const transformFunction: Partial<{[key in ChartType]: (arg: any) => EventsStatsData}> =
  44. {
  45. [ChartType.SLACK_PERFORMANCE_ENDPOINT_REGRESSION]: defaultTransform,
  46. [ChartType.SLACK_PERFORMANCE_FUNCTION_REGRESSION]: transformFunctionStats,
  47. };
  48. const transformedSeries = transformEventStats(
  49. transformFunction[chartType]!(percentileData),
  50. generateTrendFunctionAsString(TrendFunctionField.P95, trendFunctionName[chartType]!)
  51. );
  52. const intervalSeries = getIntervalLine(
  53. theme,
  54. transformedSeries,
  55. 0.5,
  56. true,
  57. evidenceData,
  58. true
  59. );
  60. const series = [...transformedSeries, ...intervalSeries];
  61. const legend = {
  62. right: 16,
  63. top: 12,
  64. data: transformedSeries.map(s => s.seriesName),
  65. };
  66. const durationUnit = getDurationUnit(series);
  67. const chartOptions: Omit<React.ComponentProps<typeof EChartsLineChart>, 'series'> = {
  68. axisPointer: {
  69. link: [
  70. {
  71. xAxisIndex: [0, 1],
  72. yAxisIndex: [0, 1],
  73. },
  74. ],
  75. },
  76. colors: [theme.gray200, theme.gray500],
  77. grid: {
  78. top: '40px',
  79. bottom: '0px',
  80. },
  81. legend,
  82. toolBox: {show: false},
  83. tooltip: {
  84. valueFormatter: (value, seriesName) => {
  85. return tooltipFormatter(value, aggregateOutputType(seriesName));
  86. },
  87. },
  88. xAxis: {type: 'time'},
  89. yAxis: {
  90. minInterval: durationUnit,
  91. axisLabel: {
  92. color: theme.chartLabel,
  93. formatter: (value: number) =>
  94. axisLabelFormatter(value, 'duration', undefined, durationUnit),
  95. },
  96. },
  97. options: {
  98. visualMap: VisualMap({
  99. show: false,
  100. type: 'piecewise',
  101. selectedMode: false,
  102. dimension: 0,
  103. pieces: [
  104. {
  105. gte: 0,
  106. lt: evidenceData?.breakpoint ? evidenceData.breakpoint * 1000 : 0,
  107. color: theme.gray500,
  108. },
  109. {
  110. gte: evidenceData?.breakpoint ? evidenceData.breakpoint * 1000 : 0,
  111. color: theme.red300,
  112. },
  113. ],
  114. }),
  115. },
  116. };
  117. return {
  118. series,
  119. chartOptions,
  120. };
  121. }
  122. export default getBreakpointChartOptionsFromData;