import { QueryService } from './base'; import { Datasource, DatasourceQuery } from '../../connectors'; import { TsdbKitError, DatasourceUnavailable } from '../../types'; import axios, { AxiosResponse } from 'axios'; import * as _ from 'lodash'; export class GrafanaUnavailable extends TsdbKitError { }; export class GrafanaQueryService extends QueryService { constructor(datasource: Datasource) { super(datasource); } async query(query: DatasourceQuery, apiKey: string): Promise> { let headers = { Authorization: `Bearer ${apiKey}` }; if(query.headers !== undefined) { _.merge(headers, query.headers); } let axiosQuery = { headers, url: query.url, method: query.method, }; _.defaults(axiosQuery, query.schema); try { const resp = await axios(axiosQuery); return resp; } catch (e) { // TODO: seems like this error handler can be used for both Grafana and Direct queries const msg = `TSDB-kit: fail while request data: ${e.message}`; const parsedUrl = new URL(query.url); const queryUrl = `query url: ${JSON.stringify(parsedUrl.pathname)}`; console.error(`${msg} ${queryUrl}`); if(e.errno === 'ECONNREFUSED') { throw new GrafanaUnavailable(e.message); } if(e.response !== undefined) { console.error(`Response: \ status: ${e.response.status}, \ response data: ${JSON.stringify(e.response.data)}, \ headers: ${JSON.stringify(e.response.headers)} `); if(e.response.status === 401) { throw new Error(`Unauthorized. Check the API_KEY. ${e.message}`); } if(e.response.status === 502) { let datasourceError = new DatasourceUnavailable( `datasource ${parsedUrl.pathname} unavailable, message: ${e.message}`, this._datasource.type, query.url ); throw datasourceError; } } throw new Error(msg); } } }