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, 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}`); } }