spanSummaryCharts.tsx 5.2 KB

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