resourceSummaryCharts.tsx 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. import {Fragment} from 'react';
  2. import {t, tct} from 'sentry/locale';
  3. import {formatBytesBase2} from 'sentry/utils/bytes/formatBytesBase2';
  4. import {formatRate} from 'sentry/utils/formatters';
  5. import getDynamicText from 'sentry/utils/getDynamicText';
  6. import {MutableSearch} from 'sentry/utils/tokenizeSearch';
  7. import {ALERTS} from 'sentry/views/insights/browser/resources/alerts';
  8. import {Referrer} from 'sentry/views/insights/browser/resources/referrer';
  9. import {
  10. DATA_TYPE,
  11. RESOURCE_THROUGHPUT_UNIT,
  12. } from 'sentry/views/insights/browser/resources/settings';
  13. import {useResourceModuleFilters} from 'sentry/views/insights/browser/resources/utils/useResourceFilters';
  14. import {AVG_COLOR, THROUGHPUT_COLOR} from 'sentry/views/insights/colors';
  15. import Chart, {ChartType} from 'sentry/views/insights/common/components/chart';
  16. import ChartPanel from 'sentry/views/insights/common/components/chartPanel';
  17. import * as ModuleLayout from 'sentry/views/insights/common/components/moduleLayout';
  18. import {useSpanMetricsSeries} from 'sentry/views/insights/common/queries/useDiscoverSeries';
  19. import {
  20. DataTitles,
  21. getDurationChartTitle,
  22. getThroughputChartTitle,
  23. } from 'sentry/views/insights/common/views/spans/types';
  24. import {SpanMetricsField} from 'sentry/views/insights/types';
  25. const {
  26. SPAN_SELF_TIME,
  27. HTTP_RESPONSE_CONTENT_LENGTH,
  28. HTTP_DECODED_RESPONSE_CONTENT_LENGTH,
  29. HTTP_RESPONSE_TRANSFER_SIZE,
  30. RESOURCE_RENDER_BLOCKING_STATUS,
  31. } = SpanMetricsField;
  32. function ResourceSummaryCharts(props: {groupId: string}) {
  33. const filters = useResourceModuleFilters();
  34. const mutableSearch = MutableSearch.fromQueryObject({
  35. 'span.group': props.groupId,
  36. ...(filters[RESOURCE_RENDER_BLOCKING_STATUS]
  37. ? {
  38. [RESOURCE_RENDER_BLOCKING_STATUS]: filters[RESOURCE_RENDER_BLOCKING_STATUS],
  39. }
  40. : {}),
  41. ...(filters[SpanMetricsField.USER_GEO_SUBREGION]
  42. ? {
  43. [SpanMetricsField.USER_GEO_SUBREGION]: `[${filters[SpanMetricsField.USER_GEO_SUBREGION].join(',')}]`,
  44. }
  45. : {}),
  46. });
  47. const {data: spanMetricsSeriesData, isPending: areSpanMetricsSeriesLoading} =
  48. useSpanMetricsSeries(
  49. {
  50. search: mutableSearch,
  51. yAxis: [
  52. `spm()`,
  53. `avg(${SPAN_SELF_TIME})`,
  54. `avg(${HTTP_RESPONSE_CONTENT_LENGTH})`,
  55. `avg(${HTTP_DECODED_RESPONSE_CONTENT_LENGTH})`,
  56. `avg(${HTTP_RESPONSE_TRANSFER_SIZE})`,
  57. ],
  58. enabled: Boolean(props.groupId),
  59. },
  60. Referrer.RESOURCE_SUMMARY_CHARTS
  61. );
  62. if (spanMetricsSeriesData) {
  63. spanMetricsSeriesData[`avg(${HTTP_RESPONSE_TRANSFER_SIZE})`].lineStyle = {
  64. type: 'dashed',
  65. };
  66. spanMetricsSeriesData[`avg(${HTTP_DECODED_RESPONSE_CONTENT_LENGTH})`].lineStyle = {
  67. type: 'dashed',
  68. };
  69. }
  70. return (
  71. <Fragment>
  72. <ModuleLayout.Third>
  73. <ChartPanel
  74. title={getThroughputChartTitle('http', RESOURCE_THROUGHPUT_UNIT)}
  75. alertConfigs={[{...ALERTS.spm, query: mutableSearch.formatString()}]}
  76. >
  77. <Chart
  78. height={160}
  79. data={[spanMetricsSeriesData?.[`spm()`]]}
  80. loading={areSpanMetricsSeriesLoading}
  81. type={ChartType.LINE}
  82. definedAxisTicks={4}
  83. aggregateOutputFormat="rate"
  84. rateUnit={RESOURCE_THROUGHPUT_UNIT}
  85. stacked
  86. chartColors={[THROUGHPUT_COLOR]}
  87. tooltipFormatterOptions={{
  88. valueFormatter: value => formatRate(value, RESOURCE_THROUGHPUT_UNIT),
  89. nameFormatter: () => t('Requests'),
  90. }}
  91. />
  92. </ChartPanel>
  93. </ModuleLayout.Third>
  94. <ModuleLayout.Third>
  95. <ChartPanel
  96. title={getDurationChartTitle('http')}
  97. alertConfigs={[{...ALERTS.duration, query: mutableSearch.formatString()}]}
  98. >
  99. <Chart
  100. height={160}
  101. data={[spanMetricsSeriesData?.[`avg(${SPAN_SELF_TIME})`]]}
  102. loading={areSpanMetricsSeriesLoading}
  103. chartColors={[AVG_COLOR]}
  104. type={ChartType.LINE}
  105. definedAxisTicks={4}
  106. />
  107. </ChartPanel>
  108. </ModuleLayout.Third>
  109. <ModuleLayout.Third>
  110. <ChartPanel
  111. title={tct('Average [dataType] Size', {dataType: DATA_TYPE})}
  112. alertConfigs={[
  113. {...ALERTS.decodedSize, query: mutableSearch.formatString()},
  114. {...ALERTS.transferSize, query: mutableSearch.formatString()},
  115. {...ALERTS.encodedSize, query: mutableSearch.formatString()},
  116. ]}
  117. >
  118. <Chart
  119. height={160}
  120. aggregateOutputFormat="size"
  121. data={[
  122. spanMetricsSeriesData?.[`avg(${HTTP_DECODED_RESPONSE_CONTENT_LENGTH})`],
  123. spanMetricsSeriesData?.[`avg(${HTTP_RESPONSE_TRANSFER_SIZE})`],
  124. spanMetricsSeriesData?.[`avg(${HTTP_RESPONSE_CONTENT_LENGTH})`],
  125. ]}
  126. loading={areSpanMetricsSeriesLoading}
  127. chartColors={[AVG_COLOR]}
  128. type={ChartType.LINE}
  129. definedAxisTicks={4}
  130. tooltipFormatterOptions={{
  131. valueFormatter: bytes =>
  132. getDynamicText({
  133. value: formatBytesBase2(bytes),
  134. fixed: 'xx KiB',
  135. }),
  136. nameFormatter: name => DataTitles[name],
  137. }}
  138. />
  139. </ChartPanel>
  140. </ModuleLayout.Third>
  141. </Fragment>
  142. );
  143. }
  144. export default ResourceSummaryCharts;