adminQueue.tsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import styled from '@emotion/styled';
  2. import {Button} from 'sentry/components/button';
  3. import ButtonBar from 'sentry/components/buttonBar';
  4. import SelectControl from 'sentry/components/forms/controls/selectControl';
  5. import InternalStatChart from 'sentry/components/internalStatChart';
  6. import Panel from 'sentry/components/panels/panel';
  7. import PanelBody from 'sentry/components/panels/panelBody';
  8. import PanelHeader from 'sentry/components/panels/panelHeader';
  9. import DeprecatedAsyncView from 'sentry/views/deprecatedAsyncView';
  10. const TIME_WINDOWS = ['1h', '1d', '1w'] as const;
  11. type TimeWindow = (typeof TIME_WINDOWS)[number];
  12. type State = DeprecatedAsyncView['state'] & {
  13. activeTask: string;
  14. resolution: string;
  15. since: number;
  16. taskList: string[];
  17. taskName: string;
  18. timeWindow: TimeWindow;
  19. };
  20. export default class AdminQueue extends DeprecatedAsyncView<{}, State> {
  21. getDefaultState() {
  22. return {
  23. ...super.getDefaultState(),
  24. timeWindow: '1w',
  25. since: new Date().getTime() / 1000 - 3600 * 24 * 7,
  26. resolution: '1h',
  27. taskName: null,
  28. };
  29. }
  30. getEndpoints(): ReturnType<DeprecatedAsyncView['getEndpoints']> {
  31. return [['taskList', '/internal/queue/tasks/']];
  32. }
  33. changeWindow(timeWindow: TimeWindow) {
  34. let seconds: number;
  35. if (timeWindow === '1h') {
  36. seconds = 3600;
  37. } else if (timeWindow === '1d') {
  38. seconds = 3600 * 24;
  39. } else if (timeWindow === '1w') {
  40. seconds = 3600 * 24 * 7;
  41. } else {
  42. throw new Error('Invalid time window');
  43. }
  44. this.setState({
  45. since: new Date().getTime() / 1000 - seconds,
  46. timeWindow,
  47. });
  48. }
  49. changeTask(value: string) {
  50. this.setState({activeTask: value});
  51. }
  52. renderBody() {
  53. const {activeTask, taskList} = this.state;
  54. return (
  55. <div>
  56. <Header>
  57. <h3>Queue Overview</h3>
  58. <ButtonBar merged active={this.state.timeWindow}>
  59. {TIME_WINDOWS.map(r => (
  60. <Button size="sm" barId={r} onClick={() => this.changeWindow(r)} key={r}>
  61. {r}
  62. </Button>
  63. ))}
  64. </ButtonBar>
  65. </Header>
  66. <Panel>
  67. <PanelHeader>Global Throughput</PanelHeader>
  68. <PanelBody withPadding>
  69. <InternalStatChart
  70. since={this.state.since}
  71. resolution={this.state.resolution}
  72. stat="jobs.all.started"
  73. label="jobs started"
  74. />
  75. </PanelBody>
  76. </Panel>
  77. <h3>Task Details</h3>
  78. <div>
  79. <div className="m-b-1">
  80. <label>Show details for task:</label>
  81. <SelectControl
  82. name="task"
  83. onChange={({value}) => this.changeTask(value)}
  84. value={activeTask}
  85. clearable
  86. options={taskList.map(value => ({value, label: value}))}
  87. />
  88. </div>
  89. {activeTask ? (
  90. <div>
  91. <Panel key={`jobs.started.${activeTask}`}>
  92. <PanelHeader>
  93. Jobs Started <small>{activeTask}</small>
  94. </PanelHeader>
  95. <PanelBody withPadding>
  96. <InternalStatChart
  97. since={this.state.since}
  98. resolution={this.state.resolution}
  99. stat={`jobs.started.${activeTask}`}
  100. label="jobs"
  101. height={100}
  102. />
  103. </PanelBody>
  104. </Panel>
  105. <Panel key={`jobs.finished.${activeTask}`}>
  106. <PanelHeader>
  107. Jobs Finished <small>{activeTask}</small>
  108. </PanelHeader>
  109. <PanelBody withPadding>
  110. <InternalStatChart
  111. since={this.state.since}
  112. resolution={this.state.resolution}
  113. stat={`jobs.finished.${activeTask}`}
  114. label="jobs"
  115. height={100}
  116. />
  117. </PanelBody>
  118. </Panel>
  119. </div>
  120. ) : null}
  121. </div>
  122. </div>
  123. );
  124. }
  125. }
  126. const Header = styled('div')`
  127. display: flex;
  128. justify-content: space-between;
  129. align-items: center;
  130. `;