You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
122 lines
3.1 KiB
122 lines
3.1 KiB
import { queryByMetric, Datasource, Metric } from 'grafana-datasource-kit'; |
|
import { getApiKey } from './config'; |
|
|
|
import * as csv from 'fast-csv'; |
|
import * as path from 'path'; |
|
import * as fs from 'fs'; |
|
import * as moment from 'moment'; |
|
import { URL } from 'url'; |
|
|
|
|
|
const MS_IN_DAY = 24 * 60 * 60 * 1000; |
|
|
|
export class Target { |
|
private exportedRows: number; |
|
private days: number; |
|
private day: number; |
|
private csvStream: any; |
|
private metric: Metric; |
|
private createdTimestamp: number; |
|
|
|
constructor( |
|
private panelUrl: string, |
|
private user: string, |
|
datasource: Datasource, |
|
targets: Array<Object>, |
|
private from: number, |
|
private to: number, |
|
private datasourceName: string, |
|
) { |
|
this.metric = new Metric(datasource, targets); |
|
} |
|
|
|
public updateStatus(status) { |
|
let time = moment().valueOf(); |
|
let data = { |
|
time, |
|
user: this.user, |
|
exportedRows: this.exportedRows, |
|
progress: (this.day / this.days).toLocaleString('en', { style: 'percent' }), |
|
status, |
|
datasourceName: this.datasourceName |
|
}; |
|
return new Promise((resolve, reject) => { |
|
fs.writeFile(this.getFilePath('json'), JSON.stringify(data), 'utf8', err => { |
|
if(err) { |
|
console.error(err); |
|
reject('Can`t write file'); |
|
} else { |
|
resolve(); |
|
} |
|
}); |
|
}); |
|
} |
|
|
|
public async export() { |
|
this.exportedRows = 0; |
|
this.days = Math.ceil((this.to - this.from) / MS_IN_DAY); |
|
this.day = 0; |
|
this.initCsvStream(); |
|
|
|
let to = this.to; |
|
let from = this.from; |
|
|
|
console.log(`Total days: ${this.days}`); |
|
while(this.day < this.days) { |
|
this.day++; |
|
to = from + MS_IN_DAY; |
|
|
|
console.log(`${this.day} day: ${from}ms -> ${to}ms`); |
|
|
|
let apiKey = getApiKey(new URL(this.panelUrl).origin); |
|
let metrics = await queryByMetric(this.metric, this.panelUrl, from, to, apiKey); |
|
|
|
if(metrics.values.length > 0) { |
|
if(metrics !== undefined) { |
|
this.writeCsv(metrics); |
|
} |
|
} |
|
await this.updateStatus('exporting'); |
|
|
|
from += MS_IN_DAY; |
|
} |
|
this.csvStream.end(); |
|
} |
|
// TODO: move csv-related stuff to service |
|
private initCsvStream() { |
|
this.csvStream = csv.createWriteStream({ headers: true }); |
|
let writableStream = fs.createWriteStream(this.getFilePath('csv')); |
|
|
|
this.csvStream.pipe(writableStream); |
|
writableStream.on('finish', async () => { |
|
console.log('Everything is written'); |
|
await this.updateStatus('finished'); |
|
}) |
|
} |
|
|
|
private writeCsv(series) { |
|
for(let val of series.values) { |
|
if(val[1] !== null) { |
|
let row = {}; |
|
for(let col in series.columns) { |
|
row[series.columns[col]] = val[col]; |
|
} |
|
this.csvStream.write(row); |
|
this.exportedRows++; |
|
} |
|
} |
|
} |
|
|
|
private getFilename(extension) { |
|
if(this.createdTimestamp === undefined) { |
|
this.createdTimestamp = moment().valueOf(); |
|
} |
|
return `${this.createdTimestamp}.${this.datasourceName}.${extension}`; |
|
} |
|
|
|
private getFilePath(extension) { |
|
let filename = this.getFilename(extension); |
|
return path.join(__dirname, `../exported/${filename}`); |
|
} |
|
|
|
}
|
|
|