transformSessionsResponseToSeries.tsx 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import {t} from 'sentry/locale';
  2. import type {MetricsApiResponse, SessionApiResponse} from 'sentry/types';
  3. import type {Series} from 'sentry/types/echarts';
  4. import {defined} from 'sentry/utils';
  5. import {DERIVED_STATUS_METRICS_PATTERN} from '../widgetBuilder/releaseWidget/fields';
  6. import {derivedMetricsToField} from './releaseWidgetQueries';
  7. export function getSeriesName(
  8. field: string,
  9. group: SessionApiResponse['groups'][number],
  10. queryAlias?: string
  11. ) {
  12. const groupName = Object.entries(group.by)
  13. .map(([_, value]) => `${value}`)
  14. .join(', ');
  15. const seriesName = groupName
  16. ? `${groupName} : ${derivedMetricsToField(field)}`
  17. : derivedMetricsToField(field);
  18. return `${queryAlias ? `${queryAlias} > ` : ''}${seriesName}`;
  19. }
  20. export function transformSessionsResponseToSeries(
  21. response: SessionApiResponse | MetricsApiResponse | null,
  22. requestedStatusMetrics: string[],
  23. injectedFields: string[],
  24. queryAlias?: string
  25. ): Series[] {
  26. if (response === null) {
  27. return [];
  28. }
  29. const results: Series[] = [];
  30. if (!response.groups.length) {
  31. return [
  32. {
  33. seriesName: `(${t('no results')})`,
  34. data: response.intervals.map(interval => ({
  35. name: interval,
  36. value: 0,
  37. })),
  38. },
  39. ];
  40. }
  41. response.groups.forEach(group => {
  42. Object.keys(group.series).forEach(field => {
  43. // if `sum(session)` or `count_unique(user)` are not
  44. // requested as a part of the payload for
  45. // derived status metrics through the Sessions API,
  46. // they are injected into the payload and need to be
  47. // stripped.
  48. if (!injectedFields.includes(derivedMetricsToField(field))) {
  49. results.push({
  50. seriesName: getSeriesName(field, group, queryAlias),
  51. data: response.intervals.map((interval, index) => ({
  52. name: interval,
  53. value: group.series[field][index] ?? 0,
  54. })),
  55. });
  56. }
  57. });
  58. // if session.status is a groupby, some post processing
  59. // is needed to calculate the status derived metrics
  60. // from grouped results of `sum(session)` or `count_unique(user)`
  61. if (requestedStatusMetrics.length && defined(group.by['session.status'])) {
  62. requestedStatusMetrics.forEach(status => {
  63. const result = status.match(DERIVED_STATUS_METRICS_PATTERN);
  64. if (result) {
  65. let metricField: string | undefined = undefined;
  66. if (group.by['session.status'] === result[1]) {
  67. if (result[2] === 'session') {
  68. metricField = 'sum(session)';
  69. } else if (result[2] === 'user') {
  70. metricField = 'count_unique(user)';
  71. }
  72. }
  73. results.push({
  74. seriesName: getSeriesName(status, group, queryAlias),
  75. data: response.intervals.map((interval, index) => ({
  76. name: interval,
  77. value: metricField ? group.series[metricField][index] ?? 0 : 0,
  78. })),
  79. });
  80. }
  81. });
  82. }
  83. });
  84. return results;
  85. }