Skip to content
Browse files

blode now uses socket.io

- lots of cleanup
- updated examples to use jQuery
  • Loading branch information...
1 parent f19f00b commit 16fdf8e5c628e84b8605189f3db2cfab3c4fbf03 @benlemasurier committed Mar 27, 2012
Showing with 427 additions and 198 deletions.
  1. +72 −151 blode.js
  2. +13 −7 config.js
  3. +0 −35 example/blode.html
  4. +11 −0 example/graph/graph.css
  5. +238 −0 example/graph/graph.js
  6. +28 −0 example/graph/index.html
  7. +7 −5 example/services.html
  8. +42 −0 http.js
  9. +16 −0 udp.js
View
223 blode.js
@@ -14,184 +14,105 @@
* 6: info, 7: debug, 8: none
*/
-DEBUG = false;
HOST = "127.0.0.1";
require("./lib/Math.uuid");
-var util = require("./lib/util"),
- ws = require("websocket-server"),
+var derp = require("./lib/util"),
+ io = require("socket.io"),
net = require("net"),
- sys = require("sys"),
+ util = require("util"),
url = require("url"),
http = require("http"),
dgram = require("dgram"),
event = require("events"),
emitter = new event.EventEmitter,
- config = require('./config').config,
log_buffer = { id: 0, severity: 'none', message: '--MARK--' };
-// Listen to log events
-http.createServer(function(request, response) {
- request.extract_message = function() {
- return(url.parse(this.url, true).query);
- };
-
- request.is_valid = function() {
- try {
- var query = this.extract_message();
- if(typeof query.severity !== 'undefined' &&
- typeof query.message !== 'undefined')
- return(true);
- else
- return(false);
- } catch(error) { return(false) }
- };
-
- if(!request.is_valid()) {
- response.writeHead(400); // HTTP 400
- response.end();
-
- if(DEBUG)
- console.log((new Date().getTime()) + " malformed request: " + request.url);
-
- return;
- }
-
- var log = request.extract_message();
- log_buffer.id = Math.uuid();
- log_buffer.severity = log.severity;
- log_buffer.message = log.message;
-
- response.writeHead(200); // HTTP 200 OK
- response.end();
-
- // emit message event
- emitter.emit("log", log_buffer.severity, log_buffer.message);
-
- if(DEBUG)
- console.log((new Date().getTime()) + " received request: " + JSON.stringify(log_buffer));
-}).listen(config.http_log_port, HOST);
-sys.puts("Event HTTP capture daemon started at http://" + HOST + ":" + config.http_log_port);
-
-// UDP event listener
-var udp_server = dgram.createSocket("udp4");
-udp_server.on("message", function (message, rinfo) {
- if(DEBUG)
- console.log("UDP listener got: " + message + " from " + rinfo.address + ":" + rinfo.port);
-
- try {
- var log = JSON.parse(message);
- log_buffer.id = Math.uuid();
- log_buffer.source = rinfo.address;
- log_buffer.severity = log.severity;
- log_buffer.message = log.message;
-
- // emit message event
- emitter.emit("log", log_buffer.severity, log_buffer.message);
- } catch(e) {}
-});
-udp_server.bind(config.dgram_log_port);
-sys.puts("Event UDP capture daemon started at http://" + HOST + ":" + config.dgram_log_port);
-
-// TCP socket event broadcast
-function Client(stream) {
+function Client(stream, type) {
+ this.type = type;
this.stream = stream;
- this.broadcast_events = [
- 'none',
- 'debug',
- 'info',
- 'notice',
- 'warning',
- 'err',
- 'crit',
- 'alert',
- 'emerge'
+ this.subscription = [
+ 'emerge', 'alert', 'crit', 'err', 'warning',
+ 'notice', 'info', 'debug', 'none'
];
}
-var socket_clients = [];
-var socket_buffer = '';
+(function() {
+ var blode = {};
-var server = net.createServer(function(stream) {
- stream.setEncoding('utf8');
- stream.on("connect", function() {
- var client = new Client(stream);
- socket_clients.push(client);
+ blode.config = require('./config');
+ blode.http = require('./http');
+ blode.udp = require('./udp');
- stream.on('end', function() {
- socket_clients.remove(client);
- client.stream.end();
- });
+ blode.clients = [];
- stream.on('data', function(data) {
- socket_buffer += data;
- var message = socket_buffer.indexOf("\r");
- if (message !== -1) {
- var json = socket_buffer.slice(0, message);
- try {
+ blode.udp.listen(HOST, blode.config.dgram.log_port, emitter);
+ blode.http.listen(HOST, blode.config.http.log_port, emitter);
- var broadcast_events = JSON.parse(json);
+ blode.tcp = {};
+ blode.tcp.broadcast = net.createServer(function(stream) {
+ stream.setEncoding('utf8');
+ stream.on("connect", function() {
+ var buffer = '';
+ var client = new Client(stream, 'tcp');
+ blode.clients.push(client);
- if(broadcast_events instanceof Array)
- client.broadcast_events = broadcast_events;
+ stream.on('error', function() {
+ blode.clients.remove(client);
+ client.stream.end();
+ });
- } catch(e) { }
+ stream.on('end', function() {
+ blode.clients.remove(client);
+ client.stream.end();
+ });
- socket_buffer = socket_buffer.slice(message + 1);
- }
- });
+ stream.on('data', function(data) {
+ try {
+ var subscribe = JSON.parse(data);
+ if(subscribe instanceof Array)
+ client.subscription = subscribe;
+ } catch(e) { }
+ });
- stream.on('error', function() {
- socket_clients.remove(client);
- client.stream.end();
});
+ }).listen(blode.config.socket.broadcast_port, HOST);
+ util.puts("tcp broadcast started on " + HOST + ":" + blode.config.socket.broadcast_port);
+
+ blode.io = io.listen(blode.config.io.port);
+ blode.io.configure(function() {
+ blode.io.enable('browser client minification');
+ blode.io.enable('browser client etag');
+ blode.io.enable('browser client gzip');
+ blode.io.set('log level', 1);
});
-});
-server.listen(config.broadcast_socket_port, HOST);
-sys.puts("Event socket broadcast daemon started at " + HOST + ":" + config.broadcast_socket_port);
-
-// HTTP event broadcast
-var http_broadcast = http.createServer(function(request, response) {
- response.writeHead(200, { "Content-Type": "application/json" });
- response.end(JSON.stringify(log_buffer));
-}).listen(config.broadcast_http_port, HOST);
-sys.puts("Event HTTP broadcast daemon started at " + HOST + ":" + config.broadcast_http_port);
-
-// Websocket event broadcast
-var ws_clients = [];
-var ws_server = ws.createServer();
-ws_server.addListener("connection", function(connection) {
- var listener = null,
- client = new Client(connection);
-
- ws_clients.push(client);
- connection.addListener("end", function() {
- ws_clients.remove(client);
- });
+ blode.io.configure('development', function() { blode.io.set('log level', 3); });
- connection.addListener("error", function(error) {
- ws_clients.remove(client);
- });
-});
-ws_server.listen(8008);
-sys.puts("Event web socket broadcast daemon started at " + HOST + ":" + config.websocket_port);
-
-emitter.on("log", function(severity, message) {
- socket_clients.forEach(function(client) {
- try {
- if(client.broadcast_events.indexOf(severity) !== -1)
- client.stream.write(JSON.stringify(log_buffer) + "\r\n");
- } catch(e) {
- socket_clients.remove(client);
- }
+ blode.io.on('connection', function(socket) {
+ var client = new Client(socket, 'io');
+ blode.clients.push(client);
+
+ socket.on("disconnect", function() {
+ blode.clients.remove(client);
+ });
});
+ util.puts("socket.io broadcast started on " + HOST + ":" + blode.config.io.port);
+
+ emitter.on("log", function(log) {
+ log.id = Math.uuid();
+
+ blode.clients.forEach(function(client) {
+ try {
+ if(client.subscription.indexOf(log.severity) != -1)
+ if(client.type === 'tcp')
+ client.stream.write(JSON.stringify(log) + "\r\n");
+ else if(client.type === 'io')
+ client.stream.volatile.emit('message', JSON.stringify(log));
+ } catch(e) {
+ socket_clients.remove(client);
+ }
+ });
- ws_clients.forEach(function(client) {
- try {
- client.stream.write(JSON.stringify(log_buffer) + "\r\n");
- } catch(e) {
- ws_clients.remove(client);
- }
});
-});
+})();
View
20 config.js
@@ -1,7 +1,13 @@
-exports.config = {
- http_log_port: 8000,
- dgram_log_port: 8010,
- broadcast_socket_port: 8001,
- broadcast_http_port: 8002,
- websocket_port: 8008
-};
+var config = {};
+config.io = {};
+config.http = {};
+config.dgram = {};
+config.socket = {};
+
+config.http.log_port = 8000;
+config.http.broadcast_port = 8002;
+config.dgram.log_port = 8010;
+config.socket.broadcast_port = 8001;
+config.io.port = 8008;
+
+module.exports = config;
View
35 example/blode.html
@@ -1,35 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <title>Blode - hits are pretties</title>
- <link rel="stylesheet" type="text/css" media="screen" href="css/blode.css" />
- <script src="js/prototype.js" type="text/javascript"></script>
- <script src="js/blode_helpers.js" type="text/javascript"></script>
- <script src="js/blode_message.js" type="text/javascript"></script>
- <script src="js/blode_socket.js" type="text/javascript"></script>
- <script src="js/blode_graph.js" type="text/javascript"></script>
- <script language="javascript">
- window.onload = function() {
- window.graph = new BlodeGraph("visualization");
-
- $('legend').observe('click', function() {
- if(window.graph.show_legend) {
- window.graph.show_legend = false;
- $('legend').innerHTML = "show legend";
- } else {
- window.graph.show_legend = true;
- $('legend').innerHTML = "hide legend";
- }
- });
- };
- </script>
- </head>
- <body>
- <h1>hits are pretties</h1>
- <p id="visualization">
- </p>
- <p id="controls">
- <a id="legend" onclick="return(false);">show legend</a>
- </p>
- </body>
-</html>
View
11 example/graph/graph.css
@@ -0,0 +1,11 @@
+body {
+ background-color: #111;
+ color: white;
+ font-family: helvetica, arial;
+ margin: 30px;
+}
+
+#blode {
+ height: 300px;
+}
+
View
238 example/graph/graph.js
@@ -0,0 +1,238 @@
+;(function($) {
+
+ var _graph = {
+ log_buffer: [],
+ legend: '',
+ background: '',
+ foreground: '',
+ element: null,
+ tick: 100, // ms
+ bar_width: 3,
+ bar_padding: 1,
+ bg_color: 'rgba(25, 91, 121, 1)', // blue
+ fg_color: 'rgba(100, 170, 208, 1)', // light blue
+ legend_color: 'rgba(255, 255, 255, 1)', // white
+ show_legend: false
+ };
+
+ var methods = {
+ init: function(options) {
+ return this.each(function() {
+ _graph = $.extend({}, _graph, options);
+ _graph.element = $(this);
+
+ _graph.background = methods.create_layer.call(this, 0);
+ _graph.foreground = methods.create_layer.call(this, 1);
+ _graph.legend = methods.create_layer.call(this, 2);
+ methods.init_buffer.call(this);
+
+ methods.render_background.call(this);
+
+ var socket = io.connect('http://tuberculosis:8008');
+ socket.on('message', function() {
+ _graph.log_buffer[0]++;
+ });
+
+ // every 'tick' rotate the log buffer and render the foreground
+ window.setInterval(function() {
+ if(!_graph.pause)
+ methods.render_foreground.call(this);
+
+ if(_graph.show_legend)
+ methods.render_legend.call(this, methods.log_max.call(this, _graph.log_buffer));
+
+ // insert a new (blank) item into the current 'tick'
+ _graph.log_buffer.unshift(new Array());
+
+ // remove the last item from the buffer
+ _graph.log_buffer = _graph.log_buffer.slice(0, -1);
+ }, _graph.tick);
+
+ window.onresize = function() {
+ $(_graph.background).attr('width', _graph.element.width());
+ $(_graph.background).attr('height', _graph.element.height());
+ $(_graph.foreground).attr('width', _graph.element.width());
+ $(_graph.foreground).attr('height', _graph.element.height());
+ $(_graph.legend).attr('width', _graph.element.width());
+ $(_graph.legend).attr('height', _graph.element.height());
+
+ methods.init_buffer.call(this);
+
+ methods.render_foreground.call(this);
+ methods.render_background.call(this);
+ };
+
+ });
+ },
+
+ toggle_legend: function() {
+ if(_graph.show_legend) {
+ _graph.show_legend = false;
+ methods.clear_legend.call(this);
+
+ return
+ }
+
+ _graph.show_legend = true;
+ },
+
+ scale_buffer: function(buffer) {
+ var max = _graph.foreground.height - 1,
+ buffer_max = methods.log_max.call(this, buffer),
+ scale_factor = 1;
+
+ // calculate scale
+ scale_factor = max / buffer_max;
+
+ // scale the buffer
+ for(var i = 0; i < buffer.length; i++)
+ buffer[i] = Math.floor(buffer[i] * scale_factor);
+
+ return buffer;
+ },
+
+ create_layer: function(index) {
+ index = index || 0;
+ var p = _graph.element.position(),
+ layer = jQuery("<canvas/>").css(
+ {
+ 'z-index': index,
+ position: 'absolute',
+ top: p.top,
+ left: p.left
+ }
+ );
+
+ layer.attr('width', _graph.element.width());
+ layer.attr('height', _graph.element.height());
+
+ _graph.element.append(layer);
+
+ return layer[0];
+ },
+
+ render_background: function() {
+ // the background consists of each bars bg color
+ var context = _graph.background.getContext('2d'),
+ x = context.canvas.width,
+ y = 0,
+ height = context.canvas.height;
+
+ // clear layer
+ context.clearRect(0, 0, _graph.background.width, height);
+
+ // set layer color
+ context.fillStyle = _graph.bg_color;
+
+ // draw the bar backgrounds
+ for(i = 0, j = _graph.log_buffer.length; i < j; i++) {
+ x -= _graph.bar_width;
+ context.fillRect(x, y, _graph.bar_width, height);
+ x -= _graph.bar_padding;
+ }
+ },
+
+ render_foreground: function() {
+ // render from right to left (most recent tick, descending)
+ var context = _graph.foreground.getContext('2d'),
+ x = context.canvas.width,
+ y = 0,
+ height = context.canvas.height,
+ scaled = [];
+
+ // clear layer and set styles
+ context.clearRect(0, 0, _graph.foreground.width, height);
+ context.fillStyle = _graph.fg_color;
+
+ // scale and draw the bars
+ scaled = methods.scale_buffer.call(this, _graph.log_buffer.slice());
+
+ // draw
+ for(var i = 0, j = scaled.length; i < j; i++) {
+ x -= _graph.bar_width;
+ y = (context.canvas.height - scaled[i]) || height;
+
+ context.fillRect(x, y, _graph.bar_width, height);
+
+ x -= _graph.bar_padding;
+ }
+ },
+
+ clear_legend: function() {
+ _graph.legend.getContext('2d').clearRect(0, 0, _graph.legend.width, _graph.legend.height);
+ },
+
+ render_legend: function(max) {
+ if(!_graph.show_legend)
+ return;
+
+ var context = _graph.legend.getContext('2d'),
+ height = context.canvas.height,
+ half_pi = Math.PI / 180;
+
+ // clear layer and set styles
+ methods.clear_legend.call(this);
+ context.fillStyle = "rgba(0, 0, 0, 0.7)";
+ context.fillRect(0, 0, 30, height);
+ context.fillStyle = _graph.legend_color;
+ context.font = "bold 10px Helvetica, Arial";
+ context.textBaseline = "top";
+ context.textAlign = "end";
+
+ // hits legend
+ context.translate(10, height / 2);
+ context.rotate(-90 * half_pi);
+ context.fillText("HITS", 0, 0);
+ context.rotate(90 * half_pi);
+ context.translate(-10, -(height / 2));
+ context.fillText(max, 25, 10);
+ context.fillText(0, 25, height - 20);
+
+ // time legend
+ context.fillStyle = "rgba(0, 0, 0, 0.7)";
+ context.fillRect(30, height - 30, context.canvas.width, 30);
+ context.textAlign = "center";
+ context.fillStyle = _graph.legend_color;
+ context.fillText("TIME (" + _graph.tick + "ms)", context.canvas.width / 2, height - 20);
+ },
+
+ log_max: function(buffer) {
+ var max = 0;
+ for(var i = 0, j = buffer.length; i < j; i++) {
+ if(isNaN(buffer[i]))
+ buffer[i] = 0;
+ if(buffer[i] > max)
+ max = buffer[i];
+ }
+
+ return max;
+ },
+
+ log_buffer_size: function() {
+ // the size is determined by the maximum number of graph "bars"
+ // capable of being displayed on the screen at any given time.
+ // i.e. the wider the screen, the more bars.
+ // the more bars, the more ticks.
+ return Math.floor(_graph.foreground.width /
+ (_graph.bar_width + _graph.bar_padding));
+ },
+
+ init_buffer: function() {
+ _graph.log_buffer = [];
+ for(var i = 0, j = methods.log_buffer_size.call(this); i < j; i++)
+ _graph.log_buffer[i] = 0;
+ },
+
+ };
+
+ $.fn.graph = function(method) {
+ if(methods[method]) {
+ return methods[ method ].apply(this, Array.prototype.slice.call(arguments, 1));
+ } else if(typeof method === 'object' || !method) {
+ return methods.init.apply(this, arguments);
+ } else {
+ $.error('Method ' + method + ' does not exist on jQuery.graph' );
+ }
+ };
+
+})(jQuery);
View
28 example/graph/index.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+
+ <head>
+ <title>Blode - hits are pretties</title>
+ <link rel="stylesheet" type="text/css" media="screen" href="graph.css" />
+ <script src="http://tuberculosis:8008/socket.io/socket.io.js"></script>
+ <script src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
+ </head>
+
+ <body>
+ <h1>hits are pretties</h1>
+
+ <div id=blode></div>
+ <p>
+ <a id="legend" onclick="$(blode).graph('toggle_legend'); return(false);">show legend</a>
+ </p>
+
+ </body>
+
+ <script src="graph.js"></script>
+ <script>
+ $(document).ready(function() {
+ var blode = $('#blode').graph();
+ });
+ </script>
+
+</html>
View
12 example/services.html
@@ -4,6 +4,7 @@
<title>Blode - SparkFun</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script src="http://omnipotent.net/jquery.sparkline/1.6/jquery.sparkline.min.js"></script>
+ <script src="http://tuberculosis:8008/socket.io/socket.io.js"></script>
<style>
body {
font-family: Helvetica, Arial, sans-serif;
@@ -135,10 +136,11 @@
$(document).data('log_buffer', buffer);
}
- var i = 0;
- var ws = new WebSocket('ws://10.10.10.2:8008');
- ws.onmessage = function(event) {
- var data = jQuery.parseJSON(event.data);
+ var i = 0,
+ socket = io.connect('http://tuberculosis:8008');
+ socket.on('message', function(event) {
+ var data = jQuery.parseJSON(event);
+ console.log(data);
var buffer = $(document).data('log_buffer');
buffer[0].push(1);
@@ -163,7 +165,7 @@
$(document).data('threads', threads);
$('#threads-blink').toggle();
}
- };
+ });
init_log_buffer();
window.setInterval(function() {
View
42 http.js
@@ -0,0 +1,42 @@
+(function() {
+
+ module.exports.listen = function(host, port, emitter) {
+ var event = emitter;
+ var util = require("util");
+ var url = require("url");
+ var http = require("http");
+
+ http.createServer(function(request, response) {
+ request.extract_message = function() {
+ return(url.parse(this.url, true).query);
+ };
+
+ request.is_valid = function() {
+ try {
+ var query = this.extract_message();
+ if(typeof query.severity !== 'undefined' &&
+ typeof query.message !== 'undefined')
+ return(true);
+ else
+ return(false);
+ } catch(error) { return(false) }
+ };
+
+ if(!request.is_valid()) {
+ response.writeHead(400); // HTTP 400
+ response.end();
+ return;
+ }
+
+ response.writeHead(200); // HTTP 200 OK
+ response.end();
+
+ // emit message event
+ var message = request.extract_message();
+ event.emit("log", message);
+
+ }).listen(port, host);
+ util.puts("http capture listening on http://" + host + ":" + port);
+ }
+
+})();
View
16 udp.js
@@ -0,0 +1,16 @@
+(function() {
+
+ module.exports.listen = function(host, port, emitter) {
+ var event = emitter;
+ var util = require("util");
+ var udp = require("dgram").createSocket("udp4");
+
+ udp.on("message", function (message, rinfo) {
+ try { event.emit("log", JSON.parse(message)); } catch(e) {}
+ });
+
+ udp.bind(port);
+ util.puts("udp capture listening on " + host + ":" + port);
+ }
+
+})();

0 comments on commit 16fdf8e

Please sign in to comment.
Something went wrong with that request. Please try again.