Metrics.tsx 5.4 KB

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