|
|
@ -3,9 +3,10 @@ import { Metric } from '../models/metric_model'; |
|
|
|
import { HASTIC_API_KEY } from '../config'; |
|
|
|
import { HASTIC_API_KEY } from '../config'; |
|
|
|
|
|
|
|
|
|
|
|
import { URL } from 'url'; |
|
|
|
import { URL } from 'url'; |
|
|
|
import { stringify } from 'querystring'; |
|
|
|
|
|
|
|
import axios from 'axios'; |
|
|
|
import axios from 'axios'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const CHUNK_SIZE = 50000; |
|
|
|
|
|
|
|
|
|
|
|
export type Timestamp = number; |
|
|
|
export type Timestamp = number; |
|
|
|
/** |
|
|
|
/** |
|
|
@ -15,25 +16,63 @@ export type Timestamp = number; |
|
|
|
export async function queryByMetric(metric: Metric, panelUrl: string): Promise<[number, number][]> { |
|
|
|
export async function queryByMetric(metric: Metric, panelUrl: string): Promise<[number, number][]> { |
|
|
|
let datasource = metric.datasource; |
|
|
|
let datasource = metric.datasource; |
|
|
|
|
|
|
|
|
|
|
|
if(datasource.type !== 'influxdb') { |
|
|
|
if (datasource.type !== 'influxdb') { |
|
|
|
throw new Error(`${datasource.type} queries are not supported yet`); |
|
|
|
throw new Error(`${datasource.type} queries are not supported yet`); |
|
|
|
} |
|
|
|
} |
|
|
|
var params = {}; |
|
|
|
|
|
|
|
let origin = new URL(panelUrl).origin; |
|
|
|
let origin = new URL(panelUrl).origin; |
|
|
|
let url = `${origin}/${datasource.url}?${stringify(params)}`; |
|
|
|
let url = `${origin}/${datasource.url}`; |
|
|
|
console.log(url) |
|
|
|
|
|
|
|
|
|
|
|
let params = datasource.params |
|
|
|
|
|
|
|
let records = await getRecordsCount(url, params); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let limit = Math.min(records, CHUNK_SIZE); |
|
|
|
|
|
|
|
let offset = 0; |
|
|
|
|
|
|
|
|
|
|
|
let headers = { 'Authorization': 'Bearer ' + HASTIC_API_KEY }; |
|
|
|
let data = []; |
|
|
|
|
|
|
|
while (offset <= records) { |
|
|
|
|
|
|
|
let paramsClone = Object.assign({}, params); |
|
|
|
|
|
|
|
paramsClone.q = paramsClone.q.replace(/(WHERE time >[^A-Z]+)/, `LIMIT ${limit} OFFSET ${offset}`); |
|
|
|
|
|
|
|
|
|
|
|
let res = await axios.get(url, { headers }); |
|
|
|
let chunk = await queryGrafana(url, paramsClone); |
|
|
|
|
|
|
|
data = data.concat(chunk); |
|
|
|
|
|
|
|
|
|
|
|
let results = res.data['results']; |
|
|
|
offset += CHUNK_SIZE; |
|
|
|
console.log(results) |
|
|
|
|
|
|
|
if(results === undefined) { |
|
|
|
|
|
|
|
throw new Error('reuslts field is undefined in response'); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
if(results.series === undefined) { |
|
|
|
|
|
|
|
|
|
|
|
return data; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async function getRecordsCount(url: string, params: any) { |
|
|
|
|
|
|
|
let paramsClone = Object.assign({}, params); |
|
|
|
|
|
|
|
let query = paramsClone.q; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let field = query.match(/"(\w+)"\)*\sFROM/)[1]; |
|
|
|
|
|
|
|
let measurement = query.match(/FROM\s"(\w+)"/)[1]; |
|
|
|
|
|
|
|
paramsClone.q = `SELECT COUNT(${field}) FROM ${measurement}`; |
|
|
|
|
|
|
|
let result = await queryGrafana(url, paramsClone); |
|
|
|
|
|
|
|
return result[0][1]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async function queryGrafana(url: string, params: any) { |
|
|
|
|
|
|
|
let headers = { Authorization: `Bearer ${HASTIC_API_KEY}` }; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let res; |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
res = await axios.get(url, { params, headers }); |
|
|
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
|
|
console.error(`Error while getting data from Grafana: ${e}`); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (res.data.results === undefined) { |
|
|
|
|
|
|
|
throw new Error('results field is undefined in response'); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: support more than 1 metric (each res.data.results item is a metric)
|
|
|
|
|
|
|
|
let results = res.data.results[0]; |
|
|
|
|
|
|
|
if (results.series === undefined) { |
|
|
|
return []; |
|
|
|
return []; |
|
|
|
} |
|
|
|
} |
|
|
|
return res['series'][0]; |
|
|
|
|
|
|
|
|
|
|
|
return results.series[0].values; |
|
|
|
} |
|
|
|
} |
|
|
|