| 
									
										
										
										
											2018-09-07 23:18:15 +08:00
										 |  |  | import _ from 'lodash'; | 
					
						
							| 
									
										
										
										
											2018-09-04 19:21:02 +08:00
										 |  |  | import { QueryCtrl } from 'app/plugins/sdk'; | 
					
						
							| 
									
										
										
										
											2018-09-07 23:18:15 +08:00
										 |  |  | import appEvents from 'app/core/app_events'; | 
					
						
							| 
									
										
										
										
											2018-09-04 19:21:02 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 04:41:24 +08:00
										 |  |  | export interface QueryMeta { | 
					
						
							|  |  |  |   rawQuery: string; | 
					
						
							|  |  |  |   rawQueryString: string; | 
					
						
							| 
									
										
										
										
											2018-09-14 05:51:45 +08:00
										 |  |  |   metricLabels: { [key: string]: string[] }; | 
					
						
							|  |  |  |   resourceLabels: { [key: string]: string[] }; | 
					
						
							| 
									
										
										
										
											2018-09-12 04:41:24 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-09-14 07:49:39 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-04 19:21:02 +08:00
										 |  |  | export class StackdriverQueryCtrl extends QueryCtrl { | 
					
						
							|  |  |  |   static templateUrl = 'partials/query.editor.html'; | 
					
						
							| 
									
										
										
										
											2018-09-10 04:53:35 +08:00
										 |  |  |   target: { | 
					
						
							|  |  |  |     project: { | 
					
						
							|  |  |  |       id: string; | 
					
						
							|  |  |  |       name: string; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  |     metricType: string; | 
					
						
							| 
									
										
										
										
											2018-09-12 04:41:24 +08:00
										 |  |  |     refId: string; | 
					
						
							| 
									
										
										
										
											2018-09-13 17:02:31 +08:00
										 |  |  |     aggregation: { | 
					
						
							|  |  |  |       crossSeriesReducer: string; | 
					
						
							|  |  |  |       alignmentPeriod: string; | 
					
						
							|  |  |  |       perSeriesAligner: string; | 
					
						
							|  |  |  |       groupBys: string[]; | 
					
						
							|  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2018-09-14 21:44:12 +08:00
										 |  |  |     filters: string[]; | 
					
						
							| 
									
										
										
										
											2018-09-07 23:18:15 +08:00
										 |  |  |   }; | 
					
						
							| 
									
										
										
										
											2018-09-14 21:44:12 +08:00
										 |  |  |   defaultDropdownValue = 'select metric'; | 
					
						
							|  |  |  |   defaultFilterValue = 'select value'; | 
					
						
							|  |  |  |   defaultRemoveGroupByValue = '-- remove group by --'; | 
					
						
							|  |  |  |   defaultRemoveFilterValue = '-- remove filter --'; | 
					
						
							| 
									
										
										
										
											2018-09-17 17:28:10 +08:00
										 |  |  |   loadLabelsPromise: Promise<any>; | 
					
						
							| 
									
										
										
										
											2018-09-07 23:18:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-11 01:08:39 +08:00
										 |  |  |   defaults = { | 
					
						
							|  |  |  |     project: { | 
					
						
							|  |  |  |       id: 'default', | 
					
						
							|  |  |  |       name: 'loading project...', | 
					
						
							|  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2018-09-12 06:24:59 +08:00
										 |  |  |     metricType: this.defaultDropdownValue, | 
					
						
							| 
									
										
										
										
											2018-09-13 17:02:31 +08:00
										 |  |  |     aggregation: { | 
					
						
							|  |  |  |       crossSeriesReducer: 'REDUCE_MEAN', | 
					
						
							|  |  |  |       alignmentPeriod: '', | 
					
						
							|  |  |  |       perSeriesAligner: '', | 
					
						
							|  |  |  |       groupBys: [], | 
					
						
							|  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2018-09-14 07:49:39 +08:00
										 |  |  |     filters: [], | 
					
						
							| 
									
										
										
										
											2018-09-11 01:08:39 +08:00
										 |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-13 17:02:31 +08:00
										 |  |  |   groupBySegments: any[]; | 
					
						
							| 
									
										
										
										
											2018-09-14 07:49:39 +08:00
										 |  |  |   filterSegments: any[]; | 
					
						
							|  |  |  |   removeSegment: any; | 
					
						
							| 
									
										
										
										
											2018-09-13 17:02:31 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 06:24:59 +08:00
										 |  |  |   aggOptions = [ | 
					
						
							|  |  |  |     { text: 'none', value: 'REDUCE_NONE' }, | 
					
						
							|  |  |  |     { text: 'mean', value: 'REDUCE_MEAN' }, | 
					
						
							|  |  |  |     { text: 'min', value: 'REDUCE_MIN' }, | 
					
						
							|  |  |  |     { text: 'max', value: 'REDUCE_MAX' }, | 
					
						
							|  |  |  |     { text: 'sum', value: 'REDUCE_SUM' }, | 
					
						
							|  |  |  |     { text: 'std. dev.', value: 'REDUCE_STDDEV' }, | 
					
						
							|  |  |  |     { text: 'count', value: 'REDUCE_COUNT' }, | 
					
						
							|  |  |  |     { text: '99th percentile', value: 'REDUCE_PERCENTILE_99' }, | 
					
						
							|  |  |  |     { text: '95th percentile', value: 'REDUCE_PERCENTILE_95' }, | 
					
						
							|  |  |  |     { text: '50th percentile', value: 'REDUCE_PERCENTILE_50' }, | 
					
						
							|  |  |  |     { text: '5th percentile', value: 'REDUCE_PERCENTILE_05' }, | 
					
						
							|  |  |  |   ]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 04:41:24 +08:00
										 |  |  |   showHelp: boolean; | 
					
						
							|  |  |  |   showLastQuery: boolean; | 
					
						
							|  |  |  |   lastQueryMeta: QueryMeta; | 
					
						
							|  |  |  |   lastQueryError?: string; | 
					
						
							| 
									
										
										
										
											2018-09-14 07:49:39 +08:00
										 |  |  |   metricLabels: { [key: string]: string[] }; | 
					
						
							|  |  |  |   resourceLabels: { [key: string]: string[] }; | 
					
						
							| 
									
										
										
										
											2018-09-12 04:41:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-04 19:21:02 +08:00
										 |  |  |   /** @ngInject */ | 
					
						
							| 
									
										
										
										
											2018-09-14 00:22:48 +08:00
										 |  |  |   constructor($scope, $injector, private uiSegmentSrv, private timeSrv) { | 
					
						
							| 
									
										
										
										
											2018-09-04 19:21:02 +08:00
										 |  |  |     super($scope, $injector); | 
					
						
							| 
									
										
										
										
											2018-09-11 01:08:39 +08:00
										 |  |  |     _.defaultsDeep(this.target, this.defaults); | 
					
						
							| 
									
										
										
										
											2018-09-12 04:41:24 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     this.panelCtrl.events.on('data-received', this.onDataReceived.bind(this), $scope); | 
					
						
							|  |  |  |     this.panelCtrl.events.on('data-error', this.onDataError.bind(this), $scope); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-17 17:28:10 +08:00
										 |  |  |     this.getCurrentProject() | 
					
						
							|  |  |  |       .then(this.getMetricTypes.bind(this)) | 
					
						
							|  |  |  |       .then(this.getLabels.bind(this)); | 
					
						
							| 
									
										
										
										
											2018-09-13 17:02:31 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-14 07:49:39 +08:00
										 |  |  |     this.initSegments(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   initSegments() { | 
					
						
							| 
									
										
										
										
											2018-09-14 00:22:48 +08:00
										 |  |  |     this.groupBySegments = this.target.aggregation.groupBys.map(groupBy => { | 
					
						
							| 
									
										
										
										
											2018-09-14 07:49:39 +08:00
										 |  |  |       return this.uiSegmentSrv.getSegmentForValue(groupBy); | 
					
						
							| 
									
										
										
										
											2018-09-13 17:02:31 +08:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2018-09-14 07:49:39 +08:00
										 |  |  |     this.removeSegment = this.uiSegmentSrv.newSegment({ fake: true, value: '-- remove group by --' }); | 
					
						
							| 
									
										
										
										
											2018-09-13 17:02:31 +08:00
										 |  |  |     this.ensurePlusButton(this.groupBySegments); | 
					
						
							| 
									
										
										
										
											2018-09-14 07:49:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     this.filterSegments = []; | 
					
						
							| 
									
										
										
										
											2018-09-14 21:44:12 +08:00
										 |  |  |     this.target.filters.forEach((f, index) => { | 
					
						
							|  |  |  |       switch (index % 4) { | 
					
						
							|  |  |  |         case 0: | 
					
						
							|  |  |  |           this.filterSegments.push(this.uiSegmentSrv.newKey(f)); | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         case 1: | 
					
						
							|  |  |  |           this.filterSegments.push(this.uiSegmentSrv.newOperator(f)); | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         case 2: | 
					
						
							|  |  |  |           this.filterSegments.push(this.uiSegmentSrv.newKeyValue(f)); | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         case 3: | 
					
						
							|  |  |  |           this.filterSegments.push(this.uiSegmentSrv.newCondition(f)); | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2018-09-14 07:49:39 +08:00
										 |  |  |     }); | 
					
						
							|  |  |  |     this.ensurePlusButton(this.filterSegments); | 
					
						
							| 
									
										
										
										
											2018-09-07 23:18:15 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   async getCurrentProject() { | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |       const projects = await this.datasource.getProjects(); | 
					
						
							|  |  |  |       if (projects && projects.length > 0) { | 
					
						
							| 
									
										
										
										
											2018-09-11 01:16:19 +08:00
										 |  |  |         this.target.project = projects[0]; | 
					
						
							| 
									
										
										
										
											2018-09-07 23:18:15 +08:00
										 |  |  |       } else { | 
					
						
							|  |  |  |         throw new Error('No projects found'); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } catch (error) { | 
					
						
							|  |  |  |       let message = 'Projects cannot be fetched: '; | 
					
						
							|  |  |  |       message += error.statusText ? error.statusText + ': ' : ''; | 
					
						
							|  |  |  |       if (error && error.data && error.data.error && error.data.error.message) { | 
					
						
							|  |  |  |         if (error.data.error.code === 403) { | 
					
						
							|  |  |  |           message += `
 | 
					
						
							|  |  |  |             A list of projects could not be fetched from the Google Cloud Resource Manager API. | 
					
						
							|  |  |  |             You might need to enable it first: | 
					
						
							|  |  |  |             https://console.developers.google.com/apis/library/cloudresourcemanager.googleapis.com`;
 | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |           message += error.data.error.code + '. ' + error.data.error.message; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         message += 'Cannot connect to Stackdriver API'; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       appEvents.emit('ds-request-error', message); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   async getMetricTypes() { | 
					
						
							|  |  |  |     //projects/raintank-production/metricDescriptors/agent.googleapis.com/agent/api_request_count
 | 
					
						
							| 
									
										
										
										
											2018-09-10 04:53:35 +08:00
										 |  |  |     if (this.target.project.id !== 'default') { | 
					
						
							|  |  |  |       const metricTypes = await this.datasource.getMetricTypes(this.target.project.id); | 
					
						
							|  |  |  |       if (this.target.metricType === this.defaultDropdownValue && metricTypes.length > 0) { | 
					
						
							| 
									
										
										
										
											2018-09-15 01:28:48 +08:00
										 |  |  |         this.$scope.$apply(() => (this.target.metricType = metricTypes[0].id)); | 
					
						
							| 
									
										
										
										
											2018-09-07 23:18:15 +08:00
										 |  |  |       } | 
					
						
							|  |  |  |       return metricTypes.map(mt => ({ value: mt.id, text: mt.id })); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       return []; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-09-04 19:21:02 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-09-12 04:41:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-14 00:22:48 +08:00
										 |  |  |   async getLabels() { | 
					
						
							| 
									
										
										
										
											2018-09-17 17:28:10 +08:00
										 |  |  |     this.loadLabelsPromise = new Promise(async resolve => { | 
					
						
							|  |  |  |       try { | 
					
						
							|  |  |  |         const data = await this.datasource.getTimeSeries({ | 
					
						
							|  |  |  |           targets: [ | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |               refId: this.target.refId, | 
					
						
							|  |  |  |               datasourceId: this.datasource.id, | 
					
						
							|  |  |  |               metricType: this.target.metricType, | 
					
						
							|  |  |  |               aggregation: { | 
					
						
							|  |  |  |                 crossSeriesReducer: 'REDUCE_NONE', | 
					
						
							|  |  |  |               }, | 
					
						
							|  |  |  |               view: 'HEADERS', | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |           ], | 
					
						
							|  |  |  |           range: this.timeSrv.timeRange(), | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2018-09-14 00:22:48 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-17 17:28:10 +08:00
										 |  |  |         this.metricLabels = data.results[this.target.refId].meta.metricLabels; | 
					
						
							|  |  |  |         this.resourceLabels = data.results[this.target.refId].meta.resourceLabels; | 
					
						
							|  |  |  |         resolve(); | 
					
						
							|  |  |  |       } catch (error) { | 
					
						
							|  |  |  |         resolve(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2018-09-14 00:22:48 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   async onMetricTypeChange() { | 
					
						
							|  |  |  |     this.refresh(); | 
					
						
							|  |  |  |     this.getLabels(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-14 23:19:15 +08:00
										 |  |  |   async getGroupBys(segment, index, removeText?: string, removeUsed = true) { | 
					
						
							| 
									
										
										
										
											2018-09-17 17:28:10 +08:00
										 |  |  |     await this.loadLabelsPromise; | 
					
						
							| 
									
										
										
										
											2018-09-14 05:51:45 +08:00
										 |  |  |     const metricLabels = Object.keys(this.metricLabels) | 
					
						
							|  |  |  |       .filter(ml => { | 
					
						
							| 
									
										
										
										
											2018-09-14 21:44:12 +08:00
										 |  |  |         if (!removeUsed) { | 
					
						
							|  |  |  |           return true; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-09-14 05:51:45 +08:00
										 |  |  |         return this.target.aggregation.groupBys.indexOf('metric.label.' + ml) === -1; | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |       .map(l => { | 
					
						
							|  |  |  |         return this.uiSegmentSrv.newSegment({ | 
					
						
							|  |  |  |           value: `metric.label.${l}`, | 
					
						
							|  |  |  |           expandable: false, | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2018-09-14 00:22:48 +08:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-14 05:51:45 +08:00
										 |  |  |     const resourceLabels = Object.keys(this.resourceLabels) | 
					
						
							|  |  |  |       .filter(ml => { | 
					
						
							| 
									
										
										
										
											2018-09-14 21:44:12 +08:00
										 |  |  |         if (!removeUsed) { | 
					
						
							|  |  |  |           return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-14 05:51:45 +08:00
										 |  |  |         return this.target.aggregation.groupBys.indexOf('resource.label.' + ml) === -1; | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |       .map(l => { | 
					
						
							|  |  |  |         return this.uiSegmentSrv.newSegment({ | 
					
						
							|  |  |  |           value: `resource.label.${l}`, | 
					
						
							|  |  |  |           expandable: false, | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2018-09-14 00:22:48 +08:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2018-09-13 17:02:31 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-15 01:28:48 +08:00
										 |  |  |     const noValueOrPlusButton = !segment || segment.type === 'plus-button'; | 
					
						
							|  |  |  |     if (noValueOrPlusButton && metricLabels.length === 0 && resourceLabels.length === 0) { | 
					
						
							|  |  |  |       return Promise.resolve([]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-14 21:44:12 +08:00
										 |  |  |     this.removeSegment.value = removeText || this.defaultRemoveGroupByValue; | 
					
						
							| 
									
										
										
										
											2018-09-14 06:13:23 +08:00
										 |  |  |     return Promise.resolve([...metricLabels, ...resourceLabels, this.removeSegment]); | 
					
						
							| 
									
										
										
										
											2018-09-13 17:02:31 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-14 06:13:23 +08:00
										 |  |  |   groupByChanged(segment, index) { | 
					
						
							|  |  |  |     if (segment.value === this.removeSegment.value) { | 
					
						
							|  |  |  |       this.groupBySegments.splice(index, 1); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       segment.type = 'value'; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-09-14 05:51:45 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const reducer = (memo, seg) => { | 
					
						
							|  |  |  |       if (!seg.fake) { | 
					
						
							|  |  |  |         memo.push(seg.value); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return memo; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     this.target.aggregation.groupBys = this.groupBySegments.reduce(reducer, []); | 
					
						
							| 
									
										
										
										
											2018-09-13 17:02:31 +08:00
										 |  |  |     this.ensurePlusButton(this.groupBySegments); | 
					
						
							| 
									
										
										
										
											2018-09-14 00:22:48 +08:00
										 |  |  |     this.refresh(); | 
					
						
							| 
									
										
										
										
											2018-09-13 17:02:31 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-14 21:44:12 +08:00
										 |  |  |   async getFilters(segment, index) { | 
					
						
							| 
									
										
										
										
											2018-09-14 07:49:39 +08:00
										 |  |  |     if (segment.type === 'condition') { | 
					
						
							|  |  |  |       return [this.uiSegmentSrv.newSegment('AND')]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (segment.type === 'operator') { | 
					
						
							|  |  |  |       return this.uiSegmentSrv.newOperators(['=', '!=', '=~', '!=~']); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (segment.type === 'key' || segment.type === 'plus-button') { | 
					
						
							| 
									
										
										
										
											2018-09-17 17:28:10 +08:00
										 |  |  |       if ( | 
					
						
							|  |  |  |         this.metricLabels && | 
					
						
							|  |  |  |         Object.keys(this.metricLabels).length === 0 && | 
					
						
							|  |  |  |         segment.value && | 
					
						
							|  |  |  |         segment.value !== this.defaultRemoveFilterValue | 
					
						
							|  |  |  |       ) { | 
					
						
							|  |  |  |         this.removeSegment.value = this.defaultRemoveFilterValue; | 
					
						
							|  |  |  |         return Promise.resolve([this.removeSegment]); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         return this.getGroupBys(null, null, this.defaultRemoveFilterValue, false); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2018-09-14 07:49:39 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (segment.type === 'value') { | 
					
						
							|  |  |  |       const filterKey = this.filterSegments[index - 2].value; | 
					
						
							| 
									
										
										
										
											2018-09-14 21:44:12 +08:00
										 |  |  |       const shortKey = filterKey.substring(filterKey.indexOf('.label.') + 7); | 
					
						
							| 
									
										
										
										
											2018-09-14 07:49:39 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-14 21:44:12 +08:00
										 |  |  |       if (filterKey.startsWith('metric.label.') && this.metricLabels.hasOwnProperty(shortKey)) { | 
					
						
							|  |  |  |         return this.getValuesForFilterKey(this.metricLabels[shortKey]); | 
					
						
							| 
									
										
										
										
											2018-09-14 07:49:39 +08:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-14 21:44:12 +08:00
										 |  |  |       if (filterKey.startsWith('resource.label.') && this.resourceLabels.hasOwnProperty(shortKey)) { | 
					
						
							|  |  |  |         return this.getValuesForFilterKey(this.resourceLabels[shortKey]); | 
					
						
							| 
									
										
										
										
											2018-09-14 07:49:39 +08:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return []; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   getValuesForFilterKey(labels: any[]) { | 
					
						
							|  |  |  |     const filterValues = labels.map(l => { | 
					
						
							|  |  |  |       return this.uiSegmentSrv.newSegment({ | 
					
						
							|  |  |  |         value: `${l}`, | 
					
						
							|  |  |  |         expandable: false, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return filterValues; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-14 21:44:12 +08:00
										 |  |  |   filterSegmentUpdated(segment, index) { | 
					
						
							|  |  |  |     if (segment.type === 'plus-button') { | 
					
						
							|  |  |  |       this.addNewFilterSegments(segment, index); | 
					
						
							|  |  |  |     } else if (segment.type === 'key' && segment.value === this.defaultRemoveFilterValue) { | 
					
						
							|  |  |  |       this.removeFilterSegment(index); | 
					
						
							|  |  |  |       this.ensurePlusButton(this.filterSegments); | 
					
						
							|  |  |  |     } else if (segment.type === 'value' && segment.value !== this.defaultFilterValue) { | 
					
						
							|  |  |  |       this.ensurePlusButton(this.filterSegments); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     this.target.filters = this.filterSegments.filter(s => s.type !== 'plus-button').map(seg => seg.value); | 
					
						
							|  |  |  |     this.refresh(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   addNewFilterSegments(segment, index) { | 
					
						
							|  |  |  |     if (index > 2) { | 
					
						
							|  |  |  |       this.filterSegments.splice(index, 0, this.uiSegmentSrv.newCondition('AND')); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     segment.type = 'key'; | 
					
						
							|  |  |  |     this.filterSegments.push(this.uiSegmentSrv.newOperator('=')); | 
					
						
							|  |  |  |     this.filterSegments.push(this.uiSegmentSrv.newFake(this.defaultFilterValue, 'value', 'query-segment-value')); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   removeFilterSegment(index) { | 
					
						
							|  |  |  |     this.filterSegments.splice(index, 3); | 
					
						
							|  |  |  |     // remove trailing condition
 | 
					
						
							|  |  |  |     if (index > 2 && this.filterSegments[index - 1].type === 'condition') { | 
					
						
							|  |  |  |       this.filterSegments.splice(index - 1, 1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // remove condition if it is first segment
 | 
					
						
							|  |  |  |     if (index === 0 && this.filterSegments[0].type === 'condition') { | 
					
						
							|  |  |  |       this.filterSegments.splice(0, 1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-13 17:02:31 +08:00
										 |  |  |   ensurePlusButton(segments) { | 
					
						
							|  |  |  |     const count = segments.length; | 
					
						
							|  |  |  |     const lastSegment = segments[Math.max(count - 1, 0)]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!lastSegment || lastSegment.type !== 'plus-button') { | 
					
						
							|  |  |  |       segments.push(this.uiSegmentSrv.newPlusButton()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 04:41:24 +08:00
										 |  |  |   onDataReceived(dataList) { | 
					
						
							|  |  |  |     this.lastQueryError = null; | 
					
						
							|  |  |  |     this.lastQueryMeta = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const anySeriesFromQuery: any = _.find(dataList, { refId: this.target.refId }); | 
					
						
							|  |  |  |     if (anySeriesFromQuery) { | 
					
						
							|  |  |  |       this.lastQueryMeta = anySeriesFromQuery.meta; | 
					
						
							|  |  |  |       this.lastQueryMeta.rawQueryString = decodeURIComponent(this.lastQueryMeta.rawQuery); | 
					
						
							| 
									
										
										
										
											2018-09-17 17:28:10 +08:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2018-09-12 04:41:24 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   onDataError(err) { | 
					
						
							|  |  |  |     if (err.data && err.data.results) { | 
					
						
							|  |  |  |       const queryRes = err.data.results[this.target.refId]; | 
					
						
							| 
									
										
										
										
											2018-09-14 23:47:39 +08:00
										 |  |  |       if (queryRes && queryRes.error) { | 
					
						
							| 
									
										
										
										
											2018-09-12 04:41:24 +08:00
										 |  |  |         this.lastQueryMeta = queryRes.meta; | 
					
						
							|  |  |  |         this.lastQueryMeta.rawQueryString = decodeURIComponent(this.lastQueryMeta.rawQuery); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let jsonBody; | 
					
						
							|  |  |  |         try { | 
					
						
							|  |  |  |           jsonBody = JSON.parse(queryRes.error); | 
					
						
							|  |  |  |         } catch { | 
					
						
							|  |  |  |           this.lastQueryError = queryRes.error; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.lastQueryError = jsonBody.error.message; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-09-17 17:28:10 +08:00
										 |  |  |     console.error(err); | 
					
						
							| 
									
										
										
										
											2018-09-12 04:41:24 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-09-04 19:21:02 +08:00
										 |  |  | } |