@cryptotaxi247 / netdata-1 / commits / 1081013ba

converted from dos to unix

Costa Tsaousis (ktsaou) committed Feb 6, 2016 at 07:10 UTC 1081013ba164de80513395b6180e36452c6c5848
1 file changed +607 -593
node.d/node_modules/netdata.js
+607 -593
@@ -1,593 +1,607 @@
1 -'use strict';
2 -
3 -var url = require('url');
4 -var http = require('http');
5 -var util = require('util');
6 -
7 -/*
8 -var netdata = require('netdata');
9 -
10 -var example_chart = {
11 - id: 'id', // the unique id of the chart
12 - name: 'name', // the name of the chart
13 - title: 'title', // the title of the chart
14 - units: 'units', // the units of the chart dimensions
15 - family: 'family', // the family of the chart
16 - category: 'category', // the category of the chart
17 - type: netdata.chartTypes.line, // the type of the chart
18 - priority: 0, // the priority relative to others in the same family and category
19 - update_every: 1, // the expected update frequency of the chart
20 - dimensions: {
21 - 'dim1': {
22 - id: 'dim1', // the unique id of the dimension
23 - name: 'name', // the name of the dimension
24 - algorithm: netdata.chartAlgorithms.absolute, // the id of the netdata algorithm
25 - multiplier: 1, // the multiplier
26 - divisor: 1, // the divisor
27 - hidden: false, // is hidden (boolean)
28 - },
29 - 'dim2': {
30 - id: 'dim2', // the unique id of the dimension
31 - name: 'name', // the name of the dimension
32 - algorithm: 'absolute', // the id of the netdata algorithm
33 - multiplier: 1, // the multiplier
34 - divisor: 1, // the divisor
35 - hidden: false, // is hidden (boolean)
36 - }
37 - // add as many dimensions as needed
38 - }
39 -};
40 -*/
41 -
42 -var netdata = {
43 - options: {
44 - filename: __filename,
45 - DEBUG: false,
46 - update_every: 1,
47 - },
48 -
49 - chartAlgorithms: {
50 - incremental: 'incremental',
51 - absolute: 'absolute',
52 - percentage_of_absolute_row: 'percentage-of-absolute-row',
53 - percentage_of_incremental_row: 'percentage-of-incremental-row'
54 - },
55 -
56 - chartTypes: {
57 - line: 'line',
58 - area: 'area',
59 - stacked: 'stacked'
60 - },
61 -
62 - services: new Array(),
63 - modules_configuring: 0,
64 - charts: {},
65 -
66 -
67 - processors: {
68 - http: {
69 - name: 'http',
70 -
71 - process: function(service, callback) {
72 - if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': making ' + this.name + ' request: ' + netdata.stringify(service.request));
73 -
74 - var req = http.request(service.request, function(response) {
75 - if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': got server response...');
76 -
77 - var end = false;
78 - var data = '';
79 - response.setEncoding('utf8');
80 -
81 - if(response.statusCode !== 200) {
82 - if(end === false) {
83 - service.error('Got HTTP code ' + response.statusCode + ', failed to get data.');
84 - end = true;
85 - callback(null);
86 - }
87 - }
88 -
89 - response.on('data', function(chunk) {
90 - if(end === false) data += chunk;
91 - });
92 -
93 - response.on('error', function() {
94 - if(end === false) {
95 - service.error(': Read error, failed to get data.');
96 - end = true;
97 - callback(null);
98 - }
99 - });
100 -
101 - response.on('end', function() {
102 - if(end === false) {
103 - if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': read completed.');
104 - end = true;
105 - callback(data);
106 - }
107 - });
108 - });
109 -
110 - req.on('error', function(e) {
111 - service.error('Failed to make request: ' + netdata.stringify(service.request) + ', message: ' + e.message);
112 - callback(null);
113 - });
114 -
115 - // write data to request body
116 - if(typeof service.postData !== 'undefined' && service.request.method === 'POST') {
117 - if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': posting data: ' + service.postData);
118 - req.write(service.postData);
119 - }
120 -
121 - req.end();
122 - }
123 - }
124 - },
125 -
126 - stringify: function(obj) {
127 - return util.inspect(obj, {depth: 10});
128 - },
129 -
130 - // show debug info, if debug is enabled
131 - debug: function(msg) {
132 - if(this.options.DEBUG === true) {
133 - var now = new Date();
134 - console.error(now.toString() + ': ' + netdata.options.filename + ': DEBUG: ' + ((typeof(msg) === 'object')?netdata.stringify(msg):msg).toString());
135 - }
136 - },
137 -
138 - // log an error
139 - error: function(msg) {
140 - var now = new Date();
141 - console.error(now.toString() + ': ' + netdata.options.filename + ': ERROR: ' + ((typeof(msg) === 'object')?netdata.stringify(msg):msg).toString());
142 - },
143 -
144 - // send data to netdata
145 - send: function(msg) {
146 - console.log(msg.toString());
147 - },
148 -
149 - service: function(service) {
150 - if(typeof service === 'undefined')
151 - service = {};
152 -
153 - service._current_chart = null; // the current chart we work on
154 - service._queue = ''; // data to be sent to netdata
155 -
156 - service.error_reported = false; // error log flood control
157 -
158 - service.added = false; // added to netdata.services
159 - service.enabled = true;
160 - service.updates = 0;
161 - service.running = false;
162 - service.started = 0;
163 - service.ended = 0;
164 - service.next_run = new Date().getTime();
165 -
166 - if(typeof service.update_every === 'undefined')
167 - service.update_every = service.module.update_every;
168 -
169 - if(typeof service.update_every === 'undefined')
170 - service.update_every = netdata.options.update_every;
171 -
172 - if(typeof service.processor === 'undefined')
173 - service.processor = netdata.processors.http;
174 -
175 - if(service.update_every < netdata.options.update_every)
176 - service.update_every = netdata.options.update_every;
177 -
178 - service.commit = function() {
179 - if(this.added !== true) {
180 - this.added = true;
181 -
182 - var now = new Date().getTime();
183 - while( this.next_run < now )
184 - this.next_run += (this.update_every * 1000);
185 -
186 - netdata.services.push(this);
187 - if(netdata.options.DEBUG === true) netdata.debug(this.module.name + ': ' + this.name + ': service committed.');
188 - }
189 - };
190 -
191 - service.execute = function(callback) {
192 - this.module.active++;
193 - this.running = true;
194 - this.started = new Date().getTime();
195 - this.updates++;
196 -
197 - if(netdata.options.DEBUG === true)
198 - netdata.debug(this.module.name + ': ' + this.name + ': making ' + this.processor.name + ' request: ' + netdata.stringify(this));
199 -
200 - this.processor.process(this, function(response) {
201 - service.ended = new Date().getTime();
202 - service.duration = service.ended - service.started;
203 -
204 - if(typeof response === 'undefined')
205 - response = null;
206 -
207 - if(response !== null)
208 - service.errorClear();
209 -
210 - if(netdata.options.DEBUG === true)
211 - netdata.debug(service.module.name + ': ' + service.name + ': processing ' + service.processor.name + ' response (received in ' + (service.ended - service.started).toString() + ' ms)');
212 -
213 - callback(service, response);
214 -
215 - service.running = false;
216 - service.module.active--;
217 - if(service.module.active < 0) {
218 - service.module.active = 0;
219 - if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': active module counter below zero.');
220 - }
221 -
222 - if(service.module.active === 0) {
223 - // check if we run under configure
224 - if(service.module.configure_callback !== null) {
225 - if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': configuration finish callback called from processResponse().');
226 - var ccallback = service.module.configure_callback;
227 - service.module.configure_callback = null;
228 - ccallback();
229 - }
230 - }
231 - });
232 - };
233 -
234 - service.update = function() {
235 - if(netdata.options.DEBUG === true) netdata.debug(this.module.name + ': ' + this.name + ': starting data collection...');
236 -
237 - this.module.update(this, function() {
238 - if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': data collection ended in ' + service.duration.toString() + ' ms.');
239 - });
240 - };
241 -
242 - service.error = function(message) {
243 - if(this.error_reported === false) {
244 - netdata.error(this.module.name + ': ' + this.name + ': ' + message);
245 - this.error_reported = true;
246 - }
247 - else if(netdata.options.DEBUG === true)
248 - netdata.debug(this.module.name + ': ' + this.name + ': ' + message);
249 - };
250 -
251 - service.errorClear = function() {
252 - this.error_reported = false;
253 - };
254 -
255 - service.queue = function(txt) {
256 - this._queue += txt + '\n';
257 - };
258 -
259 - service._send_chart_to_netdata = function(chart) {
260 - // internal function to send a chart to netdata
261 - this.queue('CHART "' + chart.id + '" "' + chart.name + '" "' + chart.title + '" "' + chart.units + '" "' + chart.family + '" "' + chart.category + '" "' + chart.type + '" ' + chart.priority.toString() + ' ' + chart.update_every.toString());
262 -
263 - for(var dim in chart.dimensions) {
264 - var d = chart.dimensions[dim];
265 -
266 - this.queue('DIMENSION "' + d.id + '" "' + d.name + '" "' + d.algorithm + '" ' + d.multiplier.toString() + ' ' + d.divisor.toString() + ' ' + ((d.hidden === true)?'hidden':'').toString());
267 - d._created = true;
268 - d._updated = false;
269 - }
270 -
271 - chart._created = true;
272 - chart._updated = false;
273 - };
274 -
275 - // begin data collection for a chart
276 - service.begin = function(chart) {
277 - if(this._current_chart !== null && this._current_chart !== chart) {
278 - this.error('Called begin() for chart ' + chart.id + ' while chart ' + this._current_chart.id + ' is still open. Closing it.');
279 - this.end();
280 - }
281 -
282 - if(typeof(chart.id) === 'undefined' || netdata.charts[chart.id] != chart) {
283 - this.error('Called begin() for chart ' + chart.id + ' that is not mine. Where did you find it? Ignoring it.');
284 - return false;
285 - }
286 -
287 - if(netdata.options.DEBUG === true) netdata.debug('setting current chart to ' + chart.id);
288 - this._current_chart = chart;
289 - this._current_chart._began = true;
290 -
291 - if(this._current_chart._dimensions_count !== 0) {
292 - if(this._current_chart._created === false || this._current_chart._updated === true)
293 - this._send_chart_to_netdata(this._current_chart);
294 -
295 - var now = this.ended;
296 - this.queue('BEGIN ' + this._current_chart.id + ' ' + ((this._current_chart._last_updated > 0)?((now - this._current_chart._last_updated) * 1000):'').toString());
297 - }
298 - // else this.error('Called begin() for chart ' + chart.id + ' which is empty.');
299 -
300 - this._current_chart._last_updated = now;
301 - this._current_chart._began = true;
302 - this._current_chart._counter++;
303 -
304 - return true;
305 - };
306 -
307 - // set a collected value for a chart
308 - // we do most things on the first value we attempt to set
309 - service.set = function(dimension, value) {
310 - if(this._current_chart === null) {
311 - this.error('Called set(' + dimension + ', ' + value + ') without an open chart.');
312 - return false;
313 - }
314 -
315 - if(typeof(this._current_chart.dimensions[dimension]) === 'undefined') {
316 - this.error('Called set(' + dimension + ', ' + value + ') but dimension "' + dimension + '" does not exist in chart "' + this._current_chart.id + '".');
317 - return false;
318 - }
319 -
320 - if(typeof value === 'undefined' || value === null)
321 - return false;
322 -
323 - if(this._current_chart._dimensions_count !== 0)
324 - this.queue('SET ' + dimension + ' = ' + value);
325 -
326 - return true;
327 - };
328 -
329 - // end data collection for the current chart - after calling begin()
330 - service.end = function() {
331 - if(this._current_chart !== null && this._current_chart._began === false) {
332 - this.error('Called end() without an open chart.');
333 - return false;
334 - }
335 -
336 - if(this._current_chart._dimensions_count !== 0) {
337 - this.queue('END');
338 - netdata.send(this._queue);
339 - }
340 -
341 - this._queue = '';
342 - this._current_chart._began = false;
343 - if(netdata.options.DEBUG === true) netdata.debug('sent chart ' + this._current_chart.id);
344 - this._current_chart = null;
345 - return true;
346 - };
347 -
348 - // discard the collected values for the current chart - after calling begin()
349 - service.flush = function() {
350 - if(this._current_chart === null || this._current_chart._began === false) {
351 - this.error('Called flush() without an open chart.');
352 - return false;
353 - }
354 -
355 - this._queue = '';
356 - this._current_chart._began = false;
357 - this._current_chart = null;
358 - return true;
359 - };
360 -
361 - // create a netdata chart
362 - service.chart = function(id, chart) {
363 - if(typeof(netdata.charts[id]) === 'undefined') {
364 - netdata.charts[id] = {
365 - _created: false,
366 - _updated: true,
367 - _began: false,
368 - _counter: 0,
369 - _last_updated: 0,
370 - _dimensions_count: 0,
371 - id: id,
372 - name: id,
373 - title: 'untitled chart',
374 - units: 'a unit',
375 - family: '',
376 - category: '',
377 - type: netdata.chartTypes.line,
378 - priority: 0,
379 - update_every: netdata.options.update_every,
380 - dimensions: {}
381 - };
382 - }
383 -
384 - var c = netdata.charts[id];
385 -
386 - if(typeof(chart.name) !== 'undefined' && chart.name !== c.name) {
387 - if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its name');
388 - c.name = chart.name;
389 - c._updated = true;
390 - }
391 -
392 - if(typeof(chart.title) !== 'undefined' && chart.title !== c.title) {
393 - if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its title');
394 - c.title = chart.title;
395 - c._updated = true;
396 - }
397 -
398 - if(typeof(chart.units) !== 'undefined' && chart.units !== c.units) {
399 - if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its units');
400 - c.units = chart.units;
401 - c._updated = true;
402 - }
403 -
404 - if(typeof(chart.family) !== 'undefined' && chart.family !== c.family) {
405 - if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its family');
406 - c.family = chart.family;
407 - c._updated = true;
408 - }
409 -
410 - if(typeof(chart.category) !== 'undefined' && chart.category !== c.category) {
411 - if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its category');
412 - c.category = chart.category;
413 - c._updated = true;
414 - }
415 -
416 - if(typeof(chart.type) !== 'undefined' && chart.type !== c.type) {
417 - if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its type');
418 - c.type = chart.type;
419 - c._updated = true;
420 - }
421 -
422 - if(typeof(chart.priority) !== 'undefined' && chart.priority !== c.priority) {
423 - if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its priority');
424 - c.priority = chart.priority;
425 - c._updated = true;
426 - }
427 -
428 - if(typeof(chart.update_every) !== 'undefined' && chart.update_every !== c.update_every) {
429 - if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its update_every from ' + c.update_every + ' to ' + chart.update_every);
430 - c.update_every = chart.update_every;
431 - c._updated = true;
432 - }
433 -
434 - if(typeof(chart.dimensions) !== 'undefined') {
435 - for(var x in chart.dimensions) {
436 - if(typeof(c.dimensions[x]) === 'undefined') {
437 - c._dimensions_count++;
438 -
439 - c.dimensions[x] = {
440 - _created: false,
441 - _updated: false,
442 - id: x, // the unique id of the dimension
443 - name: x, // the name of the dimension
444 - algorithm: netdata.chartAlgorithms.absolute, // the id of the netdata algorithm
445 - multiplier: 1, // the multiplier
446 - divisor: 1, // the divisor
447 - hidden: false, // is hidden (boolean)
448 - };
449 -
450 - if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' created dimension ' + x);
451 - c._updated = true;
452 - }
453 -
454 - var dim = chart.dimensions[x];
455 - var d = c.dimensions[x];
456 -
457 - if(typeof(dim.name) !== 'undefined' && d.name !== dim.name) {
458 - if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ', dimension ' + x + ' updated its name');
459 - d.name = dim.name;
460 - d._updated = true;
461 - }
462 -
463 - if(typeof(dim.algorithm) !== 'undefined' && d.algorithm !== dim.algorithm) {
464 - if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ', dimension ' + x + ' updated its algorithm from ' + d.algorithm + ' to ' + dim.algorithm);
465 - d.algorithm = dim.algorithm;
466 - d._updated = true;
467 - }
468 -
469 - if(typeof(dim.multiplier) !== 'undefined' && d.multiplier !== dim.multiplier) {
470 - if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ', dimension ' + x + ' updated its multiplier');
471 - d.multiplier = dim.multiplier;
472 - d._updated = true;
473 - }
474 -
475 - if(typeof(dim.divisor) !== 'undefined' && d.divisor !== dim.divisor) {
476 - if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ', dimension ' + x + ' updated its divisor');
477 - d.divisor = dim.divisor;
478 - d._updated = true;
479 - }
480 -
481 - if(typeof(dim.hidden) !== 'undefined' && d.hidden !== dim.hidden) {
482 - if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ', dimension ' + x + ' updated its hidden status');
483 - d.hidden = dim.hidden;
484 - d._updated = true;
485 - }
486 -
487 - if(d._updated) c._updated = true;
488 - }
489 - }
490 -
491 - //if(netdata.options.DEBUG === true) netdata.debug(netdata.charts);
492 - return netdata.charts[id];
493 - };
494 -
495 - return service;
496 - },
497 -
498 - runAllServices: function() {
499 - if(netdata.options.DEBUG === true) netdata.debug('runAllServices()');
500 -
501 - var now = new Date().getTime();
502 - var len = netdata.services.length;
503 - while(len--) {
504 - var service = netdata.services[len];
505 -
506 - if(service.enabled === false || service.running === true) continue;
507 - if(now <= service.next_run) continue;
508 -
509 - service.update();
510 -
511 - now = new Date().getTime();
512 - while(service.next_run < now)
513 - service.next_run += (service.update_every * 1000);
514 - }
515 -
516 - // 1/10th of update_every in pause
517 - setTimeout(netdata.runAllServices, netdata.options.update_every * 100);
518 - },
519 -
520 - start: function() {
521 - if(netdata.options.DEBUG === true) this.debug('started, services: ' + netdata.stringify(this.services));
522 -
523 - if(this.services.length === 0) {
524 - this.disableNodePlugin();
525 - process.exit(1);
526 - }
527 - else this.runAllServices();
528 - },
529 -
530 - // disable the whole node.js plugin
531 - disableNodePlugin: function() {
532 - this.send('DISABLE');
533 - process.exit(1);
534 - },
535 -
536 - requestFromParams: function(protocol, hostname, port, path, method) {
537 - return {
538 - protocol: protocol,
539 - hostname: hostname,
540 - port: port,
541 - path: path,
542 - //family: 4,
543 - method: method,
544 - headers: {
545 - 'Content-Type': 'application/x-www-form-urlencoded',
546 - 'Connection': 'keep-alive'
547 - },
548 - agent: new http.Agent({
549 - keepAlive: true,
550 - keepAliveMsecs: netdata.options.update_every * 1000,
551 - maxSockets: 2, // it must be 2 to work
552 - maxFreeSockets: 1
553 - })
554 - };
555 - },
556 -
557 - requestFromURL: function(a_url) {
558 - var u = url.parse(a_url);
559 - return netdata.requestFromParams(u.protocol, u.hostname, u.port, u.path, 'GET');
560 - },
561 -
562 - configure: function(module, config, callback) {
563 - if(netdata.options.DEBUG === true) this.debug(module.name + ': configuring (update_every: ' + this.options.update_every + ')...');
564 -
565 - module.active = 0;
566 - module.update_every = this.options.update_every;
567 -
568 - if(typeof config.update_every !== 'undefined')
569 - module.update_every = config.update_every;
570 -
571 - module.enable_autodetect = (config.enable_autodetect)?true:false;
572 -
573 - if(typeof(callback) === 'function')
574 - module.configure_callback = callback;
575 - else
576 - module.configure_callback = null;
577 -
578 - var added = module.configure(config);
579 -
580 - if(netdata.options.DEBUG === true) this.debug(module.name + ': configured, reporting ' + added + ' eligible services.');
581 -
582 - if(module.configure_callback !== null && added === 0) {
583 - if(netdata.options.DEBUG === true) this.debug(module.name + ': configuration finish callback called from configure().');
584 - module.configure_callback = null;
585 - callback();
586 - }
587 -
588 - return added;
589 - }
590 -};
591 -
592 -if(netdata.options.DEBUG === true) netdata.debug('loaded netdata from: ' + __filename);
593 -module.exports = netdata;
1 +'use strict';
2 +
3 +var url = require('url');
4 +var http = require('http');
5 +var util = require('util');
6 +
7 +/*
8 +var netdata = require('netdata');
9 +
10 +var example_chart = {
11 + id: 'id', // the unique id of the chart
12 + name: 'name', // the name of the chart
13 + title: 'title', // the title of the chart
14 + units: 'units', // the units of the chart dimensions
15 + family: 'family', // the family of the chart
16 + category: 'category', // the category of the chart
17 + type: netdata.chartTypes.line, // the type of the chart
18 + priority: 0, // the priority relative to others in the same family and category
19 + update_every: 1, // the expected update frequency of the chart
20 + dimensions: {
21 + 'dim1': {
22 + id: 'dim1', // the unique id of the dimension
23 + name: 'name', // the name of the dimension
24 + algorithm: netdata.chartAlgorithms.absolute, // the id of the netdata algorithm
25 + multiplier: 1, // the multiplier
26 + divisor: 1, // the divisor
27 + hidden: false, // is hidden (boolean)
28 + },
29 + 'dim2': {
30 + id: 'dim2', // the unique id of the dimension
31 + name: 'name', // the name of the dimension
32 + algorithm: 'absolute', // the id of the netdata algorithm
33 + multiplier: 1, // the multiplier
34 + divisor: 1, // the divisor
35 + hidden: false, // is hidden (boolean)
36 + }
37 + // add as many dimensions as needed
38 + }
39 +};
40 +*/
41 +
42 +var netdata = {
43 + options: {
44 + filename: __filename,
45 + DEBUG: false,
46 + update_every: 1,
47 + },
48 +
49 + chartAlgorithms: {
50 + incremental: 'incremental',
51 + absolute: 'absolute',
52 + percentage_of_absolute_row: 'percentage-of-absolute-row',
53 + percentage_of_incremental_row: 'percentage-of-incremental-row'
54 + },
55 +
56 + chartTypes: {
57 + line: 'line',
58 + area: 'area',
59 + stacked: 'stacked'
60 + },
61 +
62 + services: new Array(),
63 + modules_configuring: 0,
64 + charts: {},
65 +
66 +
67 + processors: {
68 + http: {
69 + name: 'http',
70 +
71 + process: function(service, callback) {
72 + if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': making ' + this.name + ' request: ' + netdata.stringify(service.request));
73 +
74 + var req = http.request(service.request, function(response) {
75 + if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': got server response...');
76 +
77 + var end = false;
78 + var data = '';
79 + response.setEncoding('utf8');
80 +
81 + if(response.statusCode !== 200) {
82 + if(end === false) {
83 + service.error('Got HTTP code ' + response.statusCode + ', failed to get data.');
84 + end = true;
85 + callback(null);
86 + }
87 + }
88 +
89 + response.on('data', function(chunk) {
90 + if(end === false) data += chunk;
91 + });
92 +
93 + response.on('error', function() {
94 + if(end === false) {
95 + service.error(': Read error, failed to get data.');
96 + end = true;
97 + callback(null);
98 + }
99 + });
100 +
101 + response.on('end', function() {
102 + if(end === false) {
103 + if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': read completed.');
104 + end = true;
105 + callback(data);
106 + }
107 + });
108 + });
109 +
110 + req.on('error', function(e) {
111 + service.error('Failed to make request: ' + netdata.stringify(service.request) + ', message: ' + e.message);
112 + callback(null);
113 + });
114 +
115 + // write data to request body
116 + if(typeof service.postData !== 'undefined' && service.request.method === 'POST') {
117 + if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': posting data: ' + service.postData);
118 + req.write(service.postData);
119 + }
120 +
121 + req.end();
122 + }
123 + }
124 + },
125 +
126 + stringify: function(obj) {
127 + return util.inspect(obj, {depth: 10});
128 + },
129 +
130 + // show debug info, if debug is enabled
131 + debug: function(msg) {
132 + if(this.options.DEBUG === true) {
133 + var now = new Date();
134 + console.error(now.toString() + ': ' + netdata.options.filename + ': DEBUG: ' + ((typeof(msg) === 'object')?netdata.stringify(msg):msg).toString());
135 + }
136 + },
137 +
138 + // log an error
139 + error: function(msg) {
140 + var now = new Date();
141 + console.error(now.toString() + ': ' + netdata.options.filename + ': ERROR: ' + ((typeof(msg) === 'object')?netdata.stringify(msg):msg).toString());
142 + },
143 +
144 + // send data to netdata
145 + send: function(msg) {
146 + console.log(msg.toString());
147 + },
148 +
149 + service: function(service) {
150 + if(typeof service === 'undefined')
151 + service = {};
152 +
153 + service._current_chart = null; // the current chart we work on
154 + service._queue = ''; // data to be sent to netdata
155 +
156 + service.error_reported = false; // error log flood control
157 +
158 + service.added = false; // added to netdata.services
159 + service.enabled = true;
160 + service.updates = 0;
161 + service.running = false;
162 + service.started = 0;
163 + service.ended = 0;
164 + service.next_run = new Date().getTime();
165 +
166 + if(typeof service.module === 'undefined') {
167 + service.module = { name: 'not-defined-module' };
168 + service.error('Attempted to create service without a module.');
169 + service.enabled = false;
170 + }
171 +
172 + if(typeof service.name === 'undefined')
173 + service.name = 'unnamed@' + service.module.name + '/' + service.next_run;
174 +
175 + if(typeof service.update_every === 'undefined')
176 + service.update_every = service.module.update_every;
177 +
178 + if(typeof service.update_every === 'undefined')
179 + service.update_every = netdata.options.update_every;
180 +
181 + if(typeof service.processor === 'undefined')
182 + service.processor = netdata.processors.http;
183 +
184 + if(service.update_every < netdata.options.update_every)
185 + service.update_every = netdata.options.update_every;
186 +
187 + service.commit = function() {
188 + if(this.added !== true) {
189 + this.added = true;
190 +
191 + var now = new Date().getTime();
192 + while( this.next_run < now )
193 + this.next_run += (this.update_every * 1000);
194 +
195 + netdata.services.push(this);
196 + if(netdata.options.DEBUG === true) netdata.debug(this.module.name + ': ' + this.name + ': service committed.');
197 + }
198 + };
199 +
200 + service.execute = function(callback) {
201 + if(service.enabled === false) {
202 + callback(null);
203 + return;
204 + }
205 +
206 + this.module.active++;
207 + this.running = true;
208 + this.started = new Date().getTime();
209 + this.updates++;
210 +
211 + if(netdata.options.DEBUG === true)
212 + netdata.debug(this.module.name + ': ' + this.name + ': making ' + this.processor.name + ' request: ' + netdata.stringify(this));
213 +
214 + this.processor.process(this, function(response) {
215 + service.ended = new Date().getTime();
216 + service.duration = service.ended - service.started;
217 +
218 + if(typeof response === 'undefined')
219 + response = null;
220 +
221 + if(response !== null)
222 + service.errorClear();
223 +
224 + if(netdata.options.DEBUG === true)
225 + netdata.debug(service.module.name + ': ' + service.name + ': processing ' + service.processor.name + ' response (received in ' + (service.ended - service.started).toString() + ' ms)');
226 +
227 + callback(service, response);
228 +
229 + service.running = false;
230 + service.module.active--;
231 + if(service.module.active < 0) {
232 + service.module.active = 0;
233 + if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': active module counter below zero.');
234 + }
235 +
236 + if(service.module.active === 0) {
237 + // check if we run under configure
238 + if(service.module.configure_callback !== null) {
239 + if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': configuration finish callback called from processResponse().');
240 + var ccallback = service.module.configure_callback;
241 + service.module.configure_callback = null;
242 + ccallback();
243 + }
244 + }
245 + });
246 + };
247 +
248 + service.update = function() {
249 + if(netdata.options.DEBUG === true) netdata.debug(this.module.name + ': ' + this.name + ': starting data collection...');
250 +
251 + this.module.update(this, function() {
252 + if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': data collection ended in ' + service.duration.toString() + ' ms.');
253 + });
254 + };
255 +
256 + service.error = function(message) {
257 + if(this.error_reported === false) {
258 + netdata.error(this.module.name + ': ' + this.name + ': ' + message);
259 + this.error_reported = true;
260 + }
261 + else if(netdata.options.DEBUG === true)
262 + netdata.debug(this.module.name + ': ' + this.name + ': ' + message);
263 + };
264 +
265 + service.errorClear = function() {
266 + this.error_reported = false;
267 + };
268 +
269 + service.queue = function(txt) {
270 + this._queue += txt + '\n';
271 + };
272 +
273 + service._send_chart_to_netdata = function(chart) {
274 + // internal function to send a chart to netdata
275 + this.queue('CHART "' + chart.id + '" "' + chart.name + '" "' + chart.title + '" "' + chart.units + '" "' + chart.family + '" "' + chart.category + '" "' + chart.type + '" ' + chart.priority.toString() + ' ' + chart.update_every.toString());
276 +
277 + for(var dim in chart.dimensions) {
278 + var d = chart.dimensions[dim];
279 +
280 + this.queue('DIMENSION "' + d.id + '" "' + d.name + '" "' + d.algorithm + '" ' + d.multiplier.toString() + ' ' + d.divisor.toString() + ' ' + ((d.hidden === true)?'hidden':'').toString());
281 + d._created = true;
282 + d._updated = false;
283 + }
284 +
285 + chart._created = true;
286 + chart._updated = false;
287 + };
288 +
289 + // begin data collection for a chart
290 + service.begin = function(chart) {
291 + if(this._current_chart !== null && this._current_chart !== chart) {
292 + this.error('Called begin() for chart ' + chart.id + ' while chart ' + this._current_chart.id + ' is still open. Closing it.');
293 + this.end();
294 + }
295 +
296 + if(typeof(chart.id) === 'undefined' || netdata.charts[chart.id] != chart) {
297 + this.error('Called begin() for chart ' + chart.id + ' that is not mine. Where did you find it? Ignoring it.');
298 + return false;
299 + }
300 +
301 + if(netdata.options.DEBUG === true) netdata.debug('setting current chart to ' + chart.id);
302 + this._current_chart = chart;
303 + this._current_chart._began = true;
304 +
305 + if(this._current_chart._dimensions_count !== 0) {
306 + if(this._current_chart._created === false || this._current_chart._updated === true)
307 + this._send_chart_to_netdata(this._current_chart);
308 +
309 + var now = this.ended;
310 + this.queue('BEGIN ' + this._current_chart.id + ' ' + ((this._current_chart._last_updated > 0)?((now - this._current_chart._last_updated) * 1000):'').toString());
311 + }
312 + // else this.error('Called begin() for chart ' + chart.id + ' which is empty.');
313 +
314 + this._current_chart._last_updated = now;
315 + this._current_chart._began = true;
316 + this._current_chart._counter++;
317 +
318 + return true;
319 + };
320 +
321 + // set a collected value for a chart
322 + // we do most things on the first value we attempt to set
323 + service.set = function(dimension, value) {
324 + if(this._current_chart === null) {
325 + this.error('Called set(' + dimension + ', ' + value + ') without an open chart.');
326 + return false;
327 + }
328 +
329 + if(typeof(this._current_chart.dimensions[dimension]) === 'undefined') {
330 + this.error('Called set(' + dimension + ', ' + value + ') but dimension "' + dimension + '" does not exist in chart "' + this._current_chart.id + '".');
331 + return false;
332 + }
333 +
334 + if(typeof value === 'undefined' || value === null)
335 + return false;
336 +
337 + if(this._current_chart._dimensions_count !== 0)
338 + this.queue('SET ' + dimension + ' = ' + value);
339 +
340 + return true;
341 + };
342 +
343 + // end data collection for the current chart - after calling begin()
344 + service.end = function() {
345 + if(this._current_chart !== null && this._current_chart._began === false) {
346 + this.error('Called end() without an open chart.');
347 + return false;
348 + }
349 +
350 + if(this._current_chart._dimensions_count !== 0) {
351 + this.queue('END');
352 + netdata.send(this._queue);
353 + }
354 +
355 + this._queue = '';
356 + this._current_chart._began = false;
357 + if(netdata.options.DEBUG === true) netdata.debug('sent chart ' + this._current_chart.id);
358 + this._current_chart = null;
359 + return true;
360 + };
361 +
362 + // discard the collected values for the current chart - after calling begin()
363 + service.flush = function() {
364 + if(this._current_chart === null || this._current_chart._began === false) {
365 + this.error('Called flush() without an open chart.');
366 + return false;
367 + }
368 +
369 + this._queue = '';
370 + this._current_chart._began = false;
371 + this._current_chart = null;
372 + return true;
373 + };
374 +
375 + // create a netdata chart
376 + service.chart = function(id, chart) {
377 + if(typeof(netdata.charts[id]) === 'undefined') {
378 + netdata.charts[id] = {
379 + _created: false,
380 + _updated: true,
381 + _began: false,
382 + _counter: 0,
383 + _last_updated: 0,
384 + _dimensions_count: 0,
385 + id: id,
386 + name: id,
387 + title: 'untitled chart',
388 + units: 'a unit',
389 + family: '',
390 + category: '',
391 + type: netdata.chartTypes.line,
392 + priority: 0,
393 + update_every: netdata.options.update_every,
394 + dimensions: {}
395 + };
396 + }
397 +
398 + var c = netdata.charts[id];
399 +
400 + if(typeof(chart.name) !== 'undefined' && chart.name !== c.name) {
401 + if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its name');
402 + c.name = chart.name;
403 + c._updated = true;
404 + }
405 +
406 + if(typeof(chart.title) !== 'undefined' && chart.title !== c.title) {
407 + if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its title');
408 + c.title = chart.title;
409 + c._updated = true;
410 + }
411 +
412 + if(typeof(chart.units) !== 'undefined' && chart.units !== c.units) {
413 + if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its units');
414 + c.units = chart.units;
415 + c._updated = true;
416 + }
417 +
418 + if(typeof(chart.family) !== 'undefined' && chart.family !== c.family) {
419 + if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its family');
420 + c.family = chart.family;
421 + c._updated = true;
422 + }
423 +
424 + if(typeof(chart.category) !== 'undefined' && chart.category !== c.category) {
425 + if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its category');
426 + c.category = chart.category;
427 + c._updated = true;
428 + }
429 +
430 + if(typeof(chart.type) !== 'undefined' && chart.type !== c.type) {
431 + if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its type');
432 + c.type = chart.type;
433 + c._updated = true;
434 + }
435 +
436 + if(typeof(chart.priority) !== 'undefined' && chart.priority !== c.priority) {
437 + if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its priority');
438 + c.priority = chart.priority;
439 + c._updated = true;
440 + }
441 +
442 + if(typeof(chart.update_every) !== 'undefined' && chart.update_every !== c.update_every) {
443 + if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its update_every from ' + c.update_every + ' to ' + chart.update_every);
444 + c.update_every = chart.update_every;
445 + c._updated = true;
446 + }
447 +
448 + if(typeof(chart.dimensions) !== 'undefined') {
449 + for(var x in chart.dimensions) {
450 + if(typeof(c.dimensions[x]) === 'undefined') {
451 + c._dimensions_count++;
452 +
453 + c.dimensions[x] = {
454 + _created: false,
455 + _updated: false,
456 + id: x, // the unique id of the dimension
457 + name: x, // the name of the dimension
458 + algorithm: netdata.chartAlgorithms.absolute, // the id of the netdata algorithm
459 + multiplier: 1, // the multiplier
460 + divisor: 1, // the divisor
461 + hidden: false, // is hidden (boolean)
462 + };
463 +
464 + if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' created dimension ' + x);
465 + c._updated = true;
466 + }
467 +
468 + var dim = chart.dimensions[x];
469 + var d = c.dimensions[x];
470 +
471 + if(typeof(dim.name) !== 'undefined' && d.name !== dim.name) {
472 + if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ', dimension ' + x + ' updated its name');
473 + d.name = dim.name;
474 + d._updated = true;
475 + }
476 +
477 + if(typeof(dim.algorithm) !== 'undefined' && d.algorithm !== dim.algorithm) {
478 + if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ', dimension ' + x + ' updated its algorithm from ' + d.algorithm + ' to ' + dim.algorithm);
479 + d.algorithm = dim.algorithm;
480 + d._updated = true;
481 + }
482 +
483 + if(typeof(dim.multiplier) !== 'undefined' && d.multiplier !== dim.multiplier) {
484 + if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ', dimension ' + x + ' updated its multiplier');
485 + d.multiplier = dim.multiplier;
486 + d._updated = true;
487 + }
488 +
489 + if(typeof(dim.divisor) !== 'undefined' && d.divisor !== dim.divisor) {
490 + if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ', dimension ' + x + ' updated its divisor');
491 + d.divisor = dim.divisor;
492 + d._updated = true;
493 + }
494 +
495 + if(typeof(dim.hidden) !== 'undefined' && d.hidden !== dim.hidden) {
496 + if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ', dimension ' + x + ' updated its hidden status');
497 + d.hidden = dim.hidden;
498 + d._updated = true;
499 + }
500 +
501 + if(d._updated) c._updated = true;
502 + }
503 + }
504 +
505 + //if(netdata.options.DEBUG === true) netdata.debug(netdata.charts);
506 + return netdata.charts[id];
507 + };
508 +
509 + return service;
510 + },
511 +
512 + runAllServices: function() {
513 + if(netdata.options.DEBUG === true) netdata.debug('runAllServices()');
514 +
515 + var now = new Date().getTime();
516 + var len = netdata.services.length;
517 + while(len--) {
518 + var service = netdata.services[len];
519 +
520 + if(service.enabled === false || service.running === true) continue;
521 + if(now <= service.next_run) continue;
522 +
523 + service.update();
524 +
525 + now = new Date().getTime();
526 + while(service.next_run < now)
527 + service.next_run += (service.update_every * 1000);
528 + }
529 +
530 + // 1/10th of update_every in pause
531 + setTimeout(netdata.runAllServices, netdata.options.update_every * 100);
532 + },
533 +
534 + start: function() {
535 + if(netdata.options.DEBUG === true) this.debug('started, services: ' + netdata.stringify(this.services));
536 +
537 + if(this.services.length === 0) {
538 + this.disableNodePlugin();
539 + process.exit(1);
540 + }
541 + else this.runAllServices();
542 + },
543 +
544 + // disable the whole node.js plugin
545 + disableNodePlugin: function() {
546 + this.send('DISABLE');
547 + process.exit(1);
548 + },
549 +
550 + requestFromParams: function(protocol, hostname, port, path, method) {
551 + return {
552 + protocol: protocol,
553 + hostname: hostname,
554 + port: port,
555 + path: path,
556 + //family: 4,
557 + method: method,
558 + headers: {
559 + 'Content-Type': 'application/x-www-form-urlencoded',
560 + 'Connection': 'keep-alive'
561 + },
562 + agent: new http.Agent({
563 + keepAlive: true,
564 + keepAliveMsecs: netdata.options.update_every * 1000,
565 + maxSockets: 2, // it must be 2 to work
566 + maxFreeSockets: 1
567 + })
568 + };
569 + },
570 +
571 + requestFromURL: function(a_url) {
572 + var u = url.parse(a_url);
573 + return netdata.requestFromParams(u.protocol, u.hostname, u.port, u.path, 'GET');
574 + },
575 +
576 + configure: function(module, config, callback) {
577 + if(netdata.options.DEBUG === true) this.debug(module.name + ': configuring (update_every: ' + this.options.update_every + ')...');
578 +
579 + module.active = 0;
580 + module.update_every = this.options.update_every;
581 +
582 + if(typeof config.update_every !== 'undefined')
583 + module.update_every = config.update_every;
584 +
585 + module.enable_autodetect = (config.enable_autodetect)?true:false;
586 +
587 + if(typeof(callback) === 'function')
588 + module.configure_callback = callback;
589 + else
590 + module.configure_callback = null;
591 +
592 + var added = module.configure(config);
593 +
594 + if(netdata.options.DEBUG === true) this.debug(module.name + ': configured, reporting ' + added + ' eligible services.');
595 +
596 + if(module.configure_callback !== null && added === 0) {
597 + if(netdata.options.DEBUG === true) this.debug(module.name + ': configuration finish callback called from configure().');
598 + module.configure_callback = null;
599 + callback();
600 + }
601 +
602 + return added;
603 + }
604 +};
605 +
606 +if(netdata.options.DEBUG === true) netdata.debug('loaded netdata from: ' + __filename);
607 +module.exports = netdata;