MetricPicker.tsx 5.2 KB

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