countChart.tsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import {getInterval} from 'sentry/components/charts/utils';
  2. import {t} from 'sentry/locale';
  3. import {space} from 'sentry/styles/space';
  4. import type {Series} from 'sentry/types/echarts';
  5. import type {MultiSeriesEventsStats} from 'sentry/types/organization';
  6. import {defined} from 'sentry/utils';
  7. import {tooltipFormatterUsingAggregateOutputType} from 'sentry/utils/discover/charts';
  8. import EventView from 'sentry/utils/discover/eventView';
  9. import {DiscoverDatasets} from 'sentry/utils/discover/types';
  10. import {formatVersion} from 'sentry/utils/formatters';
  11. import {decodeScalar} from 'sentry/utils/queryString';
  12. import {MutableSearch} from 'sentry/utils/tokenizeSearch';
  13. import {useLocation} from 'sentry/utils/useLocation';
  14. import usePageFilters from 'sentry/utils/usePageFilters';
  15. import {COLD_START_TYPE} from 'sentry/views/performance/mobile/appStarts/screenSummary/startTypeSelector';
  16. import {OUTPUT_TYPE, YAxis} from 'sentry/views/performance/mobile/screenload/screens';
  17. import useTruncatedReleaseNames from 'sentry/views/performance/mobile/useTruncatedRelease';
  18. import {
  19. PRIMARY_RELEASE_COLOR,
  20. SECONDARY_RELEASE_COLOR,
  21. } from 'sentry/views/starfish/colors';
  22. import Chart, {ChartType} from 'sentry/views/starfish/components/chart';
  23. import MiniChartPanel from 'sentry/views/starfish/components/miniChartPanel';
  24. import {useReleaseSelection} from 'sentry/views/starfish/queries/useReleases';
  25. import {SpanMetricsField} from 'sentry/views/starfish/types';
  26. import {STARFISH_CHART_INTERVAL_FIDELITY} from 'sentry/views/starfish/utils/constants';
  27. import {appendReleaseFilters} from 'sentry/views/starfish/utils/releaseComparison';
  28. import {useEventsStatsQuery} from 'sentry/views/starfish/utils/useEventsStatsQuery';
  29. function transformData(data?: MultiSeriesEventsStats, primaryRelease?: string) {
  30. const transformedSeries: {[release: string]: Series} = {};
  31. // Check that 'meta' is not in the data object because that's a sign
  32. // that we did not get a multi-series response for comparison
  33. if (defined(data) && !('meta' in data)) {
  34. Object.keys(data).forEach(release => {
  35. transformedSeries[release] = {
  36. seriesName: release,
  37. data:
  38. data[release]?.data?.map(datum => {
  39. return {
  40. name: datum[0] * 1000,
  41. value: datum[1][0].count,
  42. };
  43. }) ?? [],
  44. ...(primaryRelease === release
  45. ? {color: PRIMARY_RELEASE_COLOR}
  46. : {
  47. color: SECONDARY_RELEASE_COLOR,
  48. lineStyle: {type: 'dashed'},
  49. }),
  50. };
  51. });
  52. }
  53. return transformedSeries;
  54. }
  55. interface Props {
  56. chartHeight?: number;
  57. }
  58. export function CountChart({chartHeight}: Props) {
  59. const location = useLocation();
  60. const pageFilter = usePageFilters();
  61. const {
  62. primaryRelease,
  63. secondaryRelease,
  64. isLoading: isReleasesLoading,
  65. } = useReleaseSelection();
  66. const appStartType =
  67. decodeScalar(location.query[SpanMetricsField.APP_START_TYPE]) ?? COLD_START_TYPE;
  68. const query = new MutableSearch([`span.op:app.start.${appStartType}`]);
  69. const queryString = `${appendReleaseFilters(
  70. query,
  71. primaryRelease,
  72. secondaryRelease
  73. )} span.description:["Cold Start","Warm Start"]`;
  74. const {data: series, isLoading: isSeriesLoading} = useEventsStatsQuery({
  75. eventView: EventView.fromNewQueryWithPageFilters(
  76. {
  77. name: '',
  78. topEvents: '2',
  79. fields: ['release', 'count()'],
  80. yAxis: ['count()'],
  81. query: queryString,
  82. dataset: DiscoverDatasets.SPANS_METRICS,
  83. version: 2,
  84. interval: getInterval(
  85. pageFilter.selection.datetime,
  86. STARFISH_CHART_INTERVAL_FIDELITY
  87. ),
  88. },
  89. pageFilter.selection
  90. ),
  91. enabled: !isReleasesLoading,
  92. referrer: 'api.starfish.mobile-startup-series',
  93. initialData: {},
  94. });
  95. const transformedSeries = Object.values(transformData(series, primaryRelease)).sort(
  96. (releaseA, _releaseB) => {
  97. return releaseA.seriesName === primaryRelease ? -1 : 1;
  98. }
  99. );
  100. const {truncatedPrimaryRelease, truncatedSecondaryRelease} = useTruncatedReleaseNames();
  101. return (
  102. <MiniChartPanel
  103. title={t('Count')}
  104. subtitle={
  105. primaryRelease
  106. ? t(
  107. '%s v. %s',
  108. truncatedPrimaryRelease,
  109. secondaryRelease ? truncatedSecondaryRelease : ''
  110. )
  111. : ''
  112. }
  113. >
  114. <Chart
  115. data={transformedSeries}
  116. height={chartHeight}
  117. loading={isSeriesLoading || isReleasesLoading}
  118. grid={{
  119. left: '0',
  120. right: '0',
  121. top: space(2),
  122. bottom: '0',
  123. }}
  124. showLegend
  125. definedAxisTicks={2}
  126. type={ChartType.LINE}
  127. aggregateOutputFormat={OUTPUT_TYPE[YAxis.COUNT]}
  128. tooltipFormatterOptions={{
  129. valueFormatter: value =>
  130. tooltipFormatterUsingAggregateOutputType(value, OUTPUT_TYPE[YAxis.COUNT]),
  131. nameFormatter: value => formatVersion(value),
  132. }}
  133. legendFormatter={value => formatVersion(value)}
  134. />
  135. </MiniChartPanel>
  136. );
  137. }