From 8b316e60caf7f9d8b427ee851733c857ea2f6c9f Mon Sep 17 00:00:00 2001 From: meltingice Date: Tue, 31 Aug 2010 22:27:43 -0400 Subject: [PATCH] Initial code commit. Very basic functionality and proof-of-concept. --- LICENSE | 10 +++++ NodeMonitor_Node.js | 80 ++++++++++++++++++++++++++++++++++++++++ NodeMonitor_Server.js | 50 +++++++++++++++++++++++++ README.textile | 23 ++++++++++++ config/node_config.js | 8 ++++ config/server_config.js | 5 +++ plugins/system_uptime.js | 21 +++++++++++ 7 files changed, 197 insertions(+) create mode 100644 LICENSE create mode 100644 NodeMonitor_Node.js create mode 100644 NodeMonitor_Server.js create mode 100644 README.textile create mode 100644 config/node_config.js create mode 100644 config/server_config.js create mode 100644 plugins/system_uptime.js diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..263ca66 --- /dev/null +++ b/LICENSE @@ -0,0 +1,10 @@ +Copyright (c) 2010, Ryan LeFevre +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the name of Ryan LeFevre, nor MeltingIce, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/NodeMonitor_Node.js b/NodeMonitor_Node.js new file mode 100644 index 0000000..a6a5fb2 --- /dev/null +++ b/NodeMonitor_Node.js @@ -0,0 +1,80 @@ +/* + * NodeMonitor + * Copyright 2010 Ryan LeFevre - @meltingice + * + * Licensed under the New BSD License, more info in LICENSE file + * included with this software. + * + * Source code is hosted at http://github.com/meltingice/NodeMonitor + */ + +var fs = require('fs'), + net = require('net'); + +var MonitorNode = { + config: require('./config/node_config'), + plugins: {}, + server_conn: false, + last_send: true +}; + +MonitorNode.start = function() { + console.log("Starting NodeMonitor Node!"); + + this.load_plugins(); + this.server_connect(); +} + +MonitorNode.load_plugins = function() { + // Load plugins + var plugin_count = 0; + var pluginarr = fs.readdirSync('./plugins'); + pluginarr.forEach(function(plugin) { + plugin = plugin.split('.')[0]; + MonitorNode.plugins[plugin] = require('./plugins/'+plugin); + plugin_count++; + }); + + console.log(plugin_count + " plugins loaded."); +} + +MonitorNode.server_connect = function() { + this.server_conn = net.createConnection(this.config.server_port, this.config.server_addr); + this.server_conn.setKeepAlive(false); + this.server_conn.setNoDelay(true); + + this.server_conn.on('connect', function() { + console.log("Connected to NodeMonitor Server at " + MonitorNode.config.server_addr + ":" + MonitorNode.config.server_port); + MonitorNode.execute_plugins(); + }); + this.server_conn.on('error', function(exception) { + console.log('Error: ' + exception.message); + process.exit(1); + }); +} + +MonitorNode.execute_plugins = function() { + var interval = setInterval(function(){ + for(var plugin in MonitorNode.plugins) { + MonitorNode.plugins[plugin].poll(function(plugin_name, data) { + MonitorNode.send_data(plugin_name, data); + }); + } + }, 500); +} + +MonitorNode.send_data = function(plugin, msg) { + var data = JSON.stringify({'plugin':plugin, 'msg':msg, 'origin':this.config.node_name}); + + /* + * I really hate doing this, but sometimes multiple pieces of data + * get clumped together into a single packet, so I needed a simple way to + * signal the beginning and end of each JSON object. This allows the server to + * easily separate each object when parsing the incoming packets. Suggestions + * for improvement are welcome. + */ + this.last_send = this.server_conn.write("//START//"+data+"//END//", 'utf8'); +} + +// Start the node! +MonitorNode.start(); \ No newline at end of file diff --git a/NodeMonitor_Server.js b/NodeMonitor_Server.js new file mode 100644 index 0000000..bf4873b --- /dev/null +++ b/NodeMonitor_Server.js @@ -0,0 +1,50 @@ +/* + * NodeMonitor + * Copyright 2010 Ryan LeFevre - @meltingice + * + * Licensed under the New BSD License, more info in LICENSE file + * included with this software. + * + * Source code is hosted at http://github.com/meltingice/NodeMonitor + */ + +var net = require('net'); + +var MonitorServer = { + config: require('./config/server_config'), + server: false +}; + +MonitorServer.start = function() { + console.log('Starting NodeMonitor Server!'); + + this.start_node_listener(); +} + +MonitorServer.start_node_listener = function() { + this.server = net.createServer(function(stream) { + stream.setEncoding('utf8'); + stream.on('connect', function(t) { + console.log("Node connected!"); + }); + stream.on('data', function(data) { + var reqs = data.split(/\/\/START\/\/(.*?)\/\/END\/\//); + if(reqs.length > 0) { + reqs.forEach(function(req) { + if(req == ""){ return true; } + + console.log(JSON.parse(req)); + }); + } + }); + stream.on('end', function() { + console.log("Node disconnecting..."); + }); + }); + + this.server.listen(this.config.node_listen_port, this.config.node_listen_addr); + console.log("NodeMonitor Server now listening on " + this.config.node_listen_addr + ":" + this.config.node_listen_port); +} + +// Start the server! +MonitorServer.start(); \ No newline at end of file diff --git a/README.textile b/README.textile new file mode 100644 index 0000000..123bbe7 --- /dev/null +++ b/README.textile @@ -0,0 +1,23 @@ +

About

+NodeMonitor is a distributed server monitoring system written in Javascript for Node.JS. It uses WebSockets to stream the data to the browser in near-realtime, and it uses a simple plugin system to add various monitoring capabilities to each node. It is currently in a very alpha phase and a lot of functionality still needs to be added. This is my first time ever using Node.JS so I'm sure the code could use a lot of improvement. Anyone who would like to contribute is welcome. + +

Requirements

+*Linux/Unix (this includes Mac OSX; sorry, no Windows) +*Node.JS + +

How to Use

+For a simple proof-of-concept: + +*Configure config/server_config.js and config/node_config.js with the desired values. Should be pretty straightforward. +*Run the server on a single machine: sudo node NodeMonitor_Server.js +*Run the node on each machine you want to monitor (can be the same machine the server is running on): sudo node NodeMonitor_Node.js +*???????? +*PROFIT! + +You should see data outputted from the server to the console as it comes in from the node(s). + +

What Needs to be Done?

+*Basic plugins need to be finalized +*WebSocket server needs to be implemented +*Web interface needs to be implemented +*Lots more error handling and fault tolerance needs to be added \ No newline at end of file diff --git a/config/node_config.js b/config/node_config.js new file mode 100644 index 0000000..a9114b3 --- /dev/null +++ b/config/node_config.js @@ -0,0 +1,8 @@ +// The unique indentifier/name of this node +this.node_name = "Server 1"; + +// The address where the server is listening +this.server_addr = '127.0.0.1'; + +// The port where the server is listening +this.server_port = 88; \ No newline at end of file diff --git a/config/server_config.js b/config/server_config.js new file mode 100644 index 0000000..9e88c62 --- /dev/null +++ b/config/server_config.js @@ -0,0 +1,5 @@ +// The address to listen to for incoming connections from nodes +this.node_listen_addr = '127.0.0.1'; + +// The port to use for incoming connections from nodes +this.node_listen_port = 88; \ No newline at end of file diff --git a/plugins/system_uptime.js b/plugins/system_uptime.js new file mode 100644 index 0000000..4185fae --- /dev/null +++ b/plugins/system_uptime.js @@ -0,0 +1,21 @@ +/* + * NodeMonitor + * Copyright 2010 Ryan LeFevre - @meltingice + * + * Licensed under the New BSD License, more info in LICENSE file + * included with this software. + * + * Source code is hosted at http://github.com/meltingice/NodeMonitor + * ================================================================= + * Name: System Uptime Plugin + * Desc: Reports system uptime and system load + */ + +this.poll = function(callback) { + var exec = require('child_process').exec, + child; + + child = exec('uptime', function(error, stdout, stderr) { + callback("Uptime", stdout); + }); +} \ No newline at end of file