UNPKG

@nearform/doctor

Version:
99 lines (81 loc) 2.83 kB
'use strict' const async = require('async') const endpoint = require('endpoint') const stream = require('../lib/destroyable-stream') const guessInterval = require('./guess-interval.js') const analyseCPU = require('./analyse-cpu.js') const analyseDelay = require('./analyse-delay.js') const analyseMemory = require('./analyse-memory.js') const analyseHandles = require('./analyse-handles.js') const issueCategory = require('./issue-category.js') class Analysis extends stream.Readable { constructor (traceEventReader, processStatReader) { super({ objectMode: true }) async.waterfall([ collectData.bind(null, traceEventReader, processStatReader), analyseData ], this._done.bind(this)) } _done (err, result) { if (err) this.destroy(err) this.push(result) this.push(null) } _read () { // will call push when all data is collected } } function collectData (traceEventReader, processStatReader, callback) { async.parallel({ traceEvent (done) { traceEventReader.pipe(endpoint({ objectMode: true }, done)) }, processStat (done) { processStatReader.pipe(endpoint({ objectMode: true }, done)) } }, callback) } function analyseData ({ traceEvent, processStat }, callback) { // guess the interval for where the benchmarker ran const intervalIndex = guessInterval(processStat) if (processStat.length < 2) { const msg = 'Not enough data, try running a longer benchmark' return callback(new Error(msg)) } const intervalTime = [ processStat[intervalIndex[0]].timestamp, processStat[intervalIndex[1] - 1].timestamp ] const { processStatSubset, traceEventSubset } = subsetData( traceEvent, processStat, intervalIndex, intervalTime ) // Check for issues, the CPU analysis is async analyseCPU(processStatSubset, traceEventSubset, function (err, cpuIssue) { /* istanbul ignore if: it is very rare that HMM doesn't converge */ if (err) return callback(err) const issues = { delay: analyseDelay(processStatSubset, traceEventSubset), cpu: cpuIssue, memory: analyseMemory(processStatSubset, traceEventSubset), handles: analyseHandles(processStatSubset, traceEventSubset) } const category = issueCategory(issues) callback(null, { 'interval': intervalTime, 'issues': issues, 'issueCategory': category }) }) } function subsetData (traceEvent, processStat, intervalIndex, intervalTime) { const processStatSubset = processStat.slice(...intervalIndex) const traceEventSubset = [] for (const datum of traceEvent) { if (datum.args.startTimestamp >= intervalTime[0] && datum.args.endTimestamp <= intervalTime[1]) { traceEventSubset.push(datum) } } return { processStatSubset, traceEventSubset } } module.exports = Analysis