precis-error
Version:
Error endpoint monitor for Precis UI.
118 lines (109 loc) • 2.95 kB
JavaScript
const DEFAULT_THRESHOLD = 40;
const DEFAULT_RETAIN_COUNT = 100;
const TIME_TO_BUCKET = 1000 * 60 * 15;
var noop = function(){};
var Handler = function(options){
this.threshold = options.threshold || DEFAULT_THRESHOLD;
this.retain = options.retainCount || DEFAULT_RETAIN_COUNT;
this.event = options.event;
this.statsEvent = options.statsEvent;
this.sockets = options.sockets;
this.logger = options.logger;
this.store = options.store;
this.records = [];
this.buckets = [];
};
Handler.prototype.getBucket = function(time){
var i = this.buckets.length-1;
var bkt = new Date(Date.parse(time));
bkt.setMilliseconds(0);
bkt.setSeconds(Math.floor(bkt.getSeconds()/15)*15);
var tim = bkt.getTime();
var key = 'error_'+tim;
this.checkTrimBuckets(tim);
while(i>-1){
if(this.buckets[i] && (this.buckets[i].key===key)){
return this.buckets[i];
}
i--;
}
var bucket = {
key: key,
time: bkt,
stamp: tim,
stats: {
error: 0
}
};
this.buckets.push(bucket);
return bucket;
};
Handler.prototype.checkTrimBuckets = function(time){
var eol = (time || ((new Date()).getTime()))-(TIME_TO_BUCKET);
this.buckets = this.buckets.filter((bucket)=>bucket && (bucket.stamp >= eol));
/*
while(this.buckets && this.buckets.length && (this.buckets[0].stamp<eol)){
this.buckets.shift();
}
//*/
};
Handler.prototype.enqueueStatsUpdate = function(bucket){
var tmr = bucket.enqueueTimer;
if(!tmr){
bucket.enqueueTimer = setTimeout(function(){
bucket.enqueueTimer = false;
this.sockets.emit(this.statsEvent, {
_id: bucket.key,
key: bucket.key,
time: bucket.time,
stamp: bucket.stamp,
stats: {
error: bucket.stats.error
}
});
}.bind(this), 1000);
}
};
Handler.prototype.enqueueErrorRecord = function(record){
var tmr = this._errorRecordTimer;
if(!tmr){
this._errorRecords = [record];
return this._errorRecordTimer = setTimeout(function(){
this.sockets.emit(this.event, this._errorRecords);
this._errorRecordTimer = false;
}.bind(this));
}
this._errorRecords.push(record);
};
var getValue = function(from, key, def){
var o = from;
var path = key.split('.');
var segment;
while(o && path.length){
segment = path.shift();
o = o[segment];
}
if(o){
return o;
}
return def;
};
Handler.prototype.push = function(data){
if(data.level < this.threshold){
return;
}
if(getValue(data, 'data.0.data.code')==='ECONNRESET'){
return;
}
var bucket = this.getBucket(data.time||data.dateTime);
bucket.stats.error++;
this.records.push(data);
//this.sockets.emit(this.event, data);
this.enqueueErrorRecord(data);
this.store.insert(data, noop);
if(this.records.length>this.retain){
this.records = this.records.slice(this.records.length-this.retain);
}
this.enqueueStatsUpdate(bucket);
};
module.exports = {Handler};