Permalink
Browse files

Initial commit

  • Loading branch information...
0 parents commit 67faeb3a384fbd7af3af561906a89aba4ea28cb0 @mattrobenolt mattrobenolt committed Nov 29, 2011
Showing with 163 additions and 0 deletions.
  1. +15 −0 .gitignore
  2. +26 −0 lib/middleware/connect-raven.js
  3. +90 −0 lib/raven.js
  4. +21 −0 lib/utils.js
  5. +11 −0 tests.js
@@ -0,0 +1,15 @@
+lib-cov
+*.seed
+*.log
+*.csv
+*.dat
+*.out
+*.pid
+*.gz
+
+pids
+logs
+results
+
+node_modules
+npm-debug.log
@@ -0,0 +1,26 @@
+var crypto = require('crypto'),
+ utils = require('../utils'),
+ Client = require('../raven').Client;
+
+module.exports = function raven(options) {
+ var client = new Client(options);
+ return function(err, req, res, next) {
+ var kwargs = {
+ data: {
+ headers: req.headers,
+ url: req.url,
+ originalUrl: req.originalUrl,
+ method: req.method
+ },
+ url: (function build_absolute_url(req) {
+ var protocol = req.socket.encrypted ? 'https' : 'http',
+ host = req.headers.host || '<no host>';
+ return protocol+'://'+host+req.url;
+ }(req))
+ };
+ var result = client.create_from_exception(err, kwargs);
+ res.sentry = {id: result['message_id']};
+ res.statusCode = 500;
+ res.end(result['message_id']);
+ };
+};
@@ -0,0 +1,90 @@
+var zlib = require('zlib'),
+ utils = require('./utils'),
+ parseUrl = require('url').parse,
+ uuid = require('node-uuid');
+
+var Client = function(options) {
+ this.servers = options.servers;
+ this.key = options.key;
+ this.name = options.name || require('os').hostname();
+ this.site = options.site;
+ this.root = options.root || process.cwd();
+}, _ = Client.prototype;
+
+module.exports.Client = Client;
+
+_.get_ident = function(result) {
+ return result.join('$');
+};
+
+_.process = function(kwargs) {
+ var message_id = uuid().replace(/-/g, ''),
+ checksum;
+
+ kwargs['data'] = kwargs['data'] || {};
+ kwargs['data']['__sentry__'] = kwargs['data']['__sentry__'] || {};
+
+ kwargs['message_id'] = message_id;
+ kwargs['timestamp'] = kwargs['timestamp'] || new Date().getTime()/1000;
+
+ if(!'checksum' in kwargs) {
+ checksum = kwargs['checksum'] = utils.construct_checksum(kwargs);
+ } else {
+ checksum = kwargs['checksum'];
+ }
+
+ kwargs['server_name'] = kwargs['server_name'] || this.name;
+ kwargs['site'] = kwargs['site'] || this.site;
+ console.log(kwargs);
+ this.send(kwargs);
+
+ return {'message_id': message_id, 'checksum': checksum};
+};
+
+_.send_remote = function(url, message, headers, callback) {
+ url = parseUrl(url);
+ var options = {
+ host: url.hostname,
+ path: url.pathname,
+ port: url.port,
+ headers: headers,
+ method: 'POST',
+ }, httpclient = require(url.protocol.slice(0, url.protocol.length-1));
+
+ var req = httpclient.request(options, callback);
+ req.write(message);
+ req.end();
+};
+
+_.send = function(kwargs) {
+ var self = this;
+ zlib.deflate(JSON.stringify(kwargs), function(err, buff) {
+ var message = buff.toString('base64');
+ //TODO: refactor this to not blast out to all servers at once.
+ self.servers.forEach(function(url) {
+ var timestamp = Math.round((new Date().getTime()/1000))+'.0', // this is a shitty workout for Sentry
+ signature = utils.get_signature(self.key, message, timestamp),
+ headers = {
+ 'Authorization': utils.get_auth_header(signature, timestamp),
+ 'Content-Type': 'application/octet-stream',
+ };
+
+ self.send_remote(url, message, headers);
+ });
+ });
+};
+
+_.create_from_text = function(message, kwargs) {
+ kwargs = kwargs || {};
+ kwargs['message'] = message;
+ return this.process(kwargs);
+};
+
+_.create_from_exception = _.create_from_error = function(err, kwargs) {
+ kwargs = kwargs || {};
+ kwargs['message'] = err.stack.split('\n')[0];
+ kwargs['traceback'] = err.stack;
+ // this is shitty. And Node doesn't have "views". What should we do here?
+ kwargs['view'] = err.name + ' in ' + err.stack.split('\n')[1].match(/^.*?\((.*?):\d+:\d+\)$/)[1].replace(process.cwd()+'/', '');
+ return this.process(kwargs);
+};
@@ -0,0 +1,21 @@
+var crypto = require('crypto');
+
+module.exports.construct_checksum = function construct_checksum(kwargs) {
+ var checksum = crypto.createHash('md5');
+ checksum.update(kwargs['class_name'] || '');
+ checksum.update(kwargs['traceback'] || kwargs['message'] || '');
+ return checksum.digest('hex');
+};
+
+module.exports.get_signature = function get_signature(key, message, timestamp) {
+ var hmac = crypto.createHmac('sha1', key);
+ hmac.update(timestamp+' '+message);
+ return hmac.digest('hex');
+};
+
+module.exports.get_auth_header = function get_auth_header(signature, timestamp) {
+ var header = ['Sentry sentry_signature='+signature];
+ header.push('sentry_timestamp='+timestamp);
+ header.push('raven=0.1');
+ return header.join(', ');
+};
@@ -0,0 +1,11 @@
+var connect = require('connect'),
+ raven = require('./lib/middleware/connect-raven');
+
+var raven_options = {
+ key: 'testing123',
+ servers: ['http://sentry.dev:9000/store/'],
+};
+
+connect(function(req, res){
+ idontexist['what'];
+}, raven(raven_options)).listen(3000);

0 comments on commit 67faeb3

Please sign in to comment.