apiChart.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import {Component} from 'react';
  2. import type {Client} from 'sentry/api';
  3. import MiniBarChart from 'sentry/components/charts/miniBarChart';
  4. import LoadingError from 'sentry/components/loadingError';
  5. import LoadingIndicator from 'sentry/components/loadingIndicator';
  6. import type {TimeseriesValue} from 'sentry/types';
  7. import theme from 'sentry/utils/theme';
  8. import withApi from 'sentry/utils/withApi';
  9. const initialState = {
  10. error: false,
  11. loading: true,
  12. rawData: {
  13. 'client-api.all-versions.responses.2xx': [],
  14. 'client-api.all-versions.responses.4xx': [],
  15. 'client-api.all-versions.responses.5xx': [],
  16. },
  17. };
  18. type Props = {
  19. api: Client;
  20. resolution: string;
  21. since: number;
  22. };
  23. type State = {
  24. error: boolean;
  25. loading: boolean;
  26. rawData: Record<string, TimeseriesValue[]>;
  27. };
  28. class ApiChart extends Component<Props, State> {
  29. state: State = initialState;
  30. UNSAFE_componentWillMount() {
  31. this.fetchData();
  32. }
  33. UNSAFE_componentWillReceiveProps(nextProps: Props) {
  34. if (this.props.since !== nextProps.since) {
  35. this.setState(initialState, this.fetchData);
  36. }
  37. }
  38. fetchData = () => {
  39. const statNameList = [
  40. 'client-api.all-versions.responses.2xx',
  41. 'client-api.all-versions.responses.4xx',
  42. 'client-api.all-versions.responses.5xx',
  43. ];
  44. statNameList.forEach(statName => {
  45. this.props.api.request('/internal/stats/', {
  46. method: 'GET',
  47. data: {
  48. since: this.props.since,
  49. resolution: this.props.resolution,
  50. key: statName,
  51. },
  52. success: data => {
  53. this.setState(prevState => {
  54. const rawData = prevState.rawData;
  55. rawData[statName] = data;
  56. return {
  57. rawData,
  58. };
  59. }, this.requestFinished);
  60. },
  61. error: () => {
  62. this.setState({
  63. error: true,
  64. });
  65. },
  66. });
  67. });
  68. };
  69. requestFinished = () => {
  70. const {rawData} = this.state;
  71. if (
  72. rawData['client-api.all-versions.responses.2xx'] &&
  73. rawData['client-api.all-versions.responses.4xx'] &&
  74. rawData['client-api.all-versions.responses.5xx']
  75. ) {
  76. this.setState({
  77. loading: false,
  78. });
  79. }
  80. };
  81. processRawSeries(series: TimeseriesValue[]) {
  82. return series.map(item => ({name: item[0] * 1000, value: item[1]}));
  83. }
  84. getChartSeries() {
  85. const {rawData} = this.state;
  86. return [
  87. {
  88. seriesName: '2xx',
  89. data: this.processRawSeries(rawData['client-api.all-versions.responses.2xx']),
  90. color: theme.green200,
  91. },
  92. {
  93. seriesName: '4xx',
  94. data: this.processRawSeries(rawData['client-api.all-versions.responses.4xx']),
  95. color: theme.blue300,
  96. },
  97. {
  98. seriesName: '5xx',
  99. data: this.processRawSeries(rawData['client-api.all-versions.responses.5xx']),
  100. color: theme.red200,
  101. },
  102. ];
  103. }
  104. render() {
  105. const {loading, error} = this.state;
  106. if (loading) {
  107. return <LoadingIndicator />;
  108. }
  109. if (error) {
  110. return <LoadingError onRetry={this.fetchData} />;
  111. }
  112. const series = this.getChartSeries();
  113. const colors = series.map(({color}) => color);
  114. return (
  115. <MiniBarChart
  116. series={series}
  117. colors={colors}
  118. height={110}
  119. stacked
  120. isGroupedByDate
  121. showTimeInTooltip
  122. labelYAxisExtents
  123. />
  124. );
  125. }
  126. }
  127. export default withApi(ApiChart);