]> arthur.barton.de Git - netdata.git/commitdiff
converted from dos to unix
authorCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Sat, 6 Feb 2016 05:10:33 +0000 (07:10 +0200)
committerCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Sat, 6 Feb 2016 05:10:33 +0000 (07:10 +0200)
node.d/node_modules/netdata.js

index 10f979b156c3e18bc681d996b7cd09410f1ea2fc..5fa7752185e39c9a8e13f7bc1f3889b2261b17b0 100755 (executable)
-'use strict';\r
-\r
-var url = require('url');\r
-var http = require('http');\r
-var util = require('util');\r
-\r
-/*\r
-var netdata = require('netdata');\r
-\r
-var example_chart = {\r
-       id: 'id',                                               // the unique id of the chart\r
-       name: 'name',                                   // the name of the chart\r
-       title: 'title',                                 // the title of the chart\r
-       units: 'units',                                 // the units of the chart dimensions\r
-       family: 'family',                               // the family of the chart\r
-       category: 'category',                   // the category of the chart\r
-       type: netdata.chartTypes.line,  // the type of the chart\r
-       priority: 0,                                    // the priority relative to others in the same family and category\r
-       update_every: 1,                                // the expected update frequency of the chart\r
-       dimensions: {\r
-               'dim1': {\r
-                       id: 'dim1',                             // the unique id of the dimension\r
-                       name: 'name',                   // the name of the dimension\r
-                       algorithm: netdata.chartAlgorithms.absolute,    // the id of the netdata algorithm\r
-                       multiplier: 1,                  // the multiplier\r
-                       divisor: 1,                             // the divisor\r
-                       hidden: false,                  // is hidden (boolean)\r
-               },\r
-               'dim2': {\r
-                       id: 'dim2',                             // the unique id of the dimension\r
-                       name: 'name',                   // the name of the dimension\r
-                       algorithm: 'absolute',  // the id of the netdata algorithm\r
-                       multiplier: 1,                  // the multiplier\r
-                       divisor: 1,                             // the divisor\r
-                       hidden: false,                  // is hidden (boolean)\r
-               }\r
-               // add as many dimensions as needed\r
-       }\r
-};\r
-*/\r
-\r
-var netdata = {\r
-       options: {\r
-               filename: __filename,\r
-               DEBUG: false,\r
-               update_every: 1,\r
-       },\r
-\r
-       chartAlgorithms: {\r
-               incremental: 'incremental',\r
-               absolute: 'absolute',\r
-               percentage_of_absolute_row: 'percentage-of-absolute-row',\r
-               percentage_of_incremental_row: 'percentage-of-incremental-row'\r
-       },\r
-\r
-       chartTypes: {\r
-               line: 'line',\r
-               area: 'area',\r
-               stacked: 'stacked'\r
-       },\r
-\r
-       services: new Array(),\r
-       modules_configuring: 0,\r
-       charts: {},\r
-\r
-\r
-       processors: {\r
-               http: {\r
-                       name: 'http',\r
-\r
-                       process: function(service, callback) {\r
-                               if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': making ' + this.name + ' request: ' + netdata.stringify(service.request));\r
-\r
-                               var req = http.request(service.request, function(response) {\r
-                                       if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': got server response...');\r
-\r
-                                       var end = false;\r
-                                       var data = '';\r
-                                       response.setEncoding('utf8');\r
-\r
-                                       if(response.statusCode !== 200) {\r
-                                               if(end === false) {\r
-                                                       service.error('Got HTTP code ' + response.statusCode + ', failed to get data.');\r
-                                                       end = true;\r
-                                                       callback(null);\r
-                                               }\r
-                                       }\r
-\r
-                                       response.on('data', function(chunk) {\r
-                                               if(end === false) data += chunk;\r
-                                       });\r
-\r
-                                       response.on('error', function() {\r
-                                               if(end === false) {\r
-                                                       service.error(': Read error, failed to get data.');\r
-                                                       end = true;\r
-                                                       callback(null);\r
-                                               }\r
-                                       });\r
-\r
-                                       response.on('end', function() {\r
-                                               if(end === false) {\r
-                                                       if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': read completed.');\r
-                                                       end = true;\r
-                                                       callback(data);\r
-                                               }\r
-                                       });\r
-                               });\r
-\r
-                               req.on('error', function(e) {\r
-                                       service.error('Failed to make request: ' + netdata.stringify(service.request) + ', message: ' + e.message);\r
-                                       callback(null);\r
-                               });\r
-\r
-                               // write data to request body\r
-                               if(typeof service.postData !== 'undefined' && service.request.method === 'POST') {\r
-                                       if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': posting data: ' + service.postData);\r
-                                       req.write(service.postData);\r
-                               }\r
-\r
-                               req.end();\r
-                       }\r
-               }\r
-       },\r
-\r
-       stringify: function(obj) {\r
-               return util.inspect(obj, {depth: 10});\r
-       },\r
-\r
-       // show debug info, if debug is enabled\r
-       debug: function(msg) {\r
-               if(this.options.DEBUG === true) {\r
-                       var now = new Date();\r
-                       console.error(now.toString() + ': ' + netdata.options.filename + ': DEBUG: ' + ((typeof(msg) === 'object')?netdata.stringify(msg):msg).toString());\r
-               }\r
-       },\r
-\r
-       // log an error\r
-       error: function(msg) {\r
-               var now = new Date();\r
-               console.error(now.toString() + ': ' + netdata.options.filename + ': ERROR: ' + ((typeof(msg) === 'object')?netdata.stringify(msg):msg).toString());\r
-       },\r
-\r
-       // send data to netdata\r
-       send: function(msg) {\r
-               console.log(msg.toString());\r
-       },\r
-\r
-       service: function(service) {\r
-               if(typeof service === 'undefined')\r
-                       service = {};\r
-\r
-               service._current_chart = null;  // the current chart we work on\r
-               service._queue = '';                    // data to be sent to netdata\r
-\r
-               service.error_reported = false; // error log flood control\r
-\r
-               service.added = false;                  // added to netdata.services\r
-               service.enabled = true;\r
-               service.updates = 0;\r
-               service.running = false;\r
-               service.started = 0;\r
-               service.ended = 0;\r
-               service.next_run = new Date().getTime();\r
-\r
-               if(typeof service.update_every === 'undefined')\r
-                       service.update_every = service.module.update_every;\r
-\r
-               if(typeof service.update_every === 'undefined')\r
-                       service.update_every = netdata.options.update_every;\r
-\r
-               if(typeof service.processor === 'undefined')\r
-                       service.processor = netdata.processors.http;\r
-\r
-               if(service.update_every < netdata.options.update_every)\r
-                       service.update_every = netdata.options.update_every;\r
-\r
-               service.commit = function() {\r
-                       if(this.added !== true) {\r
-                               this.added = true;\r
-                               \r
-                               var now = new Date().getTime();\r
-                               while( this.next_run < now )\r
-                                       this.next_run += (this.update_every * 1000);\r
-\r
-                               netdata.services.push(this);\r
-                               if(netdata.options.DEBUG === true) netdata.debug(this.module.name + ': ' + this.name + ': service committed.');\r
-                       }\r
-               };\r
-\r
-               service.execute = function(callback) {\r
-                       this.module.active++;\r
-                       this.running = true;\r
-                       this.started = new Date().getTime();\r
-                       this.updates++;\r
-\r
-                       if(netdata.options.DEBUG === true)\r
-                               netdata.debug(this.module.name + ': ' + this.name + ': making ' + this.processor.name + ' request: ' + netdata.stringify(this));\r
-\r
-                       this.processor.process(this, function(response) {\r
-                               service.ended = new Date().getTime();\r
-                               service.duration = service.ended - service.started;\r
-\r
-                               if(typeof response === 'undefined')\r
-                                       response = null;\r
-\r
-                               if(response !== null)\r
-                                       service.errorClear();\r
-\r
-                               if(netdata.options.DEBUG === true)\r
-                                       netdata.debug(service.module.name + ': ' + service.name + ': processing ' + service.processor.name + ' response (received in ' + (service.ended - service.started).toString() + ' ms)');\r
-\r
-                               callback(service, response);\r
-\r
-                               service.running = false;\r
-                               service.module.active--;\r
-                               if(service.module.active < 0) {\r
-                                       service.module.active = 0;\r
-                                       if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': active module counter below zero.');\r
-                               }\r
-\r
-                               if(service.module.active === 0) {\r
-                                       // check if we run under configure\r
-                                       if(service.module.configure_callback !== null) {\r
-                                               if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': configuration finish callback called from processResponse().');\r
-                                               var ccallback = service.module.configure_callback;\r
-                                               service.module.configure_callback = null;\r
-                                               ccallback();\r
-                                       }\r
-                               }\r
-                       });\r
-               };\r
-\r
-               service.update = function() {\r
-                       if(netdata.options.DEBUG === true) netdata.debug(this.module.name + ': ' + this.name + ': starting data collection...');\r
-\r
-                       this.module.update(this, function() {\r
-                               if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': data collection ended in ' + service.duration.toString() + ' ms.');\r
-                       });\r
-               };\r
-\r
-               service.error = function(message) {\r
-                       if(this.error_reported === false) {\r
-                               netdata.error(this.module.name + ': ' + this.name + ': ' + message);\r
-                               this.error_reported = true;\r
-                       }\r
-                       else if(netdata.options.DEBUG === true)\r
-                               netdata.debug(this.module.name + ': ' + this.name + ': ' + message);\r
-               };\r
-\r
-               service.errorClear = function() {\r
-                       this.error_reported = false;\r
-               };\r
-\r
-               service.queue = function(txt) {\r
-                       this._queue += txt + '\n';\r
-               };\r
-\r
-               service._send_chart_to_netdata = function(chart) {\r
-                       // internal function to send a chart to netdata\r
-                       this.queue('CHART "' + chart.id + '" "' + chart.name + '" "' + chart.title + '" "' + chart.units + '" "' + chart.family + '" "' + chart.category + '" "' + chart.type + '" ' + chart.priority.toString() + ' ' + chart.update_every.toString());\r
-                       \r
-                       for(var dim in chart.dimensions) {\r
-                               var d = chart.dimensions[dim];\r
-\r
-                               this.queue('DIMENSION "' + d.id + '" "' + d.name + '" "' + d.algorithm + '" ' + d.multiplier.toString() + ' ' + d.divisor.toString() + ' ' + ((d.hidden === true)?'hidden':'').toString());\r
-                               d._created = true;\r
-                               d._updated = false;\r
-                       }\r
-\r
-                       chart._created = true;\r
-                       chart._updated = false;\r
-               };\r
-\r
-               // begin data collection for a chart\r
-               service.begin = function(chart) {\r
-                       if(this._current_chart !== null && this._current_chart !== chart) {\r
-                               this.error('Called begin() for chart ' + chart.id + ' while chart ' + this._current_chart.id + ' is still open. Closing it.');\r
-                               this.end();\r
-                       }\r
-\r
-                       if(typeof(chart.id) === 'undefined' || netdata.charts[chart.id] != chart) {\r
-                               this.error('Called begin() for chart ' + chart.id + ' that is not mine. Where did you find it? Ignoring it.');\r
-                               return false;\r
-                       }\r
-\r
-                       if(netdata.options.DEBUG === true) netdata.debug('setting current chart to ' + chart.id);\r
-                       this._current_chart = chart;\r
-                       this._current_chart._began = true;\r
-\r
-                       if(this._current_chart._dimensions_count !== 0) {\r
-                               if(this._current_chart._created === false || this._current_chart._updated === true)\r
-                                       this._send_chart_to_netdata(this._current_chart);\r
-\r
-                               var now = this.ended;\r
-                               this.queue('BEGIN ' + this._current_chart.id + ' ' + ((this._current_chart._last_updated > 0)?((now - this._current_chart._last_updated) * 1000):'').toString());\r
-                       }\r
-                       // else this.error('Called begin() for chart ' + chart.id + ' which is empty.');\r
-\r
-                       this._current_chart._last_updated = now;\r
-                       this._current_chart._began = true;\r
-                       this._current_chart._counter++;\r
-\r
-                       return true;\r
-               };\r
-\r
-               // set a collected value for a chart\r
-               // we do most things on the first value we attempt to set\r
-               service.set = function(dimension, value) {\r
-                       if(this._current_chart === null) {\r
-                               this.error('Called set(' + dimension + ', ' + value + ') without an open chart.');\r
-                               return false;\r
-                       }\r
-\r
-                       if(typeof(this._current_chart.dimensions[dimension]) === 'undefined') {\r
-                               this.error('Called set(' + dimension + ', ' + value + ') but dimension "' + dimension + '" does not exist in chart "' + this._current_chart.id + '".');\r
-                               return false;\r
-                       }\r
-\r
-                       if(typeof value === 'undefined' || value === null)\r
-                               return false;\r
-\r
-                       if(this._current_chart._dimensions_count !== 0)\r
-                               this.queue('SET ' + dimension + ' = ' + value);\r
-\r
-                       return true;\r
-               };\r
-\r
-               // end data collection for the current chart - after calling begin()\r
-               service.end = function() {\r
-                       if(this._current_chart !== null && this._current_chart._began === false) {\r
-                               this.error('Called end() without an open chart.');\r
-                               return false;\r
-                       }\r
-\r
-                       if(this._current_chart._dimensions_count !== 0) {\r
-                               this.queue('END');\r
-                               netdata.send(this._queue);\r
-                       }\r
-\r
-                       this._queue = '';\r
-                       this._current_chart._began = false;\r
-                       if(netdata.options.DEBUG === true) netdata.debug('sent chart ' + this._current_chart.id);\r
-                       this._current_chart = null;\r
-                       return true;\r
-               };\r
-\r
-               // discard the collected values for the current chart - after calling begin()\r
-               service.flush = function() {\r
-                       if(this._current_chart === null || this._current_chart._began === false) {\r
-                               this.error('Called flush() without an open chart.');\r
-                               return false;\r
-                       }\r
-\r
-                       this._queue = '';\r
-                       this._current_chart._began = false;\r
-                       this._current_chart = null;\r
-                       return true;\r
-               };\r
-\r
-               // create a netdata chart\r
-               service.chart = function(id, chart) {\r
-                       if(typeof(netdata.charts[id]) === 'undefined') {\r
-                               netdata.charts[id] = {\r
-                                       _created: false,\r
-                                       _updated: true,\r
-                                       _began: false,\r
-                                       _counter: 0,\r
-                                       _last_updated: 0,\r
-                                       _dimensions_count: 0,\r
-                                       id: id,\r
-                                       name: id,\r
-                                       title: 'untitled chart',\r
-                                       units: 'a unit',\r
-                                       family: '',\r
-                                       category: '',\r
-                                       type: netdata.chartTypes.line,\r
-                                       priority: 0,\r
-                                       update_every: netdata.options.update_every,\r
-                                       dimensions: {}\r
-                               };\r
-                       }\r
-\r
-                       var c = netdata.charts[id];\r
-\r
-                       if(typeof(chart.name) !== 'undefined' && chart.name !== c.name) {\r
-                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its name');\r
-                               c.name = chart.name;\r
-                               c._updated = true;\r
-                       }\r
-\r
-                       if(typeof(chart.title) !== 'undefined' && chart.title !== c.title) {\r
-                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its title');\r
-                               c.title = chart.title;\r
-                               c._updated = true;\r
-                       }\r
-\r
-                       if(typeof(chart.units) !== 'undefined' && chart.units !== c.units) {\r
-                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its units');\r
-                               c.units = chart.units;\r
-                               c._updated = true;\r
-                       }\r
-\r
-                       if(typeof(chart.family) !== 'undefined' && chart.family !== c.family) {\r
-                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its family');\r
-                               c.family = chart.family;\r
-                               c._updated = true;\r
-                       }\r
-\r
-                       if(typeof(chart.category) !== 'undefined' && chart.category !== c.category) {\r
-                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its category');\r
-                               c.category = chart.category;\r
-                               c._updated = true;\r
-                       }\r
-\r
-                       if(typeof(chart.type) !== 'undefined' && chart.type !== c.type) {\r
-                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its type');\r
-                               c.type = chart.type;\r
-                               c._updated = true;\r
-                       }\r
-\r
-                       if(typeof(chart.priority) !== 'undefined' && chart.priority !== c.priority) {\r
-                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its priority');\r
-                               c.priority = chart.priority;\r
-                               c._updated = true;\r
-                       }\r
-\r
-                       if(typeof(chart.update_every) !== 'undefined' && chart.update_every !== c.update_every) {\r
-                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its update_every from ' + c.update_every + ' to ' + chart.update_every);\r
-                               c.update_every = chart.update_every;\r
-                               c._updated = true;\r
-                       }\r
-\r
-                       if(typeof(chart.dimensions) !== 'undefined') {\r
-                               for(var x in chart.dimensions) {\r
-                                       if(typeof(c.dimensions[x]) === 'undefined') {\r
-                                               c._dimensions_count++;\r
-\r
-                                               c.dimensions[x] = {\r
-                                                       _created: false,\r
-                                                       _updated: false,\r
-                                                       id: x,                                  // the unique id of the dimension\r
-                                                       name: x,                                // the name of the dimension\r
-                                                       algorithm: netdata.chartAlgorithms.absolute,    // the id of the netdata algorithm\r
-                                                       multiplier: 1,                  // the multiplier\r
-                                                       divisor: 1,                             // the divisor\r
-                                                       hidden: false,                  // is hidden (boolean)\r
-                                               };\r
-\r
-                                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' created dimension ' + x);\r
-                                               c._updated = true;\r
-                                       }\r
-\r
-                                       var dim = chart.dimensions[x];\r
-                                       var d = c.dimensions[x];\r
-\r
-                                       if(typeof(dim.name) !== 'undefined' && d.name !== dim.name) {\r
-                                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ', dimension ' + x + ' updated its name');\r
-                                               d.name = dim.name;\r
-                                               d._updated = true;\r
-                                       }\r
-\r
-                                       if(typeof(dim.algorithm) !== 'undefined' && d.algorithm !== dim.algorithm) {\r
-                                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ', dimension ' + x + ' updated its algorithm from ' + d.algorithm + ' to ' + dim.algorithm);\r
-                                               d.algorithm = dim.algorithm;\r
-                                               d._updated = true;\r
-                                       }\r
-\r
-                                       if(typeof(dim.multiplier) !== 'undefined' && d.multiplier !== dim.multiplier) {\r
-                                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ', dimension ' + x + ' updated its multiplier');\r
-                                               d.multiplier = dim.multiplier;\r
-                                               d._updated = true;\r
-                                       }\r
-\r
-                                       if(typeof(dim.divisor) !== 'undefined' && d.divisor !== dim.divisor) {\r
-                                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ', dimension ' + x + ' updated its divisor');\r
-                                               d.divisor = dim.divisor;\r
-                                               d._updated = true;\r
-                                       }\r
-\r
-                                       if(typeof(dim.hidden) !== 'undefined' && d.hidden !== dim.hidden) {\r
-                                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ', dimension ' + x + ' updated its hidden status');\r
-                                               d.hidden = dim.hidden;\r
-                                               d._updated = true;\r
-                                       }\r
-\r
-                                       if(d._updated) c._updated = true;\r
-                               }\r
-                       }\r
-\r
-                       //if(netdata.options.DEBUG === true) netdata.debug(netdata.charts);\r
-                       return netdata.charts[id];\r
-               };\r
-\r
-               return service;\r
-       },\r
-\r
-       runAllServices: function() {\r
-               if(netdata.options.DEBUG === true) netdata.debug('runAllServices()');\r
-\r
-               var now = new Date().getTime();\r
-               var len = netdata.services.length;\r
-               while(len--) {\r
-                       var service = netdata.services[len];\r
-\r
-                       if(service.enabled === false || service.running === true) continue;\r
-                       if(now <= service.next_run) continue;\r
-\r
-                       service.update();\r
-\r
-                       now = new Date().getTime();\r
-                       while(service.next_run < now)\r
-                               service.next_run += (service.update_every * 1000);\r
-               }\r
-\r
-               // 1/10th of update_every in pause\r
-               setTimeout(netdata.runAllServices, netdata.options.update_every * 100);\r
-       },\r
-\r
-       start: function() {\r
-               if(netdata.options.DEBUG === true) this.debug('started, services: ' + netdata.stringify(this.services));\r
-\r
-               if(this.services.length === 0) {\r
-                       this.disableNodePlugin();\r
-                       process.exit(1);\r
-               }\r
-               else this.runAllServices();\r
-       },\r
-\r
-       // disable the whole node.js plugin\r
-       disableNodePlugin: function() {\r
-               this.send('DISABLE');\r
-               process.exit(1);\r
-       },\r
-\r
-       requestFromParams: function(protocol, hostname, port, path, method) {\r
-               return {\r
-                       protocol: protocol,\r
-                       hostname: hostname,\r
-                       port: port,\r
-                       path: path,\r
-                       //family: 4,\r
-                       method: method,\r
-                       headers: {\r
-                               'Content-Type': 'application/x-www-form-urlencoded',\r
-                               'Connection': 'keep-alive'\r
-                       },\r
-                       agent: new http.Agent({\r
-                               keepAlive: true,\r
-                               keepAliveMsecs: netdata.options.update_every * 1000,\r
-                               maxSockets: 2, // it must be 2 to work\r
-                               maxFreeSockets: 1\r
-                       })\r
-               };\r
-       },\r
-\r
-       requestFromURL: function(a_url) {\r
-               var u = url.parse(a_url);\r
-               return netdata.requestFromParams(u.protocol, u.hostname, u.port, u.path, 'GET');\r
-       },\r
-\r
-       configure: function(module, config, callback) {\r
-               if(netdata.options.DEBUG === true) this.debug(module.name + ': configuring (update_every: ' + this.options.update_every + ')...');\r
-\r
-               module.active = 0;\r
-               module.update_every = this.options.update_every;\r
-\r
-               if(typeof config.update_every !== 'undefined')\r
-                       module.update_every = config.update_every;\r
-\r
-               module.enable_autodetect = (config.enable_autodetect)?true:false;\r
-\r
-               if(typeof(callback) === 'function')\r
-                       module.configure_callback = callback;\r
-               else\r
-                       module.configure_callback = null;\r
-\r
-               var added = module.configure(config);\r
-\r
-               if(netdata.options.DEBUG === true) this.debug(module.name + ': configured, reporting ' + added + ' eligible services.');\r
-\r
-               if(module.configure_callback !== null && added === 0) {\r
-                       if(netdata.options.DEBUG === true) this.debug(module.name + ': configuration finish callback called from configure().');\r
-                       module.configure_callback = null;\r
-                       callback();\r
-               }\r
-\r
-               return added;\r
-       }\r
-};\r
-\r
-if(netdata.options.DEBUG === true) netdata.debug('loaded netdata from: ' + __filename);\r
-module.exports = netdata;\r
+'use strict';
+
+var url = require('url');
+var http = require('http');
+var util = require('util');
+
+/*
+var netdata = require('netdata');
+
+var example_chart = {
+       id: 'id',                                               // the unique id of the chart
+       name: 'name',                                   // the name of the chart
+       title: 'title',                                 // the title of the chart
+       units: 'units',                                 // the units of the chart dimensions
+       family: 'family',                               // the family of the chart
+       category: 'category',                   // the category of the chart
+       type: netdata.chartTypes.line,  // the type of the chart
+       priority: 0,                                    // the priority relative to others in the same family and category
+       update_every: 1,                                // the expected update frequency of the chart
+       dimensions: {
+               'dim1': {
+                       id: 'dim1',                             // the unique id of the dimension
+                       name: 'name',                   // the name of the dimension
+                       algorithm: netdata.chartAlgorithms.absolute,    // the id of the netdata algorithm
+                       multiplier: 1,                  // the multiplier
+                       divisor: 1,                             // the divisor
+                       hidden: false,                  // is hidden (boolean)
+               },
+               'dim2': {
+                       id: 'dim2',                             // the unique id of the dimension
+                       name: 'name',                   // the name of the dimension
+                       algorithm: 'absolute',  // the id of the netdata algorithm
+                       multiplier: 1,                  // the multiplier
+                       divisor: 1,                             // the divisor
+                       hidden: false,                  // is hidden (boolean)
+               }
+               // add as many dimensions as needed
+       }
+};
+*/
+
+var netdata = {
+       options: {
+               filename: __filename,
+               DEBUG: false,
+               update_every: 1,
+       },
+
+       chartAlgorithms: {
+               incremental: 'incremental',
+               absolute: 'absolute',
+               percentage_of_absolute_row: 'percentage-of-absolute-row',
+               percentage_of_incremental_row: 'percentage-of-incremental-row'
+       },
+
+       chartTypes: {
+               line: 'line',
+               area: 'area',
+               stacked: 'stacked'
+       },
+
+       services: new Array(),
+       modules_configuring: 0,
+       charts: {},
+
+
+       processors: {
+               http: {
+                       name: 'http',
+
+                       process: function(service, callback) {
+                               if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': making ' + this.name + ' request: ' + netdata.stringify(service.request));
+
+                               var req = http.request(service.request, function(response) {
+                                       if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': got server response...');
+
+                                       var end = false;
+                                       var data = '';
+                                       response.setEncoding('utf8');
+
+                                       if(response.statusCode !== 200) {
+                                               if(end === false) {
+                                                       service.error('Got HTTP code ' + response.statusCode + ', failed to get data.');
+                                                       end = true;
+                                                       callback(null);
+                                               }
+                                       }
+
+                                       response.on('data', function(chunk) {
+                                               if(end === false) data += chunk;
+                                       });
+
+                                       response.on('error', function() {
+                                               if(end === false) {
+                                                       service.error(': Read error, failed to get data.');
+                                                       end = true;
+                                                       callback(null);
+                                               }
+                                       });
+
+                                       response.on('end', function() {
+                                               if(end === false) {
+                                                       if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': read completed.');
+                                                       end = true;
+                                                       callback(data);
+                                               }
+                                       });
+                               });
+
+                               req.on('error', function(e) {
+                                       service.error('Failed to make request: ' + netdata.stringify(service.request) + ', message: ' + e.message);
+                                       callback(null);
+                               });
+
+                               // write data to request body
+                               if(typeof service.postData !== 'undefined' && service.request.method === 'POST') {
+                                       if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': posting data: ' + service.postData);
+                                       req.write(service.postData);
+                               }
+
+                               req.end();
+                       }
+               }
+       },
+
+       stringify: function(obj) {
+               return util.inspect(obj, {depth: 10});
+       },
+
+       // show debug info, if debug is enabled
+       debug: function(msg) {
+               if(this.options.DEBUG === true) {
+                       var now = new Date();
+                       console.error(now.toString() + ': ' + netdata.options.filename + ': DEBUG: ' + ((typeof(msg) === 'object')?netdata.stringify(msg):msg).toString());
+               }
+       },
+
+       // log an error
+       error: function(msg) {
+               var now = new Date();
+               console.error(now.toString() + ': ' + netdata.options.filename + ': ERROR: ' + ((typeof(msg) === 'object')?netdata.stringify(msg):msg).toString());
+       },
+
+       // send data to netdata
+       send: function(msg) {
+               console.log(msg.toString());
+       },
+
+       service: function(service) {
+               if(typeof service === 'undefined')
+                       service = {};
+
+               service._current_chart = null;  // the current chart we work on
+               service._queue = '';                    // data to be sent to netdata
+
+               service.error_reported = false; // error log flood control
+
+               service.added = false;                  // added to netdata.services
+               service.enabled = true;
+               service.updates = 0;
+               service.running = false;
+               service.started = 0;
+               service.ended = 0;
+               service.next_run = new Date().getTime();
+
+               if(typeof service.module === 'undefined') {
+                       service.module = { name: 'not-defined-module' };
+                       service.error('Attempted to create service without a module.');
+                       service.enabled = false;
+               }
+
+               if(typeof service.name === 'undefined')
+                       service.name = 'unnamed@' + service.module.name + '/' + service.next_run;
+
+               if(typeof service.update_every === 'undefined')
+                       service.update_every = service.module.update_every;
+
+               if(typeof service.update_every === 'undefined')
+                       service.update_every = netdata.options.update_every;
+
+               if(typeof service.processor === 'undefined')
+                       service.processor = netdata.processors.http;
+
+               if(service.update_every < netdata.options.update_every)
+                       service.update_every = netdata.options.update_every;
+
+               service.commit = function() {
+                       if(this.added !== true) {
+                               this.added = true;
+                               
+                               var now = new Date().getTime();
+                               while( this.next_run < now )
+                                       this.next_run += (this.update_every * 1000);
+
+                               netdata.services.push(this);
+                               if(netdata.options.DEBUG === true) netdata.debug(this.module.name + ': ' + this.name + ': service committed.');
+                       }
+               };
+
+               service.execute = function(callback) {
+                       if(service.enabled === false) {
+                               callback(null);
+                               return;
+                       }
+
+                       this.module.active++;
+                       this.running = true;
+                       this.started = new Date().getTime();
+                       this.updates++;
+
+                       if(netdata.options.DEBUG === true)
+                               netdata.debug(this.module.name + ': ' + this.name + ': making ' + this.processor.name + ' request: ' + netdata.stringify(this));
+
+                       this.processor.process(this, function(response) {
+                               service.ended = new Date().getTime();
+                               service.duration = service.ended - service.started;
+
+                               if(typeof response === 'undefined')
+                                       response = null;
+
+                               if(response !== null)
+                                       service.errorClear();
+
+                               if(netdata.options.DEBUG === true)
+                                       netdata.debug(service.module.name + ': ' + service.name + ': processing ' + service.processor.name + ' response (received in ' + (service.ended - service.started).toString() + ' ms)');
+
+                               callback(service, response);
+
+                               service.running = false;
+                               service.module.active--;
+                               if(service.module.active < 0) {
+                                       service.module.active = 0;
+                                       if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': active module counter below zero.');
+                               }
+
+                               if(service.module.active === 0) {
+                                       // check if we run under configure
+                                       if(service.module.configure_callback !== null) {
+                                               if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': configuration finish callback called from processResponse().');
+                                               var ccallback = service.module.configure_callback;
+                                               service.module.configure_callback = null;
+                                               ccallback();
+                                       }
+                               }
+                       });
+               };
+
+               service.update = function() {
+                       if(netdata.options.DEBUG === true) netdata.debug(this.module.name + ': ' + this.name + ': starting data collection...');
+
+                       this.module.update(this, function() {
+                               if(netdata.options.DEBUG === true) netdata.debug(service.module.name + ': ' + service.name + ': data collection ended in ' + service.duration.toString() + ' ms.');
+                       });
+               };
+
+               service.error = function(message) {
+                       if(this.error_reported === false) {
+                               netdata.error(this.module.name + ': ' + this.name + ': ' + message);
+                               this.error_reported = true;
+                       }
+                       else if(netdata.options.DEBUG === true)
+                               netdata.debug(this.module.name + ': ' + this.name + ': ' + message);
+               };
+
+               service.errorClear = function() {
+                       this.error_reported = false;
+               };
+
+               service.queue = function(txt) {
+                       this._queue += txt + '\n';
+               };
+
+               service._send_chart_to_netdata = function(chart) {
+                       // internal function to send a chart to netdata
+                       this.queue('CHART "' + chart.id + '" "' + chart.name + '" "' + chart.title + '" "' + chart.units + '" "' + chart.family + '" "' + chart.category + '" "' + chart.type + '" ' + chart.priority.toString() + ' ' + chart.update_every.toString());
+                       
+                       for(var dim in chart.dimensions) {
+                               var d = chart.dimensions[dim];
+
+                               this.queue('DIMENSION "' + d.id + '" "' + d.name + '" "' + d.algorithm + '" ' + d.multiplier.toString() + ' ' + d.divisor.toString() + ' ' + ((d.hidden === true)?'hidden':'').toString());
+                               d._created = true;
+                               d._updated = false;
+                       }
+
+                       chart._created = true;
+                       chart._updated = false;
+               };
+
+               // begin data collection for a chart
+               service.begin = function(chart) {
+                       if(this._current_chart !== null && this._current_chart !== chart) {
+                               this.error('Called begin() for chart ' + chart.id + ' while chart ' + this._current_chart.id + ' is still open. Closing it.');
+                               this.end();
+                       }
+
+                       if(typeof(chart.id) === 'undefined' || netdata.charts[chart.id] != chart) {
+                               this.error('Called begin() for chart ' + chart.id + ' that is not mine. Where did you find it? Ignoring it.');
+                               return false;
+                       }
+
+                       if(netdata.options.DEBUG === true) netdata.debug('setting current chart to ' + chart.id);
+                       this._current_chart = chart;
+                       this._current_chart._began = true;
+
+                       if(this._current_chart._dimensions_count !== 0) {
+                               if(this._current_chart._created === false || this._current_chart._updated === true)
+                                       this._send_chart_to_netdata(this._current_chart);
+
+                               var now = this.ended;
+                               this.queue('BEGIN ' + this._current_chart.id + ' ' + ((this._current_chart._last_updated > 0)?((now - this._current_chart._last_updated) * 1000):'').toString());
+                       }
+                       // else this.error('Called begin() for chart ' + chart.id + ' which is empty.');
+
+                       this._current_chart._last_updated = now;
+                       this._current_chart._began = true;
+                       this._current_chart._counter++;
+
+                       return true;
+               };
+
+               // set a collected value for a chart
+               // we do most things on the first value we attempt to set
+               service.set = function(dimension, value) {
+                       if(this._current_chart === null) {
+                               this.error('Called set(' + dimension + ', ' + value + ') without an open chart.');
+                               return false;
+                       }
+
+                       if(typeof(this._current_chart.dimensions[dimension]) === 'undefined') {
+                               this.error('Called set(' + dimension + ', ' + value + ') but dimension "' + dimension + '" does not exist in chart "' + this._current_chart.id + '".');
+                               return false;
+                       }
+
+                       if(typeof value === 'undefined' || value === null)
+                               return false;
+
+                       if(this._current_chart._dimensions_count !== 0)
+                               this.queue('SET ' + dimension + ' = ' + value);
+
+                       return true;
+               };
+
+               // end data collection for the current chart - after calling begin()
+               service.end = function() {
+                       if(this._current_chart !== null && this._current_chart._began === false) {
+                               this.error('Called end() without an open chart.');
+                               return false;
+                       }
+
+                       if(this._current_chart._dimensions_count !== 0) {
+                               this.queue('END');
+                               netdata.send(this._queue);
+                       }
+
+                       this._queue = '';
+                       this._current_chart._began = false;
+                       if(netdata.options.DEBUG === true) netdata.debug('sent chart ' + this._current_chart.id);
+                       this._current_chart = null;
+                       return true;
+               };
+
+               // discard the collected values for the current chart - after calling begin()
+               service.flush = function() {
+                       if(this._current_chart === null || this._current_chart._began === false) {
+                               this.error('Called flush() without an open chart.');
+                               return false;
+                       }
+
+                       this._queue = '';
+                       this._current_chart._began = false;
+                       this._current_chart = null;
+                       return true;
+               };
+
+               // create a netdata chart
+               service.chart = function(id, chart) {
+                       if(typeof(netdata.charts[id]) === 'undefined') {
+                               netdata.charts[id] = {
+                                       _created: false,
+                                       _updated: true,
+                                       _began: false,
+                                       _counter: 0,
+                                       _last_updated: 0,
+                                       _dimensions_count: 0,
+                                       id: id,
+                                       name: id,
+                                       title: 'untitled chart',
+                                       units: 'a unit',
+                                       family: '',
+                                       category: '',
+                                       type: netdata.chartTypes.line,
+                                       priority: 0,
+                                       update_every: netdata.options.update_every,
+                                       dimensions: {}
+                               };
+                       }
+
+                       var c = netdata.charts[id];
+
+                       if(typeof(chart.name) !== 'undefined' && chart.name !== c.name) {
+                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its name');
+                               c.name = chart.name;
+                               c._updated = true;
+                       }
+
+                       if(typeof(chart.title) !== 'undefined' && chart.title !== c.title) {
+                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its title');
+                               c.title = chart.title;
+                               c._updated = true;
+                       }
+
+                       if(typeof(chart.units) !== 'undefined' && chart.units !== c.units) {
+                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its units');
+                               c.units = chart.units;
+                               c._updated = true;
+                       }
+
+                       if(typeof(chart.family) !== 'undefined' && chart.family !== c.family) {
+                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its family');
+                               c.family = chart.family;
+                               c._updated = true;
+                       }
+
+                       if(typeof(chart.category) !== 'undefined' && chart.category !== c.category) {
+                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its category');
+                               c.category = chart.category;
+                               c._updated = true;
+                       }
+
+                       if(typeof(chart.type) !== 'undefined' && chart.type !== c.type) {
+                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its type');
+                               c.type = chart.type;
+                               c._updated = true;
+                       }
+
+                       if(typeof(chart.priority) !== 'undefined' && chart.priority !== c.priority) {
+                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its priority');
+                               c.priority = chart.priority;
+                               c._updated = true;
+                       }
+
+                       if(typeof(chart.update_every) !== 'undefined' && chart.update_every !== c.update_every) {
+                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' updated its update_every from ' + c.update_every + ' to ' + chart.update_every);
+                               c.update_every = chart.update_every;
+                               c._updated = true;
+                       }
+
+                       if(typeof(chart.dimensions) !== 'undefined') {
+                               for(var x in chart.dimensions) {
+                                       if(typeof(c.dimensions[x]) === 'undefined') {
+                                               c._dimensions_count++;
+
+                                               c.dimensions[x] = {
+                                                       _created: false,
+                                                       _updated: false,
+                                                       id: x,                                  // the unique id of the dimension
+                                                       name: x,                                // the name of the dimension
+                                                       algorithm: netdata.chartAlgorithms.absolute,    // the id of the netdata algorithm
+                                                       multiplier: 1,                  // the multiplier
+                                                       divisor: 1,                             // the divisor
+                                                       hidden: false,                  // is hidden (boolean)
+                                               };
+
+                                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ' created dimension ' + x);
+                                               c._updated = true;
+                                       }
+
+                                       var dim = chart.dimensions[x];
+                                       var d = c.dimensions[x];
+
+                                       if(typeof(dim.name) !== 'undefined' && d.name !== dim.name) {
+                                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ', dimension ' + x + ' updated its name');
+                                               d.name = dim.name;
+                                               d._updated = true;
+                                       }
+
+                                       if(typeof(dim.algorithm) !== 'undefined' && d.algorithm !== dim.algorithm) {
+                                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ', dimension ' + x + ' updated its algorithm from ' + d.algorithm + ' to ' + dim.algorithm);
+                                               d.algorithm = dim.algorithm;
+                                               d._updated = true;
+                                       }
+
+                                       if(typeof(dim.multiplier) !== 'undefined' && d.multiplier !== dim.multiplier) {
+                                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ', dimension ' + x + ' updated its multiplier');
+                                               d.multiplier = dim.multiplier;
+                                               d._updated = true;
+                                       }
+
+                                       if(typeof(dim.divisor) !== 'undefined' && d.divisor !== dim.divisor) {
+                                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ', dimension ' + x + ' updated its divisor');
+                                               d.divisor = dim.divisor;
+                                               d._updated = true;
+                                       }
+
+                                       if(typeof(dim.hidden) !== 'undefined' && d.hidden !== dim.hidden) {
+                                               if(netdata.options.DEBUG === true) netdata.debug('chart ' + id + ', dimension ' + x + ' updated its hidden status');
+                                               d.hidden = dim.hidden;
+                                               d._updated = true;
+                                       }
+
+                                       if(d._updated) c._updated = true;
+                               }
+                       }
+
+                       //if(netdata.options.DEBUG === true) netdata.debug(netdata.charts);
+                       return netdata.charts[id];
+               };
+
+               return service;
+       },
+
+       runAllServices: function() {
+               if(netdata.options.DEBUG === true) netdata.debug('runAllServices()');
+
+               var now = new Date().getTime();
+               var len = netdata.services.length;
+               while(len--) {
+                       var service = netdata.services[len];
+
+                       if(service.enabled === false || service.running === true) continue;
+                       if(now <= service.next_run) continue;
+
+                       service.update();
+
+                       now = new Date().getTime();
+                       while(service.next_run < now)
+                               service.next_run += (service.update_every * 1000);
+               }
+
+               // 1/10th of update_every in pause
+               setTimeout(netdata.runAllServices, netdata.options.update_every * 100);
+       },
+
+       start: function() {
+               if(netdata.options.DEBUG === true) this.debug('started, services: ' + netdata.stringify(this.services));
+
+               if(this.services.length === 0) {
+                       this.disableNodePlugin();
+                       process.exit(1);
+               }
+               else this.runAllServices();
+       },
+
+       // disable the whole node.js plugin
+       disableNodePlugin: function() {
+               this.send('DISABLE');
+               process.exit(1);
+       },
+
+       requestFromParams: function(protocol, hostname, port, path, method) {
+               return {
+                       protocol: protocol,
+                       hostname: hostname,
+                       port: port,
+                       path: path,
+                       //family: 4,
+                       method: method,
+                       headers: {
+                               'Content-Type': 'application/x-www-form-urlencoded',
+                               'Connection': 'keep-alive'
+                       },
+                       agent: new http.Agent({
+                               keepAlive: true,
+                               keepAliveMsecs: netdata.options.update_every * 1000,
+                               maxSockets: 2, // it must be 2 to work
+                               maxFreeSockets: 1
+                       })
+               };
+       },
+
+       requestFromURL: function(a_url) {
+               var u = url.parse(a_url);
+               return netdata.requestFromParams(u.protocol, u.hostname, u.port, u.path, 'GET');
+       },
+
+       configure: function(module, config, callback) {
+               if(netdata.options.DEBUG === true) this.debug(module.name + ': configuring (update_every: ' + this.options.update_every + ')...');
+
+               module.active = 0;
+               module.update_every = this.options.update_every;
+
+               if(typeof config.update_every !== 'undefined')
+                       module.update_every = config.update_every;
+
+               module.enable_autodetect = (config.enable_autodetect)?true:false;
+
+               if(typeof(callback) === 'function')
+                       module.configure_callback = callback;
+               else
+                       module.configure_callback = null;
+
+               var added = module.configure(config);
+
+               if(netdata.options.DEBUG === true) this.debug(module.name + ': configured, reporting ' + added + ' eligible services.');
+
+               if(module.configure_callback !== null && added === 0) {
+                       if(netdata.options.DEBUG === true) this.debug(module.name + ': configuration finish callback called from configure().');
+                       module.configure_callback = null;
+                       callback();
+               }
+
+               return added;
+       }
+};
+
+if(netdata.options.DEBUG === true) netdata.debug('loaded netdata from: ' + __filename);
+module.exports = netdata;