UNPKG

node-red-nagios-nsca-send

Version:

A Node-RED node to forward to Nagios using NSCA send

211 lines (181 loc) 8.65 kB
module.exports = function(RED) { "use strict"; var exec = require('child_process').exec; // this will execute the bash command for send_nsca function NagiosNSCASend(config) { var node = this; RED.nodes.createNode(node, config); //RED.comms.publish("debug",{msg:JSON.stringify(node),format:'number'}); //console.log( "in NagiosNSCASend(config) this", JSON.stringify(node) ); //console.log( "config", JSON.stringify(config) ); /* get the config data */ node.perfname = config.perfname; node.nagioshost = config.nagioshost; node.nscaport = config.nscaport ? parseInt(config.nscaport, 10) : 5667; // make sure only numbers are transmitted node.host = config.host; node.service = config.service; node.send_nsca_script = config.send_nsca_script; node.send_nsca_config = config.send_nsca_config; node.perfdata = config.perfdata; //RED.comms.publish("debug",{msg:JSON.stringify(this),format:'number'}); this.on('input', function(msg) { // Get the value by the type of source and return it. function getValue( type, value ) { // console.log("type = " + type + ", value = " + value); switch (type) { case 'msg' : return parseFloat( RED.util.getMessageProperty(msg,value) ) || 0; break; case 'flow' : return parseFloat( node.context().flow.get(value) ) || 0; break; case 'global' : return parseFloat( node.context().global.get(value) ) || 0; break; case 'str' : return parseFloat( value ) || 0; break; case 'num' : return parseFloat( value ) || 0; break; case 'json' : return parseFloat( JSON.parse(value) ) || 0; break; case 'jsonata' : return parseFloat( value.evaluate({msg:msg}) ) || 0; break; default : return null; break; } } // create the syntax for nagios performance data ranges and return it as a string function getRange( type, low, high ) { switch (type) { case 'above' : // [h .. +∞] return "~:" + high; break; case 'below' : // [-∞ .. l] return "" + low + ":"; break; case 'between' : // [l .. h] return "@" + low + ":" + high; break; case 'outside' : // ]l .. h[ return "" + low + ":" + high; break; default: return ""; } }; // returns true if a given value is in a given range function isInRange ( value, type, low, high ) { switch (type) { case 'above' : return value > high; break; case 'below' : return low < value; break; case 'between' : return low <= value & value <= high; break; case 'outside' : return value < low | high < value; break; default: return ""; } } // returns the status calculated by the values position in the range // priority is critical, then warning, then ok function getStatus ( value, warn, crit ) { if ( isInRange( value, crit.type, crit.l, crit.h ) ) { return 2; // critical } else if ( isInRange( value, warn.type, warn.l, warn.h ) ) { return 1; // warning } else { return 0; // okay } } //console.log( "in input" + JSON.stringify(node) ); //console.log( "msg.payload" + JSON.stringify(msg.payload) ); //console.log( "config"+ JSON.stringify(msg) ); //console.log( "this" + JSON.stringify(this) ); //console.log( "node.perfdata.length = " + JSON.stringify(node.perfdata.length) ); // compose the command used for transfer to nagios nsca service var command = node.send_nsca_script + " -H " + node.nagioshost + " -p " + node.nscaport + " -c " + node.send_nsca_config; var status = 0; // by default the status is ok, if the performance data does not violate the ranges of critical or warning var service_value = []; // there is no singular value for the service, all values come with the performance data var perfstr = ""; // by default the performance string is empty, because it is optional if (node.perfdata.length > 0) { // if there is performance data then var perfdatastr = [] // we create a perfdata string for each performance data for (var i=0; i<node.perfdata.length; i++) { // for each performance data do var perfd = node.perfdata[i]; // get the performance data var value = getValue( perfd.value_fromt, perfd.value_from ); // get the value of the performance data // create the key-value pair var key_value = "'" + perfd.perfname.replace(/"/g, '\\"').replace(/['=]/g, '') + "'=" + value; service_value.push( key_value ); // key-value-pair is used as Service output. var wl = getValue( perfd.warn_lt, perfd.warn_l ); // get lower warning range value by type and value var wh = getValue( perfd.warn_ht, perfd.warn_h ); // get higher warning range value by type and value var cl = getValue( perfd.crit_lt, perfd.crit_l ); // get lower critical range value by type and value var ch = getValue( perfd.crit_ht, perfd.crit_h ); // get higher critical range value by type and value // compose the perfdata string for the current perfdata // the name may be surrounded by single quotation marks followed by an equal sign // then the value and the unit of meassure // after that, each separated by semicolon the ranges for warning and critical state // followed by minimal expected value and maximal expected value // the name may not contain single quotation marks nor equal signs. Double quotes must be escaped. var perfpart = key_value + perfd.uom + ";" + getRange( perfd.warn_t, wl, wh ) + ";" + getRange( perfd.crit_t, cl, ch ) + ";" + perfd.min + ";" + perfd.max; // add it to the array perfdatastr.push( perfpart ); // change the status if needed. Priority is critical, then warning, then ok // getStatus gets the status based on the current performance data block status = Math.max( status, getStatus( value, {type:perfd.warn_t,l:wl,h:wh}, {type:perfd.crit_t,l:cl,h:ch} ) ); } // compose the whole perfomance data string. Starting with a pipe and each performance data block separated by a blank space perfstr = "|" + perfdatastr.join(" "); } service_value = service_value.join(" "); // make the array a string, containing all the perfdata key and value pairs. // compose the nsca-message for using with send_nsca // doublequotes must be escaped var nsca_msg = node.host.replace(/"/g, '\\"') + "\t" + node.service.replace(/"/g, '\\"') + "\t" + status + "\t" + service_value + perfstr; // compose the whole command to be executed. var wholecommand = "/bin/echo -e \"" + nsca_msg + "\" | " + command; //console.log( "wholecommand = " + wholecommand ); node.log(JSON.stringify(msg.payload)); // execute the command exec( wholecommand, function (error, stdout, stderr) { // process the returned values if (error !== null) { // errors will be printed console.log("exec error: " + error); } if (stdout !== "" && stdout !== null) { // if the return on stdout is not the expected default text, print it as a warning if (stdout !== "1 data packet(s) sent to host successfully.\n") { node.warn(stdout); } } // if there is something on the stderr then print it as an error if (stderr !== "" && stderr !== null) { node.error("stderr = " + stderr); } } ); /* client.send(nagioshost, msg.payload, msg.nscaport || node.nscaport); */ }); /* */ } // register the action for this node RED.nodes.registerType("nagios-nsca-send", NagiosNSCASend); };