MetricPicker.tsx 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. import React from 'react';
  2. import _ from 'lodash';
  3. import { StackdriverPicker } from './StackdriverPicker';
  4. export interface Props {
  5. onChange: (metricDescriptor) => void;
  6. templateSrv: any;
  7. datasource: any;
  8. defaultProject: string;
  9. metricType: string;
  10. }
  11. interface State {
  12. metricDescriptors: any[];
  13. metrics: any[];
  14. services: any[];
  15. service: string;
  16. metric: string;
  17. }
  18. export class MetricPicker extends React.Component<Props, State> {
  19. state: State = {
  20. metricDescriptors: [],
  21. metrics: [],
  22. services: [],
  23. service: '',
  24. metric: '',
  25. };
  26. constructor(props) {
  27. super(props);
  28. }
  29. componentDidMount() {
  30. this.getCurrentProject()
  31. .then(this.loadMetricDescriptors.bind(this))
  32. .then(this.initializeServiceAndMetrics.bind(this));
  33. // .then(this.getLabels.bind(this));
  34. }
  35. async getCurrentProject() {
  36. return new Promise(async (resolve, reject) => {
  37. try {
  38. if (!this.props.defaultProject || this.props.defaultProject === 'loading project...') {
  39. // this.props.defaultProject = await this.props.datasource.getDefaultProject();
  40. await this.props.datasource.getDefaultProject();
  41. }
  42. resolve(this.props.defaultProject);
  43. } catch (error) {
  44. // appEvents.emit('ds-request-error', error);
  45. reject();
  46. }
  47. });
  48. }
  49. async loadMetricDescriptors() {
  50. if (this.props.defaultProject !== 'loading project...') {
  51. const metricDescriptors = await this.props.datasource.getMetricTypes(this.props.defaultProject);
  52. this.setState({ metricDescriptors });
  53. return metricDescriptors;
  54. } else {
  55. return [];
  56. }
  57. }
  58. async initializeServiceAndMetrics() {
  59. const { metricDescriptors } = this.state;
  60. const services = this.getServicesList(metricDescriptors);
  61. const metrics = this.getMetricsList(metricDescriptors);
  62. const service = metrics.length > 0 ? metrics[0].service : '';
  63. this.setState({ metricDescriptors, services, metrics, service: service });
  64. }
  65. getMetricsList(metricDescriptors) {
  66. const selectedMetricDescriptor = metricDescriptors.find(
  67. md => md.type === this.props.templateSrv.replace(this.props.metricType)
  68. );
  69. const metricsByService = metricDescriptors.filter(m => m.service === selectedMetricDescriptor.service).map(m => ({
  70. service: m.service,
  71. value: m.type,
  72. label: m.displayName,
  73. description: m.description,
  74. }));
  75. return metricsByService;
  76. }
  77. handleServiceChange(service) {
  78. console.log('handleServiceChange', service);
  79. const { metricDescriptors } = this.state;
  80. const { templateSrv, metricType } = this.props;
  81. const metrics = metricDescriptors.filter(m => m.service === templateSrv.replace(service)).map(m => ({
  82. service: m.service,
  83. value: m.type,
  84. label: m.displayName,
  85. description: m.description,
  86. }));
  87. this.setState({ service, metrics });
  88. if (metrics.length > 0 && !metrics.some(m => m.value === templateSrv.replace(metricType))) {
  89. this.handleMetricTypeChange(metrics[0].value);
  90. }
  91. }
  92. handleMetricTypeChange(value) {
  93. const selectedMetricDescriptor = this.state.metricDescriptors.find(md => md.type === value);
  94. this.props.onChange(selectedMetricDescriptor);
  95. }
  96. getServicesList(metricDescriptors) {
  97. const services = metricDescriptors.map(m => ({
  98. value: m.service,
  99. label: _.startCase(m.serviceShortName),
  100. }));
  101. return services.length > 0 ? _.uniqBy(services, s => s.value) : [];
  102. }
  103. getTemplateVariablesGroup() {
  104. return {
  105. label: 'Template Variables',
  106. options: this.props.templateSrv.variables.map(v => ({
  107. label: `$${v.name}`,
  108. value: `$${v.name}`,
  109. })),
  110. };
  111. }
  112. getMetricGroups() {
  113. return [
  114. this.getTemplateVariablesGroup(),
  115. {
  116. label: 'Metrics',
  117. options: this.state.metrics,
  118. },
  119. ];
  120. }
  121. render() {
  122. const { services, service } = this.state;
  123. const { metricType } = this.props;
  124. return (
  125. <React.Fragment>
  126. <div className="gf-form-inline">
  127. <div className="gf-form">
  128. <span className="gf-form-label width-9 query-keyword">Service</span>
  129. <StackdriverPicker
  130. onChange={value => this.handleServiceChange(value)}
  131. selected={service}
  132. options={services}
  133. searchable={false}
  134. placeholder="Select Services"
  135. className="width-15"
  136. />
  137. </div>
  138. <div className="gf-form gf-form--grow">
  139. <div className="gf-form-label gf-form-label--grow" />
  140. </div>
  141. </div>
  142. <div className="gf-form-inline">
  143. <div className="gf-form">
  144. <span className="gf-form-label width-9 query-keyword">Metric</span>
  145. <StackdriverPicker
  146. onChange={value => this.handleMetricTypeChange(value)}
  147. selected={metricType}
  148. options={this.getMetricGroups()}
  149. searchable={true}
  150. placeholder="Select Metric"
  151. className="width-15"
  152. />
  153. </div>
  154. <div className="gf-form gf-form--grow">
  155. <div className="gf-form-label gf-form-label--grow" />
  156. </div>
  157. </div>
  158. </React.Fragment>
  159. );
  160. }
  161. }