nsyslog
Version:
Modular new generation log agent. Reads, transform, aggregate, correlate and send logs from sources to destinations
164 lines (139 loc) • 4.55 kB
JavaScript
const
logger = require("../logger"),
extend = require("extend"),
EventEmiter = require("events"),
Cluster = require("../cluster"),
CPULoad = require('../cpu'),
{MODULE_TYPES,PROC_MODE} = require("../constants");
const CMD = { subscribe : 'subscribe', unsubscribe : 'unsubscribe'};
const PROC_MODE_VALS = new Set(Object.keys(PROC_MODE).map(m=>PROC_MODE[m]));
function notifyListener() {
let subhdl = this.subhdl;
if(Cluster.isMaster) {
Cluster.on(this.channel,(child,module,msg)=>{
let key = `${msg.type}@${msg.id}@${msg.mode}`;
let list = this.subscribers.get(key);
if(list) {
for (let cb of list)
cb(msg.type,msg.id,msg.mode,msg.entry);
}
});
}
else {
Cluster.on(this.channel,(process,module,msg)=>{
try {
if(msg.cmd==CMD.subscribe) {
this.subscribe(msg.type,msg.id,msg.mode,subhdl);
}
else if(msg.cmd==CMD.unsubscribe) {
this.unsubscribe(msg.type,msg.id,msg.mode,subhdl);
}
}catch(err){
logger.error(err);
}
});
}
}
function healthCheck() {
let cfg = this.config.config;
if(cfg.thresholds && cfg.thresholds.memory) {
const memmax = cfg.thresholds.memory;
const hd = cfg.thresholds.heapdump;
logger.info(`Setting max memory usage to: ${memmax} MB`)
setInterval(()=>{
let mem = process.memoryUsage().heapUsed/(1024*1024);
this.emit('threshold.mem',{max:memmax,current:mem,heapdump:hd});
},2000);
}
if(cfg.thresholds && cfg.thresholds.cpu) {
const cpumax = cfg.thresholds.cpu;
logger.info(`Setting max cpu usage to: ${cpumax} %`)
CPULoad.on(CPULoad.Event.cpuload, usage=>{
this.emit('threshold.cpu',{max:cpumax,current:usage.total});
});
}
}
class ClusterAware extends EventEmiter {
constructor(cfg,channel) {
super();
this.channel = channel;
/** @property {Config} config Configuration file */
this.config = cfg;
/**
* @property {object} modules Contains all the components that runs this instance
* @property {object} modules.inputs Map of < string, {@link Input} > values
* @property {object} modules.processors Map of < string, {@link Processor} > values
* @property {object} modules.transporters Map of < string, {@link Transporter} > values
*/
this.modules = extend({inputs : {}, processors : {}, transporters : {}},cfg.modules);
this.subscribers = new Map();
this.subhdl = (type,id,mode,entry)=>process.send({module:channel,type,id,mode,entry});
this.initialize();
}
/**
* Initialize the nsyslog instance.
* @private
*/
initialize() {
notifyListener.apply(this);
healthCheck.apply(this);
}
/**
* Subscribe to components
*
* @param {Constants.MODULE_TYPES} type Component type
* @param {string} id Component ID
* @param {Constants.PROC_MODE} mode Process mode
* @param {function} handler listener handler
*/
subscribe(type,id,mode,handler) {
if(!PROC_MODE_VALS.has(mode)) {
throw new Error(`Invalid subscription mode ${mode}`);
}
let key = `${type}@${id}@${mode}`;
if(!this.subscribers.has(key)) {
this.subscribers.set(key,new Set());
}
this.subscribers.get(key).add(handler);
let mod = this.modules[type][id];
if(!mod) {
throw new error(`Component of type "${type}" with ID "${args.id}" doesn't exist`);
}
if(type!=MODULE_TYPES.inputs)
mod.streams.forEach(str=>str.subscribe(mode,handler));
else
this.inputStream.subscribe(id,handler);
// Subscribe to child processes
if(Cluster.isMaster) {
Cluster.broadcast(this.channel,{cmd:CMD.subscribe,type,id,mode});
}
}
/**
* Unsubscribe to components
*
* @param {Constants.MODULE_TYPES} type Component type
* @param {string} id Component ID
* @param {Constants.PROC_MODE} mode Process mode
* @param {function} handler listener handler
*/
unsubscribe(type,id,mode,handler) {
let key = `${type}@${id}@${mode}`;
if(!this.subscribers.has(key)) {
this.subscribers.set(key,new Set());
}
this.subscribers.get(key).delete(handler);
let mod = this.modules[type][id];
if(!mod) {
throw new error(`Component of type "${type}" with ID "${args.id}" doesn't exist`);
}
if(type!='inputs')
mod.streams.forEach(str=>str.unsubscribe(mode,handler));
else
this.inputStream.unsubscribe(id,handler);
// Unsubscribe to child processes
if(Cluster.isMaster) {
Cluster.broadcast(this.channel,{cmd:CMD.unsubscribe,type,id,mode});
}
}
}
module.exports = ClusterAware;