spanSummaryCharts.tsx 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  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. yAxis: [`avg(${SpanMetricsField.SPAN_DURATION})`],
  59. },
  60. SpanSummaryReferrer.SPAN_SUMMARY_DURATION_CHART
  61. );
  62. const eventView = EventView.fromNewQueryWithLocation(
  63. {
  64. yAxis: ['tpm()'],
  65. name: 'Transaction Throughput',
  66. query: MutableSearch.fromQueryObject({
  67. transaction: transaction as string,
  68. }).formatString(),
  69. fields: [],
  70. version: 2,
  71. dataset: DiscoverDatasets.METRICS,
  72. },
  73. location
  74. );
  75. const {
  76. isLoading: isTxnThroughputDataLoading,
  77. data: txnThroughputData,
  78. error: txnThroughputError,
  79. } = useGenericDiscoverQuery<
  80. {
  81. data: any[];
  82. meta: MetaType;
  83. },
  84. DiscoverQueryProps
  85. >({
  86. route: 'events-stats',
  87. eventView,
  88. location,
  89. orgSlug: organization.slug,
  90. getRequestPayload: () => ({
  91. ...eventView.getEventsAPIPayload(location),
  92. yAxis: eventView.yAxis,
  93. interval: eventView.interval,
  94. }),
  95. options: {
  96. refetchOnWindowFocus: false,
  97. },
  98. referrer: SpanSummaryReferrer.SPAN_SUMMARY_TRANSACTION_THROUGHPUT_CHART,
  99. });
  100. const transactionSeries: Series = {
  101. seriesName: 'tpm()',
  102. data:
  103. txnThroughputData?.data.map(datum => ({
  104. value: datum[1][0].count,
  105. name: datum[0] * 1000,
  106. })) ?? [],
  107. };
  108. return (
  109. <BlockContainer>
  110. <Block>
  111. <ChartPanel title={t('Average Duration')}>
  112. <Chart
  113. height={160}
  114. data={[avgDurationData?.[`avg(${SpanMetricsField.SPAN_DURATION})`]]}
  115. loading={isAvgDurationDataLoading}
  116. type={ChartType.LINE}
  117. definedAxisTicks={4}
  118. aggregateOutputFormat="duration"
  119. error={avgDurationError}
  120. chartColors={[AVG_COLOR]}
  121. />
  122. </ChartPanel>
  123. </Block>
  124. <Block>
  125. <ChartPanel title={t('Span Throughput')}>
  126. <Chart
  127. height={160}
  128. data={[throughputData?.[`spm()`]]}
  129. loading={isThroughputDataLoading}
  130. type={ChartType.LINE}
  131. definedAxisTicks={4}
  132. aggregateOutputFormat="rate"
  133. rateUnit={RateUnit.PER_MINUTE}
  134. error={throughputError}
  135. chartColors={[THROUGHPUT_COLOR]}
  136. tooltipFormatterOptions={{
  137. valueFormatter: value => formatRate(value, RateUnit.PER_MINUTE),
  138. }}
  139. />
  140. </ChartPanel>
  141. </Block>
  142. <Block>
  143. <ChartPanel title={t('Transaction Throughput')}>
  144. <Chart
  145. height={160}
  146. data={[transactionSeries]}
  147. loading={isTxnThroughputDataLoading}
  148. type={ChartType.LINE}
  149. definedAxisTicks={4}
  150. aggregateOutputFormat="rate"
  151. rateUnit={RateUnit.PER_MINUTE}
  152. error={txnThroughputError}
  153. chartColors={[TXN_THROUGHPUT_COLOR]}
  154. tooltipFormatterOptions={{
  155. valueFormatter: value => formatRate(value, RateUnit.PER_MINUTE),
  156. }}
  157. />
  158. </ChartPanel>
  159. </Block>
  160. </BlockContainer>
  161. );
  162. }
  163. export default SpanSummaryCharts;