UNPKG

pmx

Version:

PM2/Keymetrics advanced API

149 lines (138 loc) 4.19 kB
var Notify = require('../notify.js'); var Sample = require('./sample.js'); var Histogram = require('./probes/Histogram.js'); var debug = require('debug')('axm:alert:checker'); /** * Required: * opts.mode * opts.value * * Optional: * extra.name * opts.cmp * opts.interval * opts.msg * opts.sample */ var Alert = function(opts, extra) { var self = this; var cmp; if (typeof(opts.mode) === 'undefined') return console.error('[Probe][Metric] Mode undefined!'); if (typeof(opts.cmp) === 'string') { switch(opts.cmp) { case '>': cmp = function(a,b) { return (a > b); }; break; case '<': cmp = function(a, b) { return (a < b); }; break; case '=': cmp = function(a,b) { return (a === b); }; break; default: return console.error('[Probe][Metric] Mode does not exist!'); } self.cmp_mode = opts.cmp; opts.cmp = null; } else { cmp = function(a,b) { return (a > b); }; self.cmp_mode = '>'; } switch(opts.mode) { case 'threshold': if (typeof(opts.value) === 'undefined') return console.error('[Probe][Metric][threshold] Val undefined!'); this.cmp = opts.cmp || function(a,b) { return cmp(parseFloat(a), b); }; break; case 'threshold-avg': if (typeof(opts.value) === 'undefined') return console.error('[Probe][Metric][threshold-avg] Val undefined!'); this.sample = new Sample(opts.interval || 180); this.cmp = function(value, threshold) { this.sample.update(parseFloat(value)); if (this.start) { if (typeof(opts.cmp) !== 'undefined' && opts.cmp !== null) return opts.cmp(this.sample.getMean(), threshold); return cmp(this.sample.getMean(), threshold); } }; break; case 'smart': this.sample = new Sample(opts.interval || 300); this.small = new Sample(opts.sample || 30); this.cmp = function(value, threshold) { if (value !== null) { this.sample.update(parseFloat(value)); this.small.update(parseFloat(value)); //debug('Check', value, Math.exp(- Math.pow(value - this.sample.getMean(), 2) / (2 * this.sample.getVariance())) / (Math.sqrt(2 * Math.PI) * this.sample.getStddev())); if (this.start) //return false return (Math.exp(- Math.pow(value - this.sample.getMean(), 2) / (2 * this.sample.getVariance())) / (Math.sqrt(2 * Math.PI) * this.sample.getStddev()) < 0.00000001) } return false; }; break; default: return console.error('[Probe][Metric] Mode does not exist!'); } this.mode = opts.mode; this.start = false; //Start the data checking after 30s (default) setTimeout(function() { self.start = true; }, opts.timeout || 30000); this.reached = 0; this.nullCheck = 0; this.value = opts.value || null; this.msg = opts.msg || ((extra && extra.name) ? ('Probe ' + extra.name + ' has reached value') : 'Alert value reached'); this.func = opts.func || opts.action || null; }; Alert.prototype.tick = function(value) { var self = this; if (this.reached === 0) { //Need 10 times null to trigger alert if (value === null && this.nullCheck < 10) { this.nullCheck += 1; } else if (this.cmp(value, this.value)) { Notify.notify(this.msg + ' ' + this.value); // Delay a bit call to custom function to allow PM2 to receive notify msg if (this.func) setTimeout(function() {self.func(value)}, 50); this.reached = 1; this.nullCheck = 0; } } else if (typeof(this.reached) !== 'undefined') { if (!this.cmp(value, this.value)) this.reached = 0; } }; Alert.prototype.serialize = function() { var self = this; var ret = { mode : self.mode }; if (this.mode == 'threshold') { ret.value = self.value; ret.cmp = self.cmp_mode; } if (this.mode == 'threshold-avg') { ret.value = self.value; ret.interval = self.sample._size; ret.cmp = self.cmp_mode; } return ret; }; module.exports = Alert;