leafygreen/mops-cli

View on GitHub
lib/util/MetricsWriter.js

Summary

Maintainability
A
3 hrs
Test Coverage
'use strict';

function MetricsWriter() {
    this.metrics = {};
}

/* Add metric
    {
        dataPoints: [
            { timestamp: '2015-07-20T17:48:00Z', value: 0 }
            { timestamp: '2015-07-20T17:50:00Z', value: 2 }
            { timestamp: '2015-07-20T17:51:00Z', value: 3 }
        ],
        granularity: 'MINUTE',
        metricName: 'DB_STORAGE_TOTAL',
        units: 'BYTES'
    }
*/
MetricsWriter.prototype.addMetric = function(metric) {
    this.metrics[metric.metricName] = metric;
};

MetricsWriter.prototype.writeCSV = function() {
    var metricNames = Object.keys(this.metrics).sort();
    var minTimestamp;
    var maxTimestamp;

    // get granularity and min and max timestamps
    metricNames.forEach(function(metricName) {
        var metric = this.metrics[metricName];
        var dataPoints = metric.dataPoints;
        if (dataPoints.length) {
            var firstTimestamp = new Date(dataPoints[0].timestamp).getTime();
            if (minTimestamp) {
                if (minTimestamp > firstTimestamp) {
                    minTimestamp = firstTimestamp;
                }
            } else {
                minTimestamp = firstTimestamp;
            }

            var lastTimestamp = new Date(dataPoints[dataPoints.length - 1].timestamp).getTime();
            if (maxTimestamp) {
                if (maxTimestamp < lastTimestamp) {
                    maxTimestamp = lastTimestamp;
                }
            } else {
                maxTimestamp = lastTimestamp;
            }
        }
    }.bind(this));

    // add header
    var header = 'Date,' + metricNames.join(',');
    var rows = [header];

    // build time range
    var increment = 60000;  // one minute -- TODO granularity
    var timeRange = [];
    var minTime = new Date(minTimestamp).getTime();
    var maxTime = new Date(maxTimestamp).getTime();
    var currentTime = minTime;
    while(currentTime <= maxTime) {
        timeRange.push(currentTime);
        currentTime += increment;
    }


    // expand data point arrays with missing entries
    metricNames.forEach(function(metricName) {
        var metric = this.metrics[metricName];
        var dataPoints = metric.dataPoints;
        var expandedPoints = [];
        var i = 0;
        var j = 0;
        var dataPoint;
        for (i = 0; i < timeRange.length; i++) {
            if (j < dataPoints.length) {
                dataPoint = dataPoints[j];
            } else {
                dataPoint = null;
            }
            if (dataPoint) {
                dataPoint.timestamp = new Date(dataPoint.timestamp).getTime();
                if (dataPoint.timestamp === timeRange[i]) {
                    expandedPoints.push(dataPoint);
                    j++;
                } else {
                    expandedPoints.push({
                        timestamp: timeRange[i],
                        value: null
                    });
                }
            } else {
                expandedPoints.push({
                    timestamp: timeRange[i],
                    value: null
                });
            }
        }
        metric.dataPoints = expandedPoints;
    }.bind(this));

    // zip
    timeRange.forEach(function(time, index) {
        var columns = [new Date(time).toISOString()];
        metricNames.forEach(function(metricName) {
            var metric = this.metrics[metricName];
            var dataPoint = metric.dataPoints[index];
            columns.push(dataPoint.value);
        }.bind(this));
        rows.push(columns.join(','));
    }.bind(this));

    return rows.join('\n');
};

module.exports = MetricsWriter;