projectStatsToSeries.tsx 2.7 KB

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