transformSessionsResponseToSeries.tsx 3.0 KB

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