UNPKG

log.io-push

Version:

based on log.io :Realtime log monitoring in your browser

491 lines (411 loc) 14.5 kB
// Generated by CoffeeScript 1.4.0 /* Log.io Log Server Relays inbound log messages to web clients LogServer receives log messages via TCP: "+log|my_stream|my_server_host|info|this is a log message\r\n" Announce a node, optionally with stream associations "+node|my_server_host\r\n" "+node|my_server_host|my_stream1,my_stream2,my_stream3\r\n" Announce a stream, optionally with node associations "+stream|my_stream1\r\n" "+stream|my_stream1|my_server_host1,my_host_server2\r\n" Remove a node or stream "-node|my_server_host1\r\n" "-stream|stream2\r\n" WebServer listens for events emitted by LogServer and forwards them to web clients via socket.io # Usage: logServer = new LogServer port: 28777 webServer = new WebServer logServer, port: 28778 webServer.run() */ (function() { var LogNode, LogServer, LogStream, WebServer, events, express, fs, http, https, io, net, winston, _LogObject, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __slice = [].slice; fs = require('fs'); net = require('net'); http = require('http'); https = require('https'); io = require('socket.io'); events = require('events'); winston = require('winston'); express = require('express'); _LogObject = (function() { _LogObject.prototype._type = 'object'; _LogObject.prototype._pclass = function() {}; _LogObject.prototype._pcollection = function() {}; function _LogObject(logServer, name, _pairs) { var pname, _i, _len; this.logServer = logServer; this.name = name; if (_pairs == null) { _pairs = []; } this.logServer.emit("add_" + this._type, this); this.pairs = {}; this.pclass = this._pclass(); this.pcollection = this._pcollection(); for (_i = 0, _len = _pairs.length; _i < _len; _i++) { pname = _pairs[_i]; this.addPair(pname); } } _LogObject.prototype.addPair = function(pname) { var pair; if (!(pair = this.pairs[pname])) { if (!(pair = this.pcollection[pname])) { pair = this.pcollection[pname] = new this.pclass(this.logServer, pname); } pair.pairs[this.name] = this; this.pairs[pname] = pair; return this.logServer.emit("add_" + this._type + "_pair", this, pname); } }; _LogObject.prototype.remove = function() { var name, p, _ref, _results; this.logServer.emit("remove_" + this._type, this); _ref = this.pairs; _results = []; for (name in _ref) { p = _ref[name]; _results.push(delete p.pairs[this.name]); } return _results; }; _LogObject.prototype.toDict = function() { var name, obj; return { name: this.name, pairs: (function() { var _ref, _results; _ref = this.pairs; _results = []; for (name in _ref) { obj = _ref[name]; _results.push(name); } return _results; }).call(this) }; }; return _LogObject; })(); LogNode = (function(_super) { __extends(LogNode, _super); function LogNode() { return LogNode.__super__.constructor.apply(this, arguments); } LogNode.prototype._type = 'node'; LogNode.prototype._pclass = function() { return LogStream; }; LogNode.prototype._pcollection = function() { return this.logServer.logStreams; }; return LogNode; })(_LogObject); LogStream = (function(_super) { __extends(LogStream, _super); function LogStream() { return LogStream.__super__.constructor.apply(this, arguments); } LogStream.prototype._type = 'stream'; LogStream.prototype._pclass = function() { return LogNode; }; LogStream.prototype._pcollection = function() { return this.logServer.logNodes; }; return LogStream; })(_LogObject); /* LogServer listens for TCP connections. It parses & validates inbound TCP messages, and emits events. */ LogServer = (function(_super) { __extends(LogServer, _super); function LogServer(config) { var _ref, _ref1; if (config == null) { config = {}; } this._flush = __bind(this._flush, this); this._receive = __bind(this._receive, this); this.host = config.host, this.port = config.port; this._log = (_ref = config.logging) != null ? _ref : winston; this._delimiter = (_ref1 = config.delimiter) != null ? _ref1 : '\r\n'; this.logNodes = {}; this.logStreams = {}; } LogServer.prototype.run = function() { var _this = this; this.listener = net.createServer(function(socket) { socket._buffer = ''; socket.on('data', function(data) { return _this._receive(data, socket); }); socket.on('error', function() { return _this._tearDown(socket); }); return socket.on('close', function() { return _this._tearDown(socket); }); }); return this.listener.listen(this.port, this.host); }; LogServer.prototype._tearDown = function(socket) { this._log.error('Lost TCP connection...'); if (socket.node) { this._removeNode(socket.node.name); return delete socket.node; } }; LogServer.prototype._receive = function(data, socket) { var part; part = data.toString(); socket._buffer += part; this._log.debug("Received TCP message: " + part); if (socket._buffer.indexOf(this._delimiter >= 0)) { return this._flush(socket); } }; LogServer.prototype._flush = function(socket) { var msg, msgs, _i, _j, _len, _ref, _results; socket.pause(); _ref = socket._buffer.split(this._delimiter), msgs = 2 <= _ref.length ? __slice.call(_ref, 0, _i = _ref.length - 1) : (_i = 0, []), socket._buffer = _ref[_i++]; socket.resume(); _results = []; for (_j = 0, _len = msgs.length; _j < _len; _j++) { msg = msgs[_j]; _results.push(this._handle(socket, msg)); } return _results; }; LogServer.prototype._handle = function(socket, msg) { var args, mtype, _ref; this._log.debug("Handling message: " + msg); _ref = msg.split('|'), mtype = _ref[0], args = 2 <= _ref.length ? __slice.call(_ref, 1) : []; switch (mtype) { case '+log': return this._newLog.apply(this, args); case '+node': return this._addNode.apply(this, args); case '+stream': return this._addStream.apply(this, args); case '-node': return this._removeNode.apply(this, args); case '-stream': return this._removeStream.apply(this, args); case '+bind': return this._bindNode.apply(this, [socket].concat(__slice.call(args))); default: return this._log.error("Invalid TCP message: " + msg); } }; LogServer.prototype._addNode = function(nname, snames) { if (snames == null) { snames = ''; } return this.__add(nname, snames, this.logNodes, LogNode, 'node'); }; LogServer.prototype._addStream = function(sname, nnames) { if (nnames == null) { nnames = ''; } return this.__add(sname, nnames, this.logStreams, LogStream, 'stream'); }; LogServer.prototype._removeNode = function(nname) { return this.__remove(nname, this.logNodes, 'node'); }; LogServer.prototype._removeStream = function(sname) { return this.__remove(sname, this.logStreams, 'stream'); }; LogServer.prototype._newLog = function() { var logLevel, message, nname, node, sname, stream; sname = arguments[0], nname = arguments[1], logLevel = arguments[2], message = 4 <= arguments.length ? __slice.call(arguments, 3) : []; message = message.join('|'); this._log.debug("Log message: (" + sname + ", " + nname + ", " + logLevel + ") " + message); node = this.logNodes[nname] || this._addNode(nname, sname); stream = this.logStreams[sname] || this._addStream(sname, nname); return this.emit('new_log', stream, node, logLevel, message); }; LogServer.prototype.__add = function(name, pnames, _collection, _objClass, objName) { var obj, p, _i, _len, _results; this._log.info("Adding " + objName + ": " + name + " (" + pnames + ")"); pnames = pnames.split(','); obj = _collection[name] = _collection[name] || new _objClass(this, name, pnames); _results = []; for (_i = 0, _len = pnames.length; _i < _len; _i++) { p = pnames[_i]; if (!obj.pairs[p]) { _results.push(obj.addPair(p)); } } return _results; }; LogServer.prototype.__remove = function(name, _collection, objType) { var obj; if (obj = _collection[name]) { this._log.info("Removing " + objType + ": " + name); obj.remove(); return delete _collection[name]; } }; LogServer.prototype._bindNode = function(socket, obj, nname) { var node; if (node = this.logNodes[nname]) { this._log.info("Binding node '" + nname + "' to TCP socket"); socket.node = node; return this._ping(socket); } }; LogServer.prototype._ping = function(socket) { var _this = this; if (socket.node) { socket.write('ping'); return setTimeout((function() { return _this._ping(socket); }), 2000); } }; return LogServer; })(events.EventEmitter); /* WebServer relays LogServer events to web clients via socket.io. */ WebServer = (function() { function WebServer(logServer, config) { var app, _ref, _ref1, _ref2; this.logServer = logServer; this.host = config.host, this.port = config.port, this.auth = config.auth; _ref = this.logServer, this.logNodes = _ref.logNodes, this.logStreams = _ref.logStreams; this.restrictSocket = (_ref1 = config.restrictSocket) != null ? _ref1 : '*:*'; this._log = (_ref2 = config.logging) != null ? _ref2 : winston; app = this._buildServer(config); this.http = this._createServer(config, app); } WebServer.prototype._buildServer = function(config) { var app, ips, staticPath, _ref, _this = this; app = express(); if (this.auth != null) { app.use(express.basicAuth(this.auth.user, this.auth.pass)); } if (config.restrictHTTP) { ips = new RegExp(config.restrictHTTP.join('|')); app.all('/', function(req, res, next) { if (!req.ip.match(ips)) { return res.send(403, "Your IP (" + req.ip + ") is not allowed."); } return next(); }); } staticPath = (_ref = config.staticPath) != null ? _ref : __dirname + '/../'; return app.use(express["static"](staticPath)); }; WebServer.prototype._createServer = function(config, app) { if (config.ssl) { return https.createServer({ key: fs.readFileSync(config.ssl.key), cert: fs.readFileSync(config.ssl.cert) }, app); } else { return http.createServer(app); } }; WebServer.prototype.run = function() { var _emit, _on, _this = this; this._log.info('Starting Log.io Web Server...'); this.logServer.run(); io = io.listen(this.http.listen(this.port, this.host)); io.set('log level', 1); io.set('origins', this.restrictSocket); this.listener = io.sockets; _on = function() { var args, _ref; args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; return (_ref = _this.logServer).on.apply(_ref, args); }; _emit = function(_event, msg) { _this._log.debug("Relaying: " + _event); return _this.listener.emit(_event, msg); }; _on('add_node', function(node) { return _emit('add_node', node.toDict()); }); _on('add_stream', function(stream) { return _emit('add_stream', stream.toDict()); }); _on('add_stream_pair', function(stream, nname) { return _emit('add_pair', { stream: stream.name, node: nname }); }); _on('add_node_pair', function(node, sname) { return _emit('add_pair', { stream: sname, node: node.name }); }); _on('remove_node', function(node) { return _emit('remove_node', node.toDict()); }); _on('remove_stream', function(stream) { return _emit('remove_stream', stream.toDict()); }); _on('new_log', function(stream, node, level, message) { _emit('ping', { stream: stream.name, node: node.name }); return _this.listener["in"]("" + stream.name + ":" + node.name).emit('new_log', { stream: stream.name, node: node.name, level: level, message: message }); }); this.listener.on('connection', function(wclient) { var n, node, s, stream, _ref, _ref1, _ref2, _ref3; _ref = _this.logNodes; for (n in _ref) { node = _ref[n]; wclient.emit('add_node', node.toDict()); } _ref1 = _this.logStreams; for (s in _ref1) { stream = _ref1[s]; wclient.emit('add_stream', stream.toDict()); } _ref2 = _this.logNodes; for (n in _ref2) { node = _ref2[n]; _ref3 = node.pairs; for (s in _ref3) { stream = _ref3[s]; wclient.emit('add_pair', { stream: s, node: n }); } } wclient.emit('initialized'); wclient.on('watch', function(pid) { return wclient.join(pid); }); return wclient.on('unwatch', function(pid) { return wclient.leave(pid); }); }); return this._log.info('Server started, listening...'); }; return WebServer; })(); exports.LogServer = LogServer; exports.WebServer = WebServer; }).call(this);