From ae8a76519038d59ce47e41e979ab724613e0f9d5 Mon Sep 17 00:00:00 2001 From: Erik Sundell Date: Thu, 11 Oct 2018 13:46:51 +0200 Subject: [PATCH] stackdriver: improve error handling --- .../datasource/stackdriver/datasource.ts | 61 +++++++++++-------- .../stackdriver/query_filter_ctrl.ts | 13 ++-- 2 files changed, 44 insertions(+), 30 deletions(-) diff --git a/public/app/plugins/datasource/stackdriver/datasource.ts b/public/app/plugins/datasource/stackdriver/datasource.ts index 57f8e00ac5c..05af784bb8c 100644 --- a/public/app/plugins/datasource/stackdriver/datasource.ts +++ b/public/app/plugins/datasource/stackdriver/datasource.ts @@ -1,11 +1,13 @@ import { stackdriverUnitMappings } from './constants'; import appEvents from 'app/core/app_events'; +import _ from 'lodash'; export default class StackdriverDatasource { id: number; url: string; baseUrl: string; projectName: string; + authenticationType: string; queryPromise: Promise; /** @ngInject */ @@ -15,6 +17,7 @@ export default class StackdriverDatasource { this.doRequest = this.doRequest; this.id = instanceSettings.id; this.projectName = instanceSettings.jsonData.defaultProject || ''; + this.authenticationType = instanceSettings.jsonData.authenticationType || 'jwt'; } async getTimeSeries(options) { @@ -178,29 +181,36 @@ export default class StackdriverDatasource { } async testDatasource() { + let status, message; + const defaultErrorMessage = 'Cannot connect to Stackdriver API'; try { - await this.backendSrv.datasourceRequest({ - url: '/api/tsdb/query', - method: 'POST', - data: { - queries: [ - { - refId: 'testDatasource', - datasourceId: this.id, - type: 'testDatasource', - }, - ], - }, - }); - return { - status: 'success', - message: 'Successfully queried the Stackdriver API.', - title: 'Success', - }; + const projectName = await this.getDefaultProject(); + const path = `v3/projects/${projectName}/metricDescriptors`; + const response = await this.doRequest(`${this.baseUrl}${path}`); + if (response.status === 200) { + status = 'success'; + message = 'Successfully queried the Stackdriver API.'; + } else { + status = 'error'; + message = response.statusText ? response.statusText : defaultErrorMessage; + } } catch (error) { + status = 'error'; + if (_.isString(error)) { + message = error; + } else { + message = 'Stackdriver: '; + message += error.statusText ? error.statusText + ': ' : ''; + if (error.data && error.data.error && error.data.error.code) { + message += error.data.error.code + '. ' + error.data.error.message; + } else { + message = defaultErrorMessage; + } + } + } finally { return { - status: 'error', - message: this.formatStackdriverError(error), + status, + message, }; } } @@ -223,28 +233,27 @@ export default class StackdriverDatasource { async getDefaultProject() { try { - if (!this.projectName) { + if (this.authenticationType === 'gce' || !this.projectName) { const { data } = await this.backendSrv.datasourceRequest({ url: '/api/tsdb/query', method: 'POST', data: { queries: [ { - refId: 'defaultProject', - type: 'defaultProject', + refId: 'ensureDefaultProjectQuery', + type: 'ensureDefaultProjectQuery', datasourceId: this.id, }, ], }, }); - this.projectName = data.results.defaultProject.meta.defaultProject; + this.projectName = data.results.ensureDefaultProjectQuery.meta.defaultProject; return this.projectName; } else { return this.projectName; } } catch (error) { - appEvents.emit('ds-request-error', this.formatStackdriverError(error)); - return ''; + throw this.formatStackdriverError(error); } } diff --git a/public/app/plugins/datasource/stackdriver/query_filter_ctrl.ts b/public/app/plugins/datasource/stackdriver/query_filter_ctrl.ts index 75e4817f395..df5fb0f2965 100644 --- a/public/app/plugins/datasource/stackdriver/query_filter_ctrl.ts +++ b/public/app/plugins/datasource/stackdriver/query_filter_ctrl.ts @@ -79,11 +79,16 @@ export class StackdriverFilterCtrl { } async getCurrentProject() { - return new Promise(async resolve => { - if (!this.target.defaultProject || this.target.defaultProject === 'loading project...') { - this.target.defaultProject = await this.datasource.getDefaultProject(); + return new Promise(async (resolve, reject) => { + try { + if (!this.target.defaultProject || this.target.defaultProject === 'loading project...') { + this.target.defaultProject = await this.datasource.getDefaultProject(); + } + resolve(this.target.defaultProject); + } catch (error) { + appEvents.emit('ds-request-error', error); + reject(); } - resolve(this.target.defaultProject); }); }