getComparisonMarkLines.tsx 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. import MarkLine from 'sentry/components/charts/components/markLine';
  2. import type {LineChartSeries} from 'sentry/components/charts/lineChart';
  3. import {t} from 'sentry/locale';
  4. import type {Series} from 'sentry/types/echarts';
  5. import {MINUTE} from 'sentry/utils/formatters';
  6. import theme from 'sentry/utils/theme';
  7. import type {
  8. AlertRuleThresholdType,
  9. Trigger,
  10. } from 'sentry/views/alerts/rules/metric/types';
  11. import {AlertRuleTriggerType} from 'sentry/views/alerts/rules/metric/types';
  12. import {getChangeStatus} from 'sentry/views/alerts/utils/getChangeStatus';
  13. export const getComparisonMarkLines = (
  14. timeseriesData: Series[] = [],
  15. comparisonTimeseriesData: Series[] = [],
  16. timeWindow: number,
  17. triggers: Trigger[],
  18. thresholdType: AlertRuleThresholdType
  19. ): LineChartSeries[] => {
  20. const changeStatuses: {name: number | string; status: string}[] = [];
  21. if (
  22. timeseriesData?.[0]?.data !== undefined &&
  23. timeseriesData[0].data.length > 1 &&
  24. comparisonTimeseriesData?.[0]?.data !== undefined &&
  25. comparisonTimeseriesData[0].data.length > 1
  26. ) {
  27. const changeData = comparisonTimeseriesData[0].data;
  28. const baseData = timeseriesData[0].data;
  29. if (triggers.some(({alertThreshold}) => typeof alertThreshold === 'number')) {
  30. const lastPointLimit =
  31. (baseData[changeData.length - 1].name as number) - timeWindow * MINUTE;
  32. changeData.forEach(({name, value: comparisonValue}, idx) => {
  33. const baseValue = baseData[idx].value;
  34. const comparisonPercentage =
  35. comparisonValue === 0
  36. ? baseValue === 0
  37. ? 0
  38. : Infinity
  39. : ((baseValue - comparisonValue) / comparisonValue) * 100;
  40. const status = getChangeStatus(comparisonPercentage, thresholdType, triggers);
  41. if (
  42. idx === 0 ||
  43. idx === changeData.length - 1 ||
  44. status !== changeStatuses[changeStatuses.length - 1].status
  45. ) {
  46. changeStatuses.push({name, status});
  47. }
  48. });
  49. return changeStatuses.slice(0, -1).map(({name, status}, idx) => ({
  50. seriesName: t('status'),
  51. type: 'line',
  52. markLine: MarkLine({
  53. silent: true,
  54. lineStyle: {
  55. color:
  56. status === AlertRuleTriggerType.CRITICAL
  57. ? theme.red300
  58. : status === AlertRuleTriggerType.WARNING
  59. ? theme.yellow300
  60. : theme.green300,
  61. type: 'solid',
  62. width: 4,
  63. },
  64. data: [
  65. [
  66. {coord: [name, 0]},
  67. {
  68. coord: [
  69. Math.min(changeStatuses[idx + 1].name as number, lastPointLimit),
  70. 0,
  71. ],
  72. },
  73. ],
  74. ],
  75. }),
  76. data: [],
  77. }));
  78. }
  79. }
  80. return [];
  81. };