mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Stackdriver: Loads project name and metrics descriptions into the query controller
This commit is contained in:
parent
684aa3ff33
commit
75c002645c
@ -9,6 +9,10 @@ export default class StackdriverDatasource {
|
|||||||
this.doRequest = this.doRequest;
|
this.doRequest = this.doRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query() {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
testDatasource() {
|
testDatasource() {
|
||||||
const path = `v3/projects/raintank-production/metricDescriptors`;
|
const path = `v3/projects/raintank-production/metricDescriptors`;
|
||||||
return this.doRequest(`${this.baseUrl}${path}`)
|
return this.doRequest(`${this.baseUrl}${path}`)
|
||||||
@ -48,6 +52,16 @@ export default class StackdriverDatasource {
|
|||||||
return response.data.projects.map(p => ({ id: p.projectId, name: p.name }));
|
return response.data.projects.map(p => ({ id: p.projectId, name: p.name }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getMetricTypes(projectId: string) {
|
||||||
|
try {
|
||||||
|
const metricsApiPath = `v3/projects/${projectId}/metricDescriptors`;
|
||||||
|
const { data } = await this.doRequest(`${this.baseUrl}${metricsApiPath}`);
|
||||||
|
return data.metricDescriptors.map(m => ({ id: m.name, name: m.displayName }));
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async doRequest(url, maxRetries = 1) {
|
async doRequest(url, maxRetries = 1) {
|
||||||
return this.backendSrv
|
return this.backendSrv
|
||||||
.datasourceRequest({
|
.datasourceRequest({
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import StackdriverDatasource from './datasource';
|
import StackdriverDatasource from './datasource';
|
||||||
// import { StackdriverQueryCtrl } from './query_ctrl';
|
import { StackdriverQueryCtrl } from './query_ctrl';
|
||||||
import { StackdriverConfigCtrl } from './config_ctrl';
|
import { StackdriverConfigCtrl } from './config_ctrl';
|
||||||
|
|
||||||
// class AnnotationsQueryCtrl {
|
// class AnnotationsQueryCtrl {
|
||||||
@ -8,7 +8,7 @@ import { StackdriverConfigCtrl } from './config_ctrl';
|
|||||||
|
|
||||||
export {
|
export {
|
||||||
StackdriverDatasource as Datasource,
|
StackdriverDatasource as Datasource,
|
||||||
// StackdriverQueryCtrl as QueryCtrl,
|
StackdriverQueryCtrl as QueryCtrl,
|
||||||
StackdriverConfigCtrl as ConfigCtrl,
|
StackdriverConfigCtrl as ConfigCtrl,
|
||||||
// AnnotationsQueryCtrl,
|
// AnnotationsQueryCtrl,
|
||||||
};
|
};
|
||||||
|
@ -1,81 +1,16 @@
|
|||||||
<query-editor-row query-ctrl="ctrl" has-text-edit-mode="true">
|
<query-editor-row query-ctrl="ctrl" has-text-edit-mode="true">
|
||||||
|
<div class="gf-form-inline">
|
||||||
<div class="gf-form" ng-show="ctrl.target.textEditor">
|
<div class="gf-form">
|
||||||
<input type="text" class="gf-form-input" ng-model="ctrl.target.target" spellcheck="false" ng-blur="ctrl.targetTextChanged()"></input>
|
<span class="gf-form-label width-9">Project</span>
|
||||||
</div>
|
<input class="gf-form-input" disabled type="text" ng-model='ctrl.project.name' get-options="ctrl.getProjects()" css-class="min-width-12"
|
||||||
|
/>
|
||||||
<div ng-hide="ctrl.target.textEditor">
|
</div>
|
||||||
<div class="gf-form-inline">
|
</div>
|
||||||
<div class="gf-form">
|
<div class="gf-form-inline">
|
||||||
<label class="gf-form-label width-6 query-keyword">Series</label>
|
<div class="gf-form">
|
||||||
</div>
|
<span class="gf-form-label width-9">Metric Type</span>
|
||||||
|
<gf-form-dropdown model="ctrl.metricType" get-options="ctrl.getMetricTypes($query)" class="gf-form-input" disabled type="text"
|
||||||
<div ng-if="ctrl.queryModel.seriesByTagUsed" ng-repeat="tag in ctrl.queryModel.tags" class="gf-form">
|
allow-custom="true" lookup-text="true" css-class="min-width-12"></gf-form-dropdown>
|
||||||
<gf-form-dropdown
|
|
||||||
model="tag.key"
|
|
||||||
allow-custom="true"
|
|
||||||
label-mode="true"
|
|
||||||
debounce="true"
|
|
||||||
placeholder="Tag key"
|
|
||||||
css-class="query-segment-key"
|
|
||||||
get-options="ctrl.getTags($index, $query)"
|
|
||||||
on-change="ctrl.tagChanged(tag, $index)"
|
|
||||||
/>
|
|
||||||
<gf-form-dropdown
|
|
||||||
model="tag.operator"
|
|
||||||
label-mode="true"
|
|
||||||
css-class="query-segment-operator"
|
|
||||||
get-options="ctrl.getTagOperators()"
|
|
||||||
on-change="ctrl.tagChanged(tag, $index)"
|
|
||||||
min-input-width="30"
|
|
||||||
/>
|
|
||||||
<gf-form-dropdown
|
|
||||||
model="tag.value"
|
|
||||||
allow-custom="true"
|
|
||||||
label-mode="true"
|
|
||||||
debounce="true"
|
|
||||||
css-class="query-segment-value"
|
|
||||||
placeholder="Tag value"
|
|
||||||
get-options="ctrl.getTagValues(tag, $index, $query)"
|
|
||||||
on-change="ctrl.tagChanged(tag, $index)"
|
|
||||||
/>
|
|
||||||
<label class="gf-form-label query-keyword" ng-if="ctrl.showDelimiter($index)">AND</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div ng-if="ctrl.queryModel.seriesByTagUsed" ng-repeat="segment in ctrl.addTagSegments" role="menuitem" class="gf-form">
|
|
||||||
<metric-segment segment="segment" get-options="ctrl.getTagsAsSegments($query)" on-change="ctrl.addNewTag(segment)" debounce="true" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div ng-if="!ctrl.queryModel.seriesByTagUsed" ng-repeat="segment in ctrl.segments" role="menuitem" class="gf-form">
|
|
||||||
<metric-segment segment="segment" get-options="ctrl.getAltSegments($index, $query)" on-change="ctrl.segmentValueChanged(segment, $index)" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div ng-if="ctrl.paused" class="gf-form">
|
|
||||||
<a ng-click="ctrl.unpause()" class="gf-form-label query-part"><i class="fa fa-play"></i></a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="gf-form gf-form--grow">
|
|
||||||
<div class="gf-form-label gf-form-label--grow"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="gf-form-inline">
|
|
||||||
<div class="gf-form">
|
|
||||||
<label class="gf-form-label width-6 query-keyword">Functions</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div ng-repeat="func in ctrl.queryModel.functions" class="gf-form">
|
|
||||||
<span graphite-func-editor class="gf-form-label query-part" ng-hide="func.hidden"></span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="gf-form dropdown">
|
|
||||||
<span graphite-add-func></span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="gf-form gf-form--grow">
|
|
||||||
<div class="gf-form-label gf-form-label--grow"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</query-editor-row>
|
</query-editor-row>
|
@ -1,11 +1,65 @@
|
|||||||
import './add_graphite_func';
|
import _ from 'lodash';
|
||||||
import './func_editor';
|
|
||||||
import { QueryCtrl } from 'app/plugins/sdk';
|
import { QueryCtrl } from 'app/plugins/sdk';
|
||||||
|
import appEvents from 'app/core/app_events';
|
||||||
|
|
||||||
export class StackdriverQueryCtrl extends QueryCtrl {
|
export class StackdriverQueryCtrl extends QueryCtrl {
|
||||||
static templateUrl = 'partials/query.editor.html';
|
static templateUrl = 'partials/query.editor.html';
|
||||||
|
project: {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
metricType: string;
|
||||||
|
defaultDropdownValue = 'select';
|
||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
constructor($scope, $injector) {
|
constructor($scope, $injector) {
|
||||||
super($scope, $injector);
|
super($scope, $injector);
|
||||||
|
this.project = {
|
||||||
|
id: 'default',
|
||||||
|
name: 'loading project...',
|
||||||
|
};
|
||||||
|
this.metricType = this.defaultDropdownValue;
|
||||||
|
|
||||||
|
this.getCurrentProject().then(this.getMetricTypes.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
async getCurrentProject() {
|
||||||
|
try {
|
||||||
|
const projects = await this.datasource.getProjects();
|
||||||
|
if (projects && projects.length > 0) {
|
||||||
|
this.project = this.project = projects[0];
|
||||||
|
} 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
|
||||||
|
if (this.project.id !== 'default') {
|
||||||
|
const metricTypes = await this.datasource.getMetricTypes(this.project.id);
|
||||||
|
if (this.metricType === this.defaultDropdownValue && metricTypes.length > 0) {
|
||||||
|
this.$scope.$apply(() => (this.metricType = metricTypes[0].name));
|
||||||
|
}
|
||||||
|
return metricTypes.map(mt => ({ value: mt.id, text: mt.id }));
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user