spanSummaryCharts.tsx 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. import {t} from 'sentry/locale';
  2. import type {Series} from 'sentry/types/echarts';
  3. import EventView, {type MetaType} from 'sentry/utils/discover/eventView';
  4. import {RateUnit} from 'sentry/utils/discover/fields';
  5. import {
  6. type DiscoverQueryProps,
  7. useGenericDiscoverQuery,
  8. } from 'sentry/utils/discover/genericDiscoverQuery';
  9. import {DiscoverDatasets} from 'sentry/utils/discover/types';
  10. import {formatRate} from 'sentry/utils/formatters';
  11. import {MutableSearch} from 'sentry/utils/tokenizeSearch';
  12. import {useLocation} from 'sentry/utils/useLocation';
  13. import useOrganization from 'sentry/utils/useOrganization';
  14. import {useParams} from 'sentry/utils/useParams';
  15. import {SpanSummaryReferrer} from 'sentry/views/performance/transactionSummary/transactionSpans/spanSummary/referrers';
  16. import {
  17. AVG_COLOR,
  18. THROUGHPUT_COLOR,
  19. TXN_THROUGHPUT_COLOR,
  20. } from 'sentry/views/starfish/colors';
  21. import Chart, {ChartType} from 'sentry/views/starfish/components/chart';
  22. import ChartPanel from 'sentry/views/starfish/components/chartPanel';
  23. import {useSpanMetricsSeries} from 'sentry/views/starfish/queries/useDiscoverSeries';
  24. import {
  25. SpanMetricsField,
  26. type SpanMetricsQueryFilters,
  27. } from 'sentry/views/starfish/types';
  28. import {Block, BlockContainer} from 'sentry/views/starfish/views/spanSummaryPage/block';
  29. function SpanSummaryCharts() {
  30. const organization = useOrganization();
  31. const {spanSlug} = useParams();
  32. const [spanOp, groupId] = spanSlug.split(':');
  33. const location = useLocation();
  34. const {transaction} = location.query;
  35. const filters: SpanMetricsQueryFilters = {
  36. 'span.group': groupId,
  37. 'span.op': spanOp,
  38. transaction: transaction as string,
  39. };
  40. const {
  41. isLoading: isThroughputDataLoading,
  42. data: throughputData,
  43. error: throughputError,
  44. } = useSpanMetricsSeries(
  45. {
  46. search: MutableSearch.fromQueryObject(filters),
  47. yAxis: ['spm()'],
  48. },
  49. SpanSummaryReferrer.SPAN_SUMMARY_THROUGHPUT_CHART
  50. );
  51. const {
  52. isLoading: isAvgDurationDataLoading,
  53. data: avgDurationData,
  54. error: avgDurationError,
  55. } = useSpanMetricsSeries(
  56. {
  57. search: MutableSearch.fromQueryObject(filters),
  58. // TODO: Switch this to SPAN_DURATION before release
  59. yAxis: [`avg(${SpanMetricsField.SPAN_SELF_TIME})`],
  60. },
  61. SpanSummaryReferrer.SPAN_SUMMARY_DURATION_CHART
  62. );
  63. const eventView = EventView.fromNewQueryWithLocation(
  64. {
  65. yAxis: ['tpm()'],
  66. name: 'Transaction Throughput',
  67. query: MutableSearch.fromQueryObject({
  68. transaction: transaction as string,
  69. }).formatString(),
  70. fields: [],
  71. version: 2,
  72. dataset: DiscoverDatasets.METRICS,
  73. },
  74. location
  75. );
  76. const {
  77. isLoading: isTxnThroughputDataLoading,
  78. data: txnThroughputData,
  79. error: txnThroughputError,
  80. } = useGenericDiscoverQuery<
  81. {
  82. data: any[];
  83. meta: MetaType;
  84. },
  85. DiscoverQueryProps
  86. >({
  87. route: 'events-stats',
  88. eventView,
  89. location,
  90. orgSlug: organization.slug,
  91. getRequestPayload: () => ({
  92. ...eventView.getEventsAPIPayload(location),
  93. yAxis: eventView.yAxis,
  94. interval: eventView.interval,
  95. }),
  96. options: {
  97. refetchOnWindowFocus: false,
  98. },
  99. referrer: SpanSummaryReferrer.SPAN_SUMMARY_TRANSACTION_THROUGHPUT_CHART,
  100. });
  101. const transactionSeries: Series = {
  102. seriesName: 'tpm()',
  103. data:
  104. txnThroughputData?.data.map(datum => ({
  105. value: datum[1][0].count,
  106. name: datum[0] * 1000,
  107. })) ?? [],
  108. };
  109. return (
  110. <BlockContainer>
  111. <Block>
  112. <ChartPanel title={t('Average Duration')}>
  113. <Chart
  114. height={160}
  115. data={[avgDurationData?.[`avg(${SpanMetricsField.SPAN_SELF_TIME})`]]}
  116. loading={isAvgDurationDataLoading}
  117. type={ChartType.LINE}
  118. definedAxisTicks={4}
  119. aggregateOutputFormat="duration"
  120. error={avgDurationError}
  121. chartColors={[AVG_COLOR]}
  122. />
  123. </ChartPanel>
  124. </Block>
  125. <Block>
  126. <ChartPanel title={t('Span Throughput')}>
  127. <Chart
  128. height={160}
  129. data={[throughputData?.[`spm()`]]}
  130. loading={isThroughputDataLoading}
  131. type={ChartType.LINE}
  132. definedAxisTicks={4}
  133. aggregateOutputFormat="rate"
  134. rateUnit={RateUnit.PER_MINUTE}
  135. error={throughputError}
  136. chartColors={[THROUGHPUT_COLOR]}
  137. tooltipFormatterOptions={{
  138. valueFormatter: value => formatRate(value, RateUnit.PER_MINUTE),
  139. }}
  140. />
  141. </ChartPanel>
  142. </Block>
  143. <Block>
  144. <ChartPanel title={t('Transaction Throughput')}>
  145. <Chart
  146. height={160}
  147. data={[transactionSeries]}
  148. loading={isTxnThroughputDataLoading}
  149. type={ChartType.LINE}
  150. definedAxisTicks={4}
  151. aggregateOutputFormat="rate"
  152. rateUnit={RateUnit.PER_MINUTE}
  153. error={txnThroughputError}
  154. chartColors={[TXN_THROUGHPUT_COLOR]}
  155. tooltipFormatterOptions={{
  156. valueFormatter: value => formatRate(value, RateUnit.PER_MINUTE),
  157. }}
  158. />
  159. </ChartPanel>
  160. </Block>
  161. </BlockContainer>
  162. );
  163. }
  164. export default SpanSummaryCharts;