]> arthur.barton.de Git - netdata.git/blob - plugins.d/node.d.plugin
Merge pull request #1111 from ktsaou/master
[netdata.git] / plugins.d / node.d.plugin
1 #!/usr/bin/env bash
2 ':' //; exec "$(command -v nodejs || command -v node || command -v js || echo "ERROR node.js IS NOT AVAILABLE IN THIS SYSTEM")" "$0" "$@"
3
4 // shebang hack from:
5 // http://unix.stackexchange.com/questions/65235/universal-node-js-shebang
6
7 // Initially this is run as a shell script (#!/bin/sh).
8 // Then, the second line, finds nodejs or node or js in the system path
9 // and executes it with the shell parameters.
10
11 // --------------------------------------------------------------------------------------------------------------------
12
13 'use strict';
14
15 // --------------------------------------------------------------------------------------------------------------------
16 // get NETDATA environment variables
17
18 var NETDATA_PLUGINS_DIR = process.env.NETDATA_PLUGINS_DIR || __dirname;
19 var NETDATA_CONFIG_DIR = process.env.NETDATA_CONFIG_DIR || '/etc/netdata';
20 var NETDATA_UPDATE_EVERY = process.env.NETDATA_UPDATE_EVERY || 1;
21 var NODE_D_DIR = NETDATA_PLUGINS_DIR + '/../node.d';
22
23 // make sure the modules are found
24 process.mainModule.paths.unshift(NODE_D_DIR + '/node_modules');
25 process.mainModule.paths.unshift(NODE_D_DIR);
26
27
28 // --------------------------------------------------------------------------------------------------------------------
29 // load required modules
30
31 var fs = require('fs');
32 var url = require('url');
33 var util = require('util');
34 var http = require('http');
35 var path = require('path');
36 var extend = require('extend');
37 var netdata = require('netdata');
38
39
40 // --------------------------------------------------------------------------------------------------------------------
41 // configuration
42
43 function pluginConfig(filename) {
44     var f = path.basename(filename);
45
46     // node.d.plugin configuration
47     var m = f.match('.plugin' + '$');
48     if(m !== null)
49         return netdata.options.paths.config + '/' + f.substring(0, m.index) + '.conf';
50
51     // node.d modules configuration
52     m = f.match('.node.js' + '$');
53     if(m !== null)
54         return netdata.options.paths.config + '/node.d/' + f.substring(0, m.index) + '.conf';
55
56     return netdata.options.paths.config + '/node.d/' + f + '.conf';
57 }
58
59 // internal defaults
60 extend(true, netdata.options, {
61     filename: path.basename(__filename),
62
63     update_every: NETDATA_UPDATE_EVERY,
64
65     paths: {
66         plugins: NETDATA_PLUGINS_DIR,
67         config: NETDATA_CONFIG_DIR,
68         modules: [],
69     },
70
71     modules_enable_autodetect: true,
72     modules_enable_all: true,
73     modules: {},
74 });
75 netdata.options.config_filename = pluginConfig(__filename);
76
77 // load configuration file
78 try {
79     netdata.options_loaded = JSON.parse(fs.readFileSync(netdata.options.config_filename, 'utf8'));
80     extend(true, netdata.options, netdata.options_loaded);
81
82     if(!netdata.options.paths.plugins)
83         netdata.options.paths.plugins = NETDATA_PLUGINS_DIR;
84
85     if(!netdata.options.paths.config)
86         netdata.options.paths.config = NETDATA_CONFIG_DIR;
87
88     // console.error('merged netdata object:');
89     // console.error(util.inspect(netdata, {depth: 10}));
90 }
91 catch(e) {
92     netdata.error('Cannot read configuration file ' + netdata.options.config_filename + ': ' + e.message + ', using internal defaults.');
93     netdata.options_loaded = undefined;
94     dumpError(e);
95 }
96
97
98 // apply module paths to node.js process
99 function applyModulePaths() {
100     var len = netdata.options.paths.modules.length;
101     while(len--)
102         process.mainModule.paths.unshift(netdata.options.paths.modules[len]);
103 }
104 applyModulePaths();
105
106
107 // --------------------------------------------------------------------------------------------------------------------
108 // tracing
109
110 function dumpError(err) {
111     if (typeof err === 'object') {
112         if (err.stack) {
113             netdata.debug(err.stack);
114         }
115     }
116 }
117
118 // --------------------------------------------------------------------------------------------------------------------
119 // get command line arguments
120 {
121     var found_myself = false;
122     var found_number = false;
123     var found_modules = false;
124     process.argv.forEach(function (val, index, array) {
125         netdata.debug('PARAM: ' + val);
126
127         if(!found_myself) {
128             if(val === __filename)
129                 found_myself = true;
130         }
131         else {
132             switch(val) {
133                 case 'debug':
134                     netdata.options.DEBUG = true;
135                     netdata.debug('DEBUG enabled');
136                     break;
137
138                 default:
139                     if(found_number === true) {
140                         if(found_modules === false) {
141                             for(var i in netdata.options.modules)
142                                 netdata.options.modules[i].enabled = false;
143                         }
144
145                         if(typeof netdata.options.modules[val] === 'undefined')
146                             netdata.options.modules[val] = {};
147
148                         netdata.options.modules[val].enabled = true;
149                         netdata.options.modules_enable_all = false;
150                         netdata.debug('enabled module ' + val);
151                     }
152                     else {
153                         try {
154                             var x = parseInt(val);
155                             if(x > 0) {
156                                 netdata.options.update_every = x;
157                                 if(netdata.options.update_every < NETDATA_UPDATE_EVERY) {
158                                     netdata.options.update_every = NETDATA_UPDATE_EVERY;
159                                     netdata.debug('Update frequency ' + x + 's is too low');
160                                 }
161
162                                 found_number = true;
163                                 netdata.debug('Update frequency set to ' + netdata.options.update_every + ' seconds');
164                             }
165                             else netdata.error('Ignoring parameter: ' + val);
166                         }
167                         catch(e) {
168                             netdata.error('Cannot get value of parameter: ' + val);
169                             dumpError(e);
170                         }
171                     }
172                     break;
173             }
174         }
175     });
176 }
177
178 if(netdata.options.update_every < 1) {
179     netdata.debug('Adjusting update frequency to 1 second');
180     netdata.options.update_every = 1;
181 }
182
183 // --------------------------------------------------------------------------------------------------------------------
184 // find modules
185
186 function findModules() {
187     var found = 0;
188
189     var files = fs.readdirSync(NODE_D_DIR);
190     var len = files.length;
191     while(len--) {
192         var m = files[len].match('.node.js' + '$');
193         if(m !== null) {
194             var n = files[len].substring(0, m.index);
195
196             if(typeof(netdata.options.modules[n]) === 'undefined')
197                 netdata.options.modules[n] = { name: n, enabled: netdata.options.modules_enable_all };
198
199             if(netdata.options.modules[n].enabled === true) {
200                 netdata.options.modules[n].name = n;
201                 netdata.options.modules[n].filename = NODE_D_DIR + '/' + files[len];
202                 netdata.options.modules[n].loaded = false;
203
204                 if(typeof(netdata.options.modules[n].config_filename) !== 'string')
205                     netdata.options.modules[n].config_filename = pluginConfig(files[len]);
206
207                 // load the module
208                 try {
209                     netdata.debug('loading module ' + netdata.options.modules[n].filename);
210                     netdata.options.modules[n].module = require(netdata.options.modules[n].filename);
211                     netdata.options.modules[n].module.name = n;
212                     netdata.debug('loaded module ' + netdata.options.modules[n].name + ' from ' + netdata.options.modules[n].filename);
213                 }
214                 catch(e) {
215                     netdata.options.modules[n].enabled = false;
216                     netdata.error('Cannot load module: ' + netdata.options.modules[n].filename + ' exception: ' + e);
217                     dumpError(e);
218                     continue;
219                 }
220
221                 // load its configuration
222                 var c = {
223                     enable_autodetect: netdata.options.modules_enable_autodetect,
224                     update_every: netdata.options.update_every
225                 };
226                 try {
227                     netdata.debug('loading module\'s ' + netdata.options.modules[n].name + ' config ' + netdata.options.modules[n].config_filename);
228                     var c2 = JSON.parse(fs.readFileSync(netdata.options.modules[n].config_filename, 'utf8'));
229                     extend(true, c, c2);
230                     netdata.debug('loaded module\'s ' + netdata.options.modules[n].name + ' config ' + netdata.options.modules[n].config_filename);
231                 }
232                 catch(e) {
233                     netdata.error('Cannot load module\'s ' + netdata.options.modules[n].name + ' config from ' + netdata.options.modules[n].config_filename + ' exception: ' + e + ', using internal defaults.');
234                     dumpError(e);
235                 }
236
237                 // call module auto-detection / configuration
238                 try {
239                     netdata.modules_configuring++;
240                     netdata.debug('Configuring module ' + netdata.options.modules[n].name);
241                     var serv = netdata.configure(netdata.options.modules[n].module, c, function() {
242                         netdata.debug('Configured module ' + netdata.options.modules[n].name);
243                         netdata.modules_configuring--;
244                     });
245
246                     netdata.debug('Configuring module ' + netdata.options.modules[n].name + ' reports ' + serv + ' eligible services.');
247                 }
248                 catch(e) {
249                     netdata.modules_configuring--;
250                     netdata.options.modules[n].enabled = false;
251                     netdata.error('Failed module auto-detection: ' + netdata.options.modules[n].name + ' exception: ' + e + ', disabling module.');
252                     dumpError(e);
253                     continue;
254                 }
255
256                 netdata.options.modules[n].loaded = true;
257                 found++;
258             }
259         }
260     }
261
262     // netdata.debug(netdata.options.modules);
263     return found;
264 }
265
266 if(findModules() === 0) {
267     netdata.error('Cannot load any .node.js module from: ' + NODE_D_DIR);
268     netdata.disableNodePlugin();
269     process.exit(1);
270 }
271
272
273 // --------------------------------------------------------------------------------------------------------------------
274 // start
275
276 function start_when_configuring_ends() {
277     if(netdata.modules_configuring > 0) {
278         netdata.debug('Waiting modules configuration, still running ' + netdata.modules_configuring);
279         setTimeout(start_when_configuring_ends, 500);
280         return;
281     }
282
283     netdata.modules_configuring = 0;
284     netdata.start();
285 }
286 start_when_configuring_ends();
287
288 //netdata.debug('netdata object:')
289 //netdata.debug(netdata);