#!/usr/bin/env bash
':' //; exec "$(command -v nodejs || command -v node || command -v js || echo "ERROR node.js IS NOT AVAILABLE IN THIS SYSTEM")" "$0" "$@"
// shebang hack from:
// http://unix.stackexchange.com/questions/65235/universal-node-js-shebang
// Initially this is run as a shell script.
// Then, the second line, finds nodejs or node or js in the system path
// and executes it with the shell parameters.
// netdata
// real-time performance and health monitoring, done right!
// (C) 2017 Costa Tsaousis
// GPL v3+
// --------------------------------------------------------------------------------------------------------------------
'use strict';
// --------------------------------------------------------------------------------------------------------------------
// get NETDATA environment variables
var NETDATA_PLUGINS_DIR = process.env.NETDATA_PLUGINS_DIR || __dirname;
var NETDATA_CONFIG_DIR = process.env.NETDATA_CONFIG_DIR || __dirname + '/../../../../etc/netdata';
var NETDATA_UPDATE_EVERY = process.env.NETDATA_UPDATE_EVERY || 1;
var NODE_D_DIR = NETDATA_PLUGINS_DIR + '/../node.d';
// make sure the modules are found
process.mainModule.paths.unshift(NODE_D_DIR + '/node_modules');
process.mainModule.paths.unshift(NODE_D_DIR);
// --------------------------------------------------------------------------------------------------------------------
// load required modules
var fs = require('fs');
var url = require('url');
var util = require('util');
var http = require('http');
var path = require('path');
var extend = require('extend');
var netdata = require('netdata');
// --------------------------------------------------------------------------------------------------------------------
// configuration
function pluginConfig(filename) {
var f = path.basename(filename);
// node.d.plugin configuration
var m = f.match('.plugin' + '$');
if(m !== null)
return netdata.options.paths.config + '/' + f.substring(0, m.index) + '.conf';
// node.d modules configuration
m = f.match('.node.js' + '$');
if(m !== null)
return netdata.options.paths.config + '/node.d/' + f.substring(0, m.index) + '.conf';
return netdata.options.paths.config + '/node.d/' + f + '.conf';
}
// internal defaults
extend(true, netdata.options, {
filename: path.basename(__filename),
update_every: NETDATA_UPDATE_EVERY,
paths: {
plugins: NETDATA_PLUGINS_DIR,
config: NETDATA_CONFIG_DIR,
modules: [],
},
modules_enable_autodetect: true,
modules_enable_all: true,
modules: {},
});
netdata.options.config_filename = pluginConfig(__filename);
// load configuration file
try {
netdata.options_loaded = JSON.parse(fs.readFileSync(netdata.options.config_filename, 'utf8'));
extend(true, netdata.options, netdata.options_loaded);
if(!netdata.options.paths.plugins)
netdata.options.paths.plugins = NETDATA_PLUGINS_DIR;
if(!netdata.options.paths.config)
netdata.options.paths.config = NETDATA_CONFIG_DIR;
// console.error('merged netdata object:');
// console.error(util.inspect(netdata, {depth: 10}));
}
catch(e) {
netdata.error('Cannot read configuration file ' + netdata.options.config_filename + ': ' + e.message + ', using internal defaults.');
netdata.options_loaded = undefined;
dumpError(e);
}
// apply module paths to node.js process
function applyModulePaths() {
var len = netdata.options.paths.modules.length;
while(len--)
process.mainModule.paths.unshift(netdata.options.paths.modules[len]);
}
applyModulePaths();
// --------------------------------------------------------------------------------------------------------------------
// tracing
function dumpError(err) {
if (typeof err === 'object') {
if (err.stack) {
netdata.debug(err.stack);
}
}
}
// --------------------------------------------------------------------------------------------------------------------
// get command line arguments
{
var found_myself = false;
var found_number = false;
var found_modules = false;
process.argv.forEach(function (val, index, array) {
netdata.debug('PARAM: ' + val);
if(!found_myself) {
if(val === __filename)
found_myself = true;
}
else {
switch(val) {
case 'debug':
netdata.options.DEBUG = true;
netdata.debug('DEBUG enabled');
break;
default:
if(found_number === true) {
if(found_modules === false) {
for(var i in netdata.options.modules)
netdata.options.modules[i].enabled = false;
}
if(typeof netdata.options.modules[val] === 'undefined')
netdata.options.modules[val] = {};
netdata.options.modules[val].enabled = true;
netdata.options.modules_enable_all = false;
netdata.debug('enabled module ' + val);
}
else {
try {
var x = parseInt(val);
if(x > 0) {
netdata.options.update_every = x;
if(netdata.options.update_every < NETDATA_UPDATE_EVERY) {
netdata.options.update_every = NETDATA_UPDATE_EVERY;
netdata.debug('Update frequency ' + x + 's is too low');
}
found_number = true;
netdata.debug('Update frequency set to ' + netdata.options.update_every + ' seconds');
}
else netdata.error('Ignoring parameter: ' + val);
}
catch(e) {
netdata.error('Cannot get value of parameter: ' + val);
dumpError(e);
}
}
break;
}
}
});
}
if(netdata.options.update_every < 1) {
netdata.debug('Adjusting update frequency to 1 second');
netdata.options.update_every = 1;
}
// --------------------------------------------------------------------------------------------------------------------
// find modules
function findModules() {
var found = 0;
var files = fs.readdirSync(NODE_D_DIR);
var len = files.length;
while(len--) {
var m = files[len].match('.node.js' + '$');
if(m !== null) {
var n = files[len].substring(0, m.index);
if(typeof(netdata.options.modules[n]) === 'undefined')
netdata.options.modules[n] = { name: n, enabled: netdata.options.modules_enable_all };
if(netdata.options.modules[n].enabled === true) {
netdata.options.modules[n].name = n;
netdata.options.modules[n].filename = NODE_D_DIR + '/' + files[len];
netdata.options.modules[n].loaded = false;
if(typeof(netdata.options.modules[n].config_filename) !== 'string')
netdata.options.modules[n].config_filename = pluginConfig(files[len]);
// load the module
try {
netdata.debug('loading module ' + netdata.options.modules[n].filename);
netdata.options.modules[n].module = require(netdata.options.modules[n].filename);
netdata.options.modules[n].module.name = n;
netdata.debug('loaded module ' + netdata.options.modules[n].name + ' from ' + netdata.options.modules[n].filename);
}
catch(e) {
netdata.options.modules[n].enabled = false;
netdata.error('Cannot load module: ' + netdata.options.modules[n].filename + ' exception: ' + e);
dumpError(e);
continue;
}
// load its configuration
var c = {
enable_autodetect: netdata.options.modules_enable_autodetect,
update_every: netdata.options.update_every
};
try {
netdata.debug('loading module\'s ' + netdata.options.modules[n].name + ' config ' + netdata.options.modules[n].config_filename);
var c2 = JSON.parse(fs.readFileSync(netdata.options.modules[n].config_filename, 'utf8'));
extend(true, c, c2);
netdata.debug('loaded module\'s ' + netdata.options.modules[n].name + ' config ' + netdata.options.modules[n].config_filename);
}
catch(e) {
netdata.error('Cannot load module\'s ' + netdata.options.modules[n].name + ' config from ' + netdata.options.modules[n].config_filename + ' exception: ' + e + ', using internal defaults.');
dumpError(e);
}
// call module auto-detection / configuration
try {
netdata.modules_configuring++;
netdata.debug('Configuring module ' + netdata.options.modules[n].name);
var serv = netdata.configure(netdata.options.modules[n].module, c, function() {
netdata.debug('Configured module ' + netdata.options.modules[n].name);
netdata.modules_configuring--;
});
netdata.debug('Configuring module ' + netdata.options.modules[n].name + ' reports ' + serv + ' eligible services.');
}
catch(e) {
netdata.modules_configuring--;
netdata.options.modules[n].enabled = false;
netdata.error('Failed module auto-detection: ' + netdata.options.modules[n].name + ' exception: ' + e + ', disabling module.');
dumpError(e);
continue;
}
netdata.options.modules[n].loaded = true;
found++;
}
}
}
// netdata.debug(netdata.options.modules);
return found;
}
if(findModules() === 0) {
netdata.error('Cannot load any .node.js module from: ' + NODE_D_DIR);
netdata.disableNodePlugin();
process.exit(1);
}
// --------------------------------------------------------------------------------------------------------------------
// start
function start_when_configuring_ends() {
if(netdata.modules_configuring > 0) {
netdata.debug('Waiting modules configuration, still running ' + netdata.modules_configuring);
setTimeout(start_when_configuring_ends, 500);
return;
}
netdata.modules_configuring = 0;
netdata.start();
}
start_when_configuring_ends();
//netdata.debug('netdata object:')
//netdata.debug(netdata);