query_ctrl.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import _ from 'lodash';
  2. import { QueryCtrl } from 'app/plugins/sdk';
  3. import appEvents from 'app/core/app_events';
  4. export interface QueryMeta {
  5. rawQuery: string;
  6. rawQueryString: string;
  7. }
  8. export class StackdriverQueryCtrl extends QueryCtrl {
  9. static templateUrl = 'partials/query.editor.html';
  10. target: {
  11. project: {
  12. id: string;
  13. name: string;
  14. };
  15. metricType: string;
  16. refId: string;
  17. };
  18. defaultDropdownValue = 'Select metric';
  19. defaults = {
  20. project: {
  21. id: 'default',
  22. name: 'loading project...',
  23. },
  24. metricType: this.defaultDropdownValue,
  25. aggregation: 'REDUCE_MEAN',
  26. };
  27. aggOptions = [
  28. { text: 'none', value: 'REDUCE_NONE' },
  29. { text: 'mean', value: 'REDUCE_MEAN' },
  30. { text: 'min', value: 'REDUCE_MIN' },
  31. { text: 'max', value: 'REDUCE_MAX' },
  32. { text: 'sum', value: 'REDUCE_SUM' },
  33. { text: 'std. dev.', value: 'REDUCE_STDDEV' },
  34. { text: 'count', value: 'REDUCE_COUNT' },
  35. { text: '99th percentile', value: 'REDUCE_PERCENTILE_99' },
  36. { text: '95th percentile', value: 'REDUCE_PERCENTILE_95' },
  37. { text: '50th percentile', value: 'REDUCE_PERCENTILE_50' },
  38. { text: '5th percentile', value: 'REDUCE_PERCENTILE_05' },
  39. ];
  40. showHelp: boolean;
  41. showLastQuery: boolean;
  42. lastQueryMeta: QueryMeta;
  43. lastQueryError?: string;
  44. /** @ngInject */
  45. constructor($scope, $injector) {
  46. super($scope, $injector);
  47. _.defaultsDeep(this.target, this.defaults);
  48. this.panelCtrl.events.on('data-received', this.onDataReceived.bind(this), $scope);
  49. this.panelCtrl.events.on('data-error', this.onDataError.bind(this), $scope);
  50. this.getCurrentProject().then(this.getMetricTypes.bind(this));
  51. }
  52. async getCurrentProject() {
  53. try {
  54. const projects = await this.datasource.getProjects();
  55. if (projects && projects.length > 0) {
  56. this.target.project = projects[0];
  57. } else {
  58. throw new Error('No projects found');
  59. }
  60. } catch (error) {
  61. let message = 'Projects cannot be fetched: ';
  62. message += error.statusText ? error.statusText + ': ' : '';
  63. if (error && error.data && error.data.error && error.data.error.message) {
  64. if (error.data.error.code === 403) {
  65. message += `
  66. A list of projects could not be fetched from the Google Cloud Resource Manager API.
  67. You might need to enable it first:
  68. https://console.developers.google.com/apis/library/cloudresourcemanager.googleapis.com`;
  69. } else {
  70. message += error.data.error.code + '. ' + error.data.error.message;
  71. }
  72. } else {
  73. message += 'Cannot connect to Stackdriver API';
  74. }
  75. appEvents.emit('ds-request-error', message);
  76. }
  77. }
  78. async getMetricTypes() {
  79. //projects/raintank-production/metricDescriptors/agent.googleapis.com/agent/api_request_count
  80. if (this.target.project.id !== 'default') {
  81. const metricTypes = await this.datasource.getMetricTypes(this.target.project.id);
  82. if (this.target.metricType === this.defaultDropdownValue && metricTypes.length > 0) {
  83. this.$scope.$apply(() => (this.target.metricType = metricTypes[0].name));
  84. }
  85. return metricTypes.map(mt => ({ value: mt.id, text: mt.id }));
  86. } else {
  87. return [];
  88. }
  89. }
  90. onDataReceived(dataList) {
  91. this.lastQueryError = null;
  92. this.lastQueryMeta = null;
  93. const anySeriesFromQuery: any = _.find(dataList, { refId: this.target.refId });
  94. if (anySeriesFromQuery) {
  95. this.lastQueryMeta = anySeriesFromQuery.meta;
  96. this.lastQueryMeta.rawQueryString = decodeURIComponent(this.lastQueryMeta.rawQuery);
  97. }
  98. }
  99. onDataError(err) {
  100. if (err.data && err.data.results) {
  101. const queryRes = err.data.results[this.target.refId];
  102. if (queryRes) {
  103. this.lastQueryMeta = queryRes.meta;
  104. this.lastQueryMeta.rawQueryString = decodeURIComponent(this.lastQueryMeta.rawQuery);
  105. let jsonBody;
  106. try {
  107. jsonBody = JSON.parse(queryRes.error);
  108. } catch {
  109. this.lastQueryError = queryRes.error;
  110. }
  111. this.lastQueryError = jsonBody.error.message;
  112. }
  113. }
  114. }
  115. }