export type GrafanaDatasource = { url: string, type: string, params: { db: string, q: string, epoch: string } } export type GrafanaMetricId = string; export class GrafanaMetric { private _metricQuery: MetricQuery = undefined; constructor( public datasource: GrafanaDatasource, public targets: any[], public id?: GrafanaMetricId ) { if(datasource === undefined) { throw new Error('datasource is undefined'); } if(targets === undefined) { throw new Error('targets is undefined'); } if(targets.length === 0) { throw new Error('targets is empty'); } } public get metricQuery() { if(this._metricQuery === undefined) { this._metricQuery = new MetricQuery(this); } return this._metricQuery; } public toObject() { return { datasource: this.datasource, targets: this.targets, _id: this.id }; } static fromObject(obj: any): GrafanaMetric { if(obj === undefined) { throw new Error('obj is undefined'); } return new GrafanaMetric( obj.datasource, obj.targets, obj._id ); } } export class MetricQuery { private static INFLUX_QUERY_TIME_REGEX = /time >[^A-Z]+/; private _queryParts: string[]; private _type: string; constructor(metric: GrafanaMetric) { this._type = metric.datasource.type; if (this._type !== 'influxdb') { throw new Error(`Queries of type "${metric.datasource.type}" are not supported yet.`); } var queryStr = metric.datasource.params.q; this._queryParts = queryStr.split(MetricQuery.INFLUX_QUERY_TIME_REGEX); if(this._queryParts.length == 1) { throw new Error( `Query "${queryStr}" is not replaced with LIMIT/OFFSET oeprators. Missing time clause.` ); } if(this._queryParts.length > 2) { throw new Error(`Query "${queryStr}" has multiple time clauses. Can't parse.`); } } getQuery(from: number, to: number, limit: number, offset: number): string { let timeClause = `time >= ${from}ms AND time <= ${to}ms`; return `${this._queryParts[0]} ${timeClause} ${this._queryParts[1]} LIMIT ${limit} OFFSET ${offset}`; } }