TemplateQueryComponent.tsx 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. import React, { PureComponent } from 'react';
  2. import ServiceSelector from './ServiceSelector';
  3. import MetricTypeSelector from './MetricTypeSelector';
  4. import SimpleDropdown from './SimpleDropdown';
  5. import { TemplateQueryProps } from 'app/types/plugins';
  6. import defaultsDeep from 'lodash/defaultsDeep';
  7. import has from 'lodash/has';
  8. import { MetricFindQueryTypes } from '../types';
  9. export class StackdriverTemplateQueryComponent extends PureComponent<TemplateQueryProps, any> {
  10. queryTypes: Array<{ value: string; name: string }> = [
  11. { value: MetricFindQueryTypes.Services, name: 'Services' },
  12. { value: MetricFindQueryTypes.MetricTypes, name: 'Metric Types' },
  13. { value: MetricFindQueryTypes.MetricLabels, name: 'Metric Labels' },
  14. { value: MetricFindQueryTypes.ResourceLabels, name: 'Resource Labels' },
  15. { value: MetricFindQueryTypes.ResourceTypes, name: 'Resource Types' },
  16. { value: MetricFindQueryTypes.Aggregations, name: 'Aggregations' },
  17. { value: MetricFindQueryTypes.Alignerns, name: 'Aligners' },
  18. { value: MetricFindQueryTypes.AlignmentPeriods, name: 'Alignment Periods' },
  19. ];
  20. defaults = {
  21. type: undefined,
  22. metricDescriptors: [],
  23. service: undefined,
  24. metricType: undefined,
  25. metricLabels: [],
  26. resourceLabels: [],
  27. metricLabelKey: undefined,
  28. resourceLabelKey: undefined,
  29. };
  30. constructor(props: TemplateQueryProps) {
  31. super(props);
  32. this.handleQueryTypeChange = this.handleQueryTypeChange.bind(this);
  33. this.onServiceChange = this.onServiceChange.bind(this);
  34. this.onMetricTypeChange = this.onMetricTypeChange.bind(this);
  35. this.onMetricLabelKeyChange = this.onMetricLabelKeyChange.bind(this);
  36. this.onResourceLabelKeyChange = this.onResourceLabelKeyChange.bind(this);
  37. this.state = defaultsDeep(this.props.query, this.defaults);
  38. }
  39. async componentDidMount() {
  40. const metricDescriptors = await this.props.datasource.getMetricTypes(this.props.datasource.projectName);
  41. this.setState({ metricDescriptors });
  42. }
  43. isLabelQuery(queryType) {
  44. return [MetricFindQueryTypes.MetricLabels, MetricFindQueryTypes.ResourceLabels].indexOf(queryType) !== -1;
  45. }
  46. async loadTimeSeriesData() {
  47. const refId = 'StackdriverTemplateQueryComponent';
  48. const response = await this.props.datasource.getLabels(this.state.metricType, refId);
  49. if (this.isLabelQuery(this.state.type) && has(response, `meta.${this.state.type}`)) {
  50. this.setState({ [this.state.type]: Object.keys(response.meta[this.state.type]) });
  51. }
  52. }
  53. handleQueryTypeChange(event) {
  54. this.setState({ type: event.target.value });
  55. if (this.isLabelQuery(event.target.value)) {
  56. this.loadTimeSeriesData();
  57. }
  58. }
  59. onServiceChange(event) {
  60. this.setState({ service: event.target.value });
  61. }
  62. onMetricTypeChange(event) {
  63. this.setState({ metricType: event.target.value });
  64. if (this.isLabelQuery(this.state.type)) {
  65. this.loadTimeSeriesData();
  66. }
  67. }
  68. onMetricLabelKeyChange(event) {
  69. this.setState({ metricLabelKey: event.target.value });
  70. }
  71. onResourceLabelKeyChange(event) {
  72. this.setState({ resourceLabelKey: event.target.value });
  73. }
  74. componentDidUpdate() {
  75. const { metricDescriptors, metricLabels, resourceLabels, ...queryModel } = this.state;
  76. this.props.onChange(queryModel);
  77. }
  78. switchMetaType(queryType) {
  79. switch (queryType) {
  80. case MetricFindQueryTypes.ResourceLabels:
  81. return (
  82. <SimpleDropdown
  83. value={this.state.resourceLabelKey}
  84. options={this.state.resourceLabels}
  85. onValueChange={this.onResourceLabelKeyChange}
  86. label="Resource Labels"
  87. />
  88. );
  89. case MetricFindQueryTypes.MetricLabels:
  90. return (
  91. <SimpleDropdown
  92. value={this.state.metricLabelKey}
  93. options={this.state.metricLabels}
  94. onValueChange={this.onMetricLabelKeyChange}
  95. label="Metric Labels"
  96. />
  97. );
  98. default:
  99. return '';
  100. }
  101. }
  102. renderSwitch(queryType) {
  103. switch (queryType) {
  104. case MetricFindQueryTypes.MetricTypes:
  105. return (
  106. <ServiceSelector metricDescriptors={this.state.metricDescriptors} onServiceChange={this.onServiceChange} />
  107. );
  108. case MetricFindQueryTypes.MetricLabels:
  109. case MetricFindQueryTypes.ResourceLabels:
  110. case MetricFindQueryTypes.ResourceTypes:
  111. const dropdown = this.switchMetaType(queryType);
  112. return (
  113. <React.Fragment>
  114. <ServiceSelector metricDescriptors={this.state.metricDescriptors} onServiceChange={this.onServiceChange} />
  115. <MetricTypeSelector
  116. selectedService={this.state.service}
  117. metricDescriptors={this.state.metricDescriptors}
  118. onMetricTypeChange={this.onMetricTypeChange}
  119. />
  120. {dropdown}
  121. </React.Fragment>
  122. );
  123. case MetricFindQueryTypes.Alignerns:
  124. case MetricFindQueryTypes.Aggregations:
  125. return (
  126. <React.Fragment>
  127. <ServiceSelector metricDescriptors={this.state.metricDescriptors} onServiceChange={this.onServiceChange} />
  128. <MetricTypeSelector
  129. selectedService={this.state.service}
  130. metricDescriptors={this.state.metricDescriptors}
  131. onMetricTypeChange={this.onMetricTypeChange}
  132. />
  133. </React.Fragment>
  134. );
  135. default:
  136. return '';
  137. }
  138. }
  139. render() {
  140. return (
  141. <React.Fragment>
  142. <div className="gf-form max-width-21">
  143. <span className="gf-form-label width-7">Query Type</span>
  144. <div className="gf-form-select-wrapper max-width-14">
  145. <select className="gf-form-input" required onChange={this.handleQueryTypeChange}>
  146. {this.queryTypes.map((qt, i) => (
  147. <option key={i} value={qt.value} ng-if="false">
  148. {qt.name}
  149. </option>
  150. ))}
  151. </select>
  152. </div>
  153. </div>
  154. {this.renderSwitch(this.state.type)}
  155. </React.Fragment>
  156. );
  157. }
  158. }