projectStatsToPredictedSeries.tsx 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import moment from 'moment';
  2. import {t} from 'sentry/locale';
  3. import {SeriesApi} from 'sentry/types';
  4. import {Series} from 'sentry/types/echarts';
  5. import {defined} from 'sentry/utils';
  6. import commonTheme from 'sentry/utils/theme';
  7. import {Outcome} from 'sentry/views/organizationStats/types';
  8. import {
  9. COLOR_DROPPED,
  10. COLOR_TRANSACTIONS,
  11. } from 'sentry/views/organizationStats/usageChart';
  12. import {quantityField} from '.';
  13. export function projectStatsToPredictedSeries(
  14. projectStats?: SeriesApi,
  15. client?: number,
  16. server?: number
  17. ): Series[] {
  18. if (!projectStats || !defined(client) || !defined(server)) {
  19. return [];
  20. }
  21. const clientRate = Math.max(Math.min(client, 1), 0);
  22. let serverRate = Math.max(Math.min(server, 1), 0);
  23. const commonSeriesConfig = {
  24. barMinHeight: 1,
  25. type: 'bar',
  26. stack: 'predictedUsage',
  27. };
  28. const seriesData: Record<string, Series['data']> = {
  29. accepted: [],
  30. droppedServer: [],
  31. droppedClient: [],
  32. };
  33. (
  34. projectStats.intervals.map((interval, index) => {
  35. const result = {};
  36. projectStats.groups.forEach(group => {
  37. result[group.by.outcome] = group.series[quantityField][index];
  38. });
  39. return {
  40. interval,
  41. ...result,
  42. };
  43. }) as Array<Record<Partial<Outcome>, number> & {interval: string}>
  44. ).forEach((bucket, index) => {
  45. const {
  46. accepted = 0,
  47. filtered = 0,
  48. invalid = 0,
  49. rate_limited: rateLimited = 0,
  50. client_discard: clientDiscard = 0,
  51. interval,
  52. } = bucket;
  53. if (clientRate < serverRate!) {
  54. serverRate = clientRate;
  55. }
  56. const total = accepted + filtered + invalid + rateLimited + clientDiscard;
  57. const newSentClient = total * clientRate;
  58. const newDroppedClient = total - newSentClient;
  59. const newAccepted = clientRate === 0 ? 0 : newSentClient * (serverRate! / clientRate);
  60. const newDroppedServer = newSentClient - newAccepted;
  61. const name = moment(interval).valueOf();
  62. seriesData.accepted[index] = {
  63. name,
  64. value: Math.round(newAccepted),
  65. };
  66. seriesData.droppedServer[index] = {
  67. name,
  68. value: Math.round(newDroppedServer),
  69. };
  70. seriesData.droppedClient[index] = {
  71. name,
  72. value: Math.round(newDroppedClient),
  73. };
  74. });
  75. return [
  76. {
  77. seriesName: t('Accepted'),
  78. color: COLOR_TRANSACTIONS,
  79. ...commonSeriesConfig,
  80. data: seriesData.accepted,
  81. },
  82. {
  83. seriesName: t('Dropped (Server)'),
  84. color: COLOR_DROPPED,
  85. data: seriesData.droppedServer,
  86. ...commonSeriesConfig,
  87. },
  88. {
  89. seriesName: t('Dropped (Client)'),
  90. color: commonTheme.yellow300,
  91. data: seriesData.droppedClient,
  92. ...commonSeriesConfig,
  93. },
  94. ];
  95. }