projectStatsToSeries.tsx 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import cloneDeep from 'lodash/cloneDeep';
  2. import moment from 'moment';
  3. import {t} from 'sentry/locale';
  4. import {Outcome, SeriesApi} from 'sentry/types';
  5. import {Series} from 'sentry/types/echarts';
  6. import {defined} from 'sentry/utils';
  7. import commonTheme from 'sentry/utils/theme';
  8. import {quantityField} from '.';
  9. export function projectStatsToSeries(
  10. projectStats: SeriesApi | undefined,
  11. specifiedClientRate?: number
  12. ): Series[] {
  13. if (!projectStats) {
  14. return [];
  15. }
  16. const commonSeriesConfig = {
  17. barMinHeight: 0,
  18. type: 'bar',
  19. stack: 'usage',
  20. };
  21. const emptySeries = projectStats.intervals.map(interval => ({
  22. name: moment(interval).valueOf(),
  23. value: 0,
  24. }));
  25. const seriesData: Record<
  26. 'indexedAndProcessed' | 'processed' | 'discarded',
  27. Series['data']
  28. > = {
  29. indexedAndProcessed: cloneDeep(emptySeries),
  30. processed: cloneDeep(emptySeries),
  31. discarded: cloneDeep(emptySeries),
  32. };
  33. projectStats.intervals.forEach((_interval, index) => {
  34. projectStats.groups.forEach(group => {
  35. switch (group.by.outcome) {
  36. case Outcome.ACCEPTED:
  37. seriesData.indexedAndProcessed[index].value +=
  38. group.series[quantityField][index];
  39. break;
  40. case Outcome.CLIENT_DISCARD:
  41. seriesData.discarded[index].value += group.series[quantityField][index];
  42. break;
  43. case Outcome.FILTERED:
  44. if (String(group.by.reason).startsWith('Sampled')) {
  45. seriesData.processed[index].value += group.series[quantityField][index];
  46. }
  47. break;
  48. default:
  49. // We do not take invalid, rate_limited and other filtered into account
  50. }
  51. });
  52. });
  53. if (defined(specifiedClientRate)) {
  54. // We assume that the clientDiscard is 0 and
  55. // calculate the discard client (SDK) bucket according to the specified client rate
  56. seriesData.discarded = seriesData.discarded.map((bucket, index) => {
  57. const totalHitServer =
  58. seriesData.indexedAndProcessed[index].value + seriesData.processed[index].value;
  59. return {
  60. ...bucket,
  61. value: totalHitServer / specifiedClientRate - totalHitServer,
  62. };
  63. });
  64. }
  65. return [
  66. {
  67. seriesName: t('Indexed and Processed'),
  68. color: commonTheme.green300,
  69. ...commonSeriesConfig,
  70. data: seriesData.indexedAndProcessed,
  71. },
  72. {
  73. seriesName: t('Processed'),
  74. color: commonTheme.yellow300,
  75. data: seriesData.processed,
  76. ...commonSeriesConfig,
  77. },
  78. {
  79. seriesName: t('Discarded'),
  80. color: commonTheme.red300,
  81. data: seriesData.discarded,
  82. ...commonSeriesConfig,
  83. },
  84. ];
  85. }