]> arthur.barton.de Git - netdata.git/blob - plugins.d/node.d.plugin
Merge remote-tracking branch 'upstream/master' into health
[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 http = require('http');
34 var path = require('path');
35 var extend = require('extend');
36 var netdata = require('netdata');
37
38
39 // --------------------------------------------------------------------------------------------------------------------
40 // configuration
41
42 function pluginConfig(filename) {
43     var f = path.basename(filename);
44
45     // node.d.plugin configuration
46     var m = f.match('.plugin' + '$');
47     if(m !== null)
48         return netdata.options.paths.config + '/' + f.substring(0, m.index) + '.conf';
49
50     // node.d modules configuration
51     m = f.match('.node.js' + '$');
52     if(m !== null)
53         return netdata.options.paths.config + '/node.d/' + f.substring(0, m.index) + '.conf';
54
55     return netdata.options.paths.config + '/node.d/' + f + '.conf';
56 }
57
58 // internal defaults
59 extend(true, netdata.options, {
60     filename: path.basename(__filename),
61
62     update_every: NETDATA_UPDATE_EVERY,
63
64     exit_after_ms: 3600 * 4 * 1000,
65
66     paths: {
67         plugins: NETDATA_PLUGINS_DIR,
68         config: NETDATA_CONFIG_DIR,
69         modules: [],
70     },
71
72     modules_enable_autodetect: true,
73     modules_enable_all: true,
74     modules: {},
75 });
76 netdata.options.config_filename = pluginConfig(__filename);
77
78 // load configuration file
79 try {
80     netdata.options_loaded = JSON.parse(fs.readFileSync(netdata.options.config_filename, 'utf8'));
81     extend(true, netdata.options, netdata.options_loaded);
82     console.error('merged netdata object:');
83     console.error(netdata);
84 }
85 catch(e) {
86     netdata.error('Cannot read configuration file ' + netdata.options.config_filename + ': ' + e.message + ', using internal defaults.');
87     netdata.options_loaded = undefined;
88     dumpError(e);
89 }
90
91
92 // apply module paths to node.js process
93 function applyModulePaths() {
94     var len = netdata.options.paths.modules.length;
95     while(len--)
96         process.mainModule.paths.unshift(netdata.options.paths.modules[len]);
97 }
98 applyModulePaths();
99
100
101 // --------------------------------------------------------------------------------------------------------------------
102 // tracing
103
104 function dumpError(err) {
105     if (typeof err === 'object') {
106         if (err.stack) {
107             netdata.debug(err.stack);
108         }
109     }
110 }
111
112 // --------------------------------------------------------------------------------------------------------------------
113 // get command line arguments
114 {
115     var found_myself = false;
116     var found_number = false;
117     var found_modules = false;
118     process.argv.forEach(function (val, index, array) {
119         netdata.debug('PARAM: ' + val);
120
121         if(!found_myself) {
122             if(val === __filename)
123                 found_myself = true;
124         }
125         else {
126             switch(val) {
127                 case 'debug':
128                     netdata.options.DEBUG = true;
129                     netdata.debug('DEBUG enabled');
130                     break;
131
132                 default:
133                     if(found_number === true) {
134                         if(found_modules === false) {
135                             for(var i in netdata.options.modules)
136                                 netdata.options.modules[i].enabled = false;
137                         }
138
139                         if(typeof netdata.options.modules[val] === 'undefined')
140                             netdata.options.modules[val] = {};
141
142                         netdata.options.modules[val].enabled = true;
143                         netdata.options.modules_enable_all = false;
144                         netdata.debug('enabled module ' + val);
145                     }
146                     else {
147                         try {
148                             var x = parseInt(val);
149                             if(x > 0) {
150                                 netdata.options.update_every = x;
151                                 if(netdata.options.update_every < NETDATA_UPDATE_EVERY) {
152                                     netdata.options.update_every = NETDATA_UPDATE_EVERY;
153                                     netdata.debug('Update frequency ' + x + 's is too low');
154                                 }
155
156                                 found_number = true;
157                                 netdata.debug('Update frequency set to ' + netdata.options.update_every + ' seconds');
158                             }
159                             else netdata.error('Ignoring parameter: ' + val);
160                         }
161                         catch(e) {
162                             netdata.error('Cannot get value of parameter: ' + val);
163                             dumpError(e);
164                         }
165                     }
166                     break;
167             }
168         }
169     });
170 }
171
172 if(netdata.options.update_every < 1) {
173     netdata.debug('Adjusting update frequency to 1 second');
174     netdata.options.update_every = 1;
175 }
176
177 // --------------------------------------------------------------------------------------------------------------------
178 // find modules
179
180 function findModules() {
181     var found = 0;
182
183     var files = fs.readdirSync(NODE_D_DIR);
184     var len = files.length;
185     while(len--) {
186         var m = files[len].match('.node.js' + '$');
187         if(m !== null) {
188             var n = files[len].substring(0, m.index);
189
190             if(typeof(netdata.options.modules[n]) === 'undefined')
191                 netdata.options.modules[n] = { name: n, enabled: netdata.options.modules_enable_all };
192
193             if(netdata.options.modules[n].enabled === true) {
194                 netdata.options.modules[n].name = n;
195                 netdata.options.modules[n].filename = NODE_D_DIR + '/' + files[len];
196                 netdata.options.modules[n].loaded = false;
197
198                 if(typeof(netdata.options.modules[n].config_filename) !== 'string')
199                     netdata.options.modules[n].config_filename = pluginConfig(files[len]);
200
201                 // load the module
202                 try {
203                     netdata.debug('loading module ' + netdata.options.modules[n].filename);
204                     netdata.options.modules[n].module = require(netdata.options.modules[n].filename);
205                     netdata.options.modules[n].module.name = n;
206                     netdata.debug('loaded module ' + netdata.options.modules[n].name + ' from ' + netdata.options.modules[n].filename);
207                 }
208                 catch(e) {
209                     netdata.options.modules[n].enabled = false;
210                     netdata.error('Cannot load module: ' + netdata.options.modules[n].filename + ' exception: ' + e);
211                     dumpError(e);
212                     continue;
213                 }
214
215                 // load its configuration
216                 var c = {
217                     enable_autodetect: netdata.options.modules_enable_autodetect,
218                     update_every: netdata.options.update_every
219                 };
220                 try {
221                     netdata.debug('loading module\'s ' + netdata.options.modules[n].name + ' config ' + netdata.options.modules[n].config_filename);
222                     var c2 = JSON.parse(fs.readFileSync(netdata.options.modules[n].config_filename, 'utf8'));
223                     extend(true, c, c2);
224                     netdata.debug('loaded module\'s ' + netdata.options.modules[n].name + ' config ' + netdata.options.modules[n].config_filename);
225                 }
226                 catch(e) {
227                     netdata.error('Cannot load module\'s ' + netdata.options.modules[n].name + ' config from ' + netdata.options.modules[n].config_filename + ' exception: ' + e + ', using internal defaults.');
228                     dumpError(e);
229                 }
230
231                 // call module auto-detection / configuration
232                 try {
233                     netdata.modules_configuring++;
234                     netdata.debug('Configuring module ' + netdata.options.modules[n].name);
235                     var serv = netdata.configure(netdata.options.modules[n].module, c, function() {
236                         netdata.debug('Configured module ' + netdata.options.modules[n].name);
237                         netdata.modules_configuring--;
238                     });
239
240                     netdata.debug('Configuring module ' + netdata.options.modules[n].name + ' reports ' + serv + ' eligible services.');
241                 }
242                 catch(e) {
243                     netdata.modules_configuring--;
244                     netdata.options.modules[n].enabled = false;
245                     netdata.error('Failed module auto-detection: ' + netdata.options.modules[n].name + ' exception: ' + e + ', disabling module.');
246                     dumpError(e);
247                     continue;
248                 }
249
250                 netdata.options.modules[n].loaded = true;
251                 found++;
252             }
253         }
254     }
255
256     // netdata.debug(netdata.options.modules);
257     return found;
258 }
259
260 if(findModules() === 0) {
261     netdata.error('Cannot load any .node.js module from: ' + NODE_D_DIR);
262     netdata.disableNodePlugin();
263     process.exit(1);
264 }
265
266
267 // --------------------------------------------------------------------------------------------------------------------
268 // start
269
270 function start_when_configuring_ends() {
271     if(netdata.modules_configuring > 0) {
272         netdata.debug('Waiting modules configuration, still running ' + netdata.modules_configuring);
273         setTimeout(start_when_configuring_ends, 500);
274         return;
275     }
276
277     netdata.modules_configuring = 0;
278     netdata.start();
279 }
280 start_when_configuring_ends();
281
282 //netdata.debug('netdata object:')
283 //netdata.debug(netdata);