Launch Week Day 5: Introducing Reachability for PHP.Learn More
Socket
Book a DemoSign in
Socket

raven

Package Overview
Dependencies
Maintainers
1
Versions
70
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

raven - npm Package Compare versions

Comparing version
0.1.0
to
0.2.0
+50
lib/parsers.js
var utils = require('./utils')
url = require('url');
module.exports.parseText = function parseText(message, kwargs) {
kwargs = kwargs || {};
kwargs['message'] = message;
kwargs['sentry.interfaces.Message'] = {
message: message,
params: []
};
return kwargs;
};
module.exports.parseError = function parseError(err, kwargs, cb) {
utils.parseStack(err.stack, function(e, frames) {
kwargs['message'] = err.name+': '+(err.message || '<no message>');
kwargs['sentry.interfaces.Exception'] = {type:err.name, value:err.message};
kwargs['sentry.interfaces.Stacktrace'] = {frames:frames};
kwargs['culprit'] = (frames[0].filename || 'unknown file').replace(process.cwd()+'/', '')+':'+(frames[0]['function'] || 'unknown function');
cb(kwargs);
});
};
module.exports.parseQuery = function parseQuery(query, engine, kwargs) {
kwargs = kwargs || {};
kwargs['message'] = query;
kwargs['sentry.interfaces.Query'] = {
query: query,
engine: engine
};
return kwargs;
};
module.exports.parseRequest = function parseRequest(req, kwargs) {
kwargs = kwargs || {};
kwargs['sentry.interfaces.Http'] = {
method: req.method,
query_string: url.parse(req.url).query,
headers: req.headers,
cookies: req.cookies || '<unavailable: use cookieParser middleware>',
data: req.body || '<unavailable: use bodyParser middleware>',
url: (function build_absolute_url() {
var protocol = req.socket.encrypted ? 'https' : 'http',
host = req.headers.host || '<no host>';
return protocol+'://'+host+req.url;
}()),
env: process.env
};
return kwargs;
};
+52
-36

@@ -1,2 +0,3 @@

var zlib = require('zlib'),
var parsers = require('./parsers'),
zlib = require('zlib'),
utils = require('./utils'),

@@ -7,10 +8,22 @@ parseUrl = require('url').parse,

module.exports.version = '0.2.0';
var Client = function Client(dsn, options) {
if(arguments.length === 0) {
// no arguments, use default from environment
dsn = process.env.SENTRY_DSN;
options = {};
}
if(typeof dsn === 'object') {
// They must only be passing through options
options = dsn;
dsn = process.env.SENTRY_DSN;
}
options = options || {};
this.dsn = utils.parseDSN(dsn);
this.name = options.name || require('os').hostname();
this.site = options.site;
this.name = options.name || process.env.SENTRY_NAME || require('os').hostname();
this.site = options.site || process.env.SENTRY_SITE;
this.root = options.root || process.cwd();
if(!process.env.NODE_ENV || !(process.env.NODE_ENV == 'production' || process.env.NODE_ENV == 'test')) {
console.log('Warning: Sentry logging is disabled, please set NODE_ENV=production');
console.warn('Warning: Sentry logging is disabled, please set NODE_ENV=production');
this._enabled = false;

@@ -33,8 +46,9 @@ } else {

kwargs['event_id'] = event_id;
kwargs['timestamp'] = new Date().toISOString().split('.')[0];
kwargs['project'] = this.dsn.project_id;
kwargs['modules'] = utils.getModules();
kwargs['server_name'] = kwargs['server_name'] || this.name;
kwargs['extra'] = kwargs['extra'] || {};
kwargs['extra']['node'] = process.version;
if(!kwargs['checksum']){
checksum = kwargs['checksum'] = utils.construct_checksum(kwargs);
checksum = kwargs['checksum'] = utils.constructChecksum(kwargs);
} else {

@@ -44,5 +58,6 @@ checksum = kwargs['checksum'];

kwargs['server_name'] = kwargs['server_name'] || this.name;
kwargs['event_id'] = event_id;
kwargs['timestamp'] = new Date().toISOString().split('.')[0];
kwargs['project'] = this.dsn.project_id;
kwargs['site'] = kwargs['site'] || this.site;
kwargs['extra'] = kwargs['extra'] || {};

@@ -55,3 +70,3 @@ // this will happen asynchronously. We don't care about it's response.

_.sendRemote = function sendRemote(message, headers, callback) {
_.sendRemote = function sendRemote(message, headers, cb) {
var self = this;

@@ -80,5 +95,5 @@ var options = {

timestamp = new Date().getTime(),
signature = utils.get_signature(self.dsn.private_key, message, timestamp),
signature = utils.getSignature(self.dsn.private_key, message, timestamp),
headers = {
'X-Sentry-Auth': utils.get_auth_header(signature, timestamp, self.dsn.public_key, self.dsn.project_id),
'X-Sentry-Auth': utils.getAuthHeader(signature, timestamp, self.dsn.public_key, self.dsn.project_id),
'Content-Type': 'application/octet-stream',

@@ -92,6 +107,5 @@ 'Content-Length': message.length

_.createFromText =
_.create_from_text = function createFromText(message, kwargs, callback) {
if(!callback && typeof kwargs === 'function') {
callback = kwargs;
_.captureMessage = function captureMessage(message, kwargs, cb) {
if(!cb && typeof kwargs === 'function') {
cb = kwargs;
kwargs = {};

@@ -101,18 +115,12 @@ } else {

}
kwargs['message'] = message;
kwargs['sentry.interfaces.Message'] = {
message: message,
params: []
};
var result = this.process(kwargs);
callback && callback(result);
var result = this.process(parsers.parseText(message, kwargs));
cb && cb(result);
return result;
};
_.createFromError =
_.create_from_exception =
_.create_from_error = function createFromError(err, kwargs, callback) {
_.captureError =
_.captureException = function captureError(err, kwargs, cb) {
var self = this;
if(!callback && typeof kwargs === 'function') {
callback = kwargs;
if(!cb && typeof kwargs === 'function') {
cb = kwargs;
kwargs = {};

@@ -122,12 +130,20 @@ } else {

}
utils.parseStack(err.stack, function(e, frames) {
kwargs['message'] = err.name+': '+err.message;
kwargs['sentry.interfaces.Exception'] = {type:err.name, value:err.message};
kwargs['sentry.interfaces.Stacktrace'] = {frames:frames};
kwargs['culprit'] = err.name + ' in ' + err.stack.split('\n')[1].match(/^.*?\((.*?):\d+:\d+\)$/)[1].replace(process.cwd()+'/', '');
var result = self.process(kwargs);
callback && callback(result);
parsers.parseError(err, kwargs, function(kw) {
var result = self.process(kw);
cb && cb(result);
});
};
_.captureQuery = function captureQuery(query, engine, kwargs, cb) {
if(!cb && typeof kwargs === 'function') {
cb = kwargs;
kwargs = {};
} else {
kwargs = kwargs || {};
}
var result = this.process(parsers.parseQuery(query, engine, kwargs));
cb && cb(result);
return result;
};
_.patchGlobal = function patchGlobal() {

@@ -134,0 +150,0 @@ module.exports.patchGlobal(this);

@@ -1,22 +0,8 @@

var Client = require('../client').Client
, url = require('url');
var raven = require('../client'),
parsers = require('../parsers');
module.exports = function raven(client) {
client = (client instanceof Client) ? client : new Client(client);
module.exports = function connectMiddleware(client) {
client = (client instanceof raven.Client) ? client : new raven.Client(client);
return function(err, req, res, next) {
var kwargs = {
'sentry.interfaces.Http': {
method: req.method,
query_string: url.parse(req.url).query,
headers: req.headers,
cookies: req.cookies || '<unavailable: use cookieParser middleware>',
data: req.body || '<unavailable: use bodyParser middleware>',
url: (function build_absolute_url() {
var protocol = req.socket.encrypted ? 'https' : 'http',
host = req.headers.host || '<no host>';
return protocol+'://'+host+req.url;
}()),
env: process.env
}
};
var kwargs = parsers.parseRequest(req);
client.createFromError(err, kwargs, function(result) {

@@ -23,0 +9,0 @@ res.sentry = client.getIdent(result);

@@ -1,7 +0,7 @@

var crypto = require('crypto'),
var raven = require('./client'),
crypto = require('crypto'),
fs = require('fs'),
url = require('url'),
LINES_OF_CONTEXT = 7;
url = require('url');
module.exports.construct_checksum = function construct_checksum(kwargs) {
module.exports.constructChecksum = function constructChecksum(kwargs) {
var checksum = crypto.createHash('md5');

@@ -12,3 +12,3 @@ checksum.update(kwargs['message'] || '');

module.exports.get_signature = function get_signature(key, message, timestamp) {
module.exports.getSignature = function getSignature(key, message, timestamp) {
var hmac = crypto.createHmac('sha1', key);

@@ -19,9 +19,9 @@ hmac.update(timestamp+' '+message);

module.exports.get_auth_header = function get_auth_header(signature, timestamp, api_key, project_id) {
module.exports.getAuthHeader = function getAuthHeader(signature, timestamp, api_key, project_id) {
var header = ['Sentry sentry_version=2.0'];
header.push('sentry_signature='+signature);
header.push('sentry_timestamp='+timestamp);
header.push('sentry_client=raven-node/0.1');
if(api_key) header.push('sentry_key='+api_key);
if(project_id) header.push('project_id='+project_id);
header.push('sentry_client=raven-node/'+raven.version);
header.push('sentry_key='+api_key);
header.push('project_id='+project_id);
return header.join(', ');

@@ -50,2 +50,25 @@ };

var module_cache;
module.exports.getModules = function getModules() {
if(module_cache) {
return module_cache;
}
var path = require('path');
var cwd = path.resolve('.');
var folders = fs.readdirSync(path.join(cwd, './node_modules/'));
folders = folders.filter(function(f){
return f.charAt(0) !== '.';
});
module_cache = {};
folders.forEach(function(folder) {
try {
var json = require(path.join(cwd, './node_modules/'+folder+'/package.json'));
module_cache[json.name] = json.version;
} catch(e){}
});
return module_cache;
};
var LINES_OF_CONTEXT = 7;
/*

@@ -55,3 +78,3 @@ * Testing out with a custom stack track.

*/
module.exports.parseStackBetter = function parseStackBetter(err, callback) {
module.exports.parseStackBetter = function parseStackBetter(err, cb) {
var orig = Error.prepareStackTrace;

@@ -82,3 +105,3 @@ Error.prepareStackTrace = function(_, stack){ return stack; };

module.exports.parseStack = function parseStack(stack, callback) {
module.exports.parseStack = function parseStack(stack, cb) {
// grab all lines except the first

@@ -88,8 +111,12 @@ var lines = stack.split('\n').slice(1), callbacks=lines.length, frames=[], cache={};

lines.forEach(function(line, index) {
var data = line.match(/^\s*at (.+?) \((.+?):(\d+):(\d+)\)$/).slice(1),
var data = line.match(/^\s*at (?:(.+(?: \[\w\s+\])?) )?\(?(.+?)(?::(\d+):(\d+))?\)?$/).slice(1),
frame = {
'function': data[0],
filename: data[1],
lineno: ~~data[2]
};
// only set the function key if it exists
if(data[0]) {
frame['function'] = data[0];
}
// internal Node files are not full path names. Ignore them.

@@ -100,9 +127,12 @@ if(frame.filename[0] === '/' || frame.filename[0] === '.') {

parseLines(cache[frame.filename]);
if(--callbacks === 0) callback(null, frames);
if(--callbacks === 0) cb(null, frames);
} else {
fs.readFile(frame.filename, function(err, file) {
file = file.toString().split('\n');
cache[frame.filename] = file;
parseLines(file);
if(--callbacks === 0) callback(null, frames);
if(!err) {
file = file.toString().split('\n');
cache[frame.filename] = file;
parseLines(file);
}
frames[index] = frame;
if(--callbacks === 0) cb(null, frames);
});

@@ -112,3 +142,3 @@ }

frames[index] = frame;
if(--callbacks === 0) callback(null, frames);
if(--callbacks === 0) cb(null, frames);
}

@@ -120,5 +150,4 @@

frame.post_context = lines.slice(frame.lineno, frame.lineno+LINES_OF_CONTEXT);
frames[index] = frame;
}
});
};

@@ -5,3 +5,3 @@ {

"keywords": ["raven", "sentry", "python"],
"version": "0.1.0",
"version": "0.2.0",
"repository": "git://github.com/mattrobenolt/raven-node.git",

@@ -14,3 +14,3 @@ "author": "Matt Robenolt <matt@ydekproductions.com>",

"engines": {
"node": ">= 0.6.0 < 0.7.0"
"node": ">= 0.6.0"
},

@@ -25,4 +25,5 @@ "dependencies": {

"should": "*",
"nock": "*"
"nock": "*",
"glob": "*"
}
}
test:
@NODE_ENV=test ./node_modules/.bin/mocha --reporter dot
.PHONY: test
# Raven
Log errors and stack traces in [Sentry](http://getsentry.com/) from within your Node.js applications. Includes middleware support for [Connect](http://www.senchalabs.org/connect/)/[Express](http://expressjs.com/).
All processing and sending happens asynchronously to not slow things down if/when Sentry is down or slow.
## Installation
```
$ npm install raven
```
## Basic Usage
```javascript
var raven = require('raven');
var client = new raven.Client('{{ SENTRY_DSN }}');
client.createFromText('Hello, world!');
```
Error logging
## Logging an error
```javascript
client.createFromError(new Error('Broke!'));
```
## Sentry Identifier
```javascript
client.createFromText('Hello, world!', function(result) {
console.log(client.getIdent(result));
});
```
```javascript
client.createFromError(new Error('Broke!'), function(result) {
console.log(client.getIdent(result));
});
```
__Note__: `client.createFromText` will also return the result directly without the need for a callback, such as: `var result = client.createFromText('Hello, world!');`
## Catching global errors
For those times when you don't catch all errors in your application. ;)
```javascript
client.patchGlobals();
// or
raven.patchGlobals(client);
// or
raven.patchGlobals('{{ SENTRY_DSN }}');
```
## Methods
```javascript
new raven.Client(dsn[, options])
client.createFromText(string[,callback])
client.createFromError(Error[,callback])
```
## Integrations
### Connect/Express middleware
The Raven middleware can be used as-is with either Connect or Express in the same way. Take note that in your middlewares, Raven must appear _after_ your main handler to pick up any errors that may result from handling a request.
#### Connect
```javascript
var connect = require('connect');
function mainHandler(req, res) {
throw new Error('Broke!');
}
function onError(err, req, res, next) {
// The error id is attached to `res.sentry` to be returned
// and optionally displayed to the user for support.
res.statusCode = 500;
res.end(res.sentry+'\n');
}
connect(
connect.bodyParser(),
connect.cookieParser(),
mainHandler,
raven.middleware.connect('{{ SENTRY_DSN }}'),
onError, // optional error handler if you want to display the error id to a user
).listen(3000);
```
#### Express
```javascript
var app = require('express').createServer();
app.error(raven.middleware.express('{{ SENTRY_DSN }}'));
app.error(onError); // optional error handler if you want to display the error id to a user
app.get('/', function mainHandler(req, res) {
throw new Error('Broke!');
});
app.listen(3000);
```
## Todo
* Support for process.env.SENTRY_DSN
* More complete test coverage
* Travis CI
* More comments in code
* More third party integration
* Logging support for SQL
function foo() {
bar('hey');
}
function bar(a,b,c) {
var test='yay!';
trace();
}
function trace() {
console.log(__stack[1].fun.arguments);
}
foo();
ReferenceError: __stack is not defined
at trace (./test/fixtures/stack.js:11:15)
at bar (./test/fixtures/stack.js:7:3)
at foo (./test/fixtures/stack.js:2:3)
at Object.<anonymous> (./test/fixtures/stack.js:14:1)
at Module._compile (module.js:441:26)
at Object..js (module.js:459:10)
at Module.load (module.js:348:31)
at Function._load (module.js:308:12)
at Array.0 (module.js:479:10)
at EventEmitter._tickCallback (node.js:192:40)

Sorry, the diff of this file is not supported yet

var raven = require('../')
, fs = require('fs')
, nock = require('nock');
var dsn = 'https://public:private@app.getsentry.com/269';
describe('raven.Client', function(){
var client;
before(function(){
client = new raven.Client(dsn);
});
describe('#getIdent()', function(){
it('should match', function(){
var result = {
id: 'c988bf5cb7db4653825c92f6864e7206',
checksum: 'b8a6fbd29cc9113a149ad62cf7e0ddd5'
};
client.getIdent(result).should.equal('c988bf5cb7db4653825c92f6864e7206$b8a6fbd29cc9113a149ad62cf7e0ddd5');
});
});
describe('#createFromText()', function(){
it('should send a plain text message to Sentry server', function(done){
var scope = nock('https://app.getsentry.com')
.filteringRequestBody(/.*/, '*')
.post('/api/store/', '*')
.reply(200, 'OK');
client.createFromText('Hey!');
setTimeout(function(){scope.done(); done();}, 2); // Really should not take more than 5ms to work.
});
});
});
var raven = require('../')
, fs = require('fs');
describe('raven.utils', function() {
describe('#construct_checksum()', function(){
it('should md5 hash the message', function(){
var kwargs = {
'foo': 'bar',
'message': 'This is awesome!'
};
raven.utils.construct_checksum(kwargs).should.equal('caf30724990022cfec2532741d6b631e');
});
});
describe('#get_signature()', function(){
it('should sign a key, timestamp, and message with md5 hash', function(){
raven.utils.get_signature('abc', 'This is awesome!', 1331932297938).should.equal('76cfb41aa49f91e5eb4ffbb1fe0c5b578459c537');
});
});
describe('#parseDSN()', function(){
it('should parse hosted Sentry DSN without path', function(){
var dsn = raven.utils.parseDSN('https://8769c40cf49c4cc58b51fa45d8e2d166:296768aa91084e17b5ac02d3ad5bc7e7@app.getsentry.com/269');
var expected = {
protocol: 'https',
public_key: '8769c40cf49c4cc58b51fa45d8e2d166',
private_key: '296768aa91084e17b5ac02d3ad5bc7e7',
host: 'app.getsentry.com',
path: '',
project_id: 269
};
dsn.should.eql(expected);
});
it('should parse http not on hosted Sentry with path', function(){
var dsn = raven.utils.parseDSN('http://8769c40cf49c4cc58b51fa45d8e2d166:296768aa91084e17b5ac02d3ad5bc7e7@mysentry.com/some/other/path/269');
var expected = {
protocol: 'http',
public_key: '8769c40cf49c4cc58b51fa45d8e2d166',
private_key: '296768aa91084e17b5ac02d3ad5bc7e7',
host: 'mysentry.com',
path: 'some/other/path',
project_id: 269
};
dsn.should.eql(expected);
});
describe('#parseStack()', function(){
var stack;
beforeEach(function(done){
fs.readFile(__dirname + '/fixtures/stack.txt', 'utf8', function(err, data){
stack = data;
done();
});
});
it('should not throw an error', function(done){
raven.utils.parseStack(stack, done);
});
it('should parse the correct number of frames', function(done){
raven.utils.parseStack(stack, function(err, frames){
frames.length.should.equal(10);
done();
});
});
it('should parse all frames correctly', function(done){
var expected = [{
'function': 'trace',
filename: './test/fixtures/stack.js',
lineno: 11,
pre_context: ['', 'function bar(a,b,c) {', ' var test=\'yay!\';', ' trace();', '}', '', 'function trace() {'],
context_line: ' console.log(__stack[1].fun.arguments);',
post_context: ['}', '', 'foo();', '']
}, {
'function': 'bar',
filename: './test/fixtures/stack.js',
lineno: 7,
pre_context: ['function foo() {', ' bar(\'hey\');', '}', '', 'function bar(a,b,c) {', ' var test=\'yay!\';'],
context_line: ' trace();',
post_context: ['}', '', 'function trace() {', ' console.log(__stack[1].fun.arguments);', '}', '', 'foo();']
}, {
'function': 'foo',
filename: './test/fixtures/stack.js',
lineno: 2,
pre_context: ['function foo() {'],
context_line: ' bar(\'hey\');',
post_context: ['}', '', 'function bar(a,b,c) {', ' var test=\'yay!\';', ' trace();', '}', '']
}, {
'function': 'Object.<anonymous>',
filename: './test/fixtures/stack.js',
lineno: 14,
pre_context: [' trace();', '}', '', 'function trace() {', ' console.log(__stack[1].fun.arguments);', '}', ''],
context_line: 'foo();',
post_context: ['']
}, {
'function': 'Module._compile',
filename: 'module.js',
lineno: 441
}, {
'function': 'Object..js',
filename: 'module.js',
lineno: 459
}, {
'function': 'Module.load',
filename: 'module.js',
lineno: 348
}, {
'function': 'Function._load',
filename: 'module.js',
lineno: 308
}, {
'function': 'Array.0',
filename: 'module.js',
lineno: 479
}, {
'function': 'EventEmitter._tickCallback',
filename: 'node.js',
lineno: 192
}];
raven.utils.parseStack(stack, function(err, frames){
frames.should.eql(expected);
done();
});
});
});
});
});
var connect = require('connect'),
raven = require('./');
var client = new raven.Client('https://952f70662d6546ebbfdd1ae4bf3ddc5a:de6343cb55ee40228ebcd808278ccc2d@app.getsentry.com/275');
//console.log(client.createFromText('Testing again!!!'));
client.patchGlobal();
function handle_request(req, res) {
throw new Error('broke2');
}
/*
connect(
connect.bodyParser(),
connect.cookieParser(),
function connect(req, res){
handle_request(req, res);
}, raven_middleware(client), function(err, req, res, next) {
res.statusCode = 500;
//console.log(res.sentry);
res.end(res.sentry+'\n');
}).listen(3000);
*/
//var connect = require('connect');
//var raven = require('raven');
//var client = new raven.Client('{{ SENTRY_DSN }}');
/*
function mainHandler(req, res) {
throw new Error('Broke!');
}
*/
function onError(err, req, res, next) {
// The error id is attached to `res.sentry` to be returned
// and optionally displayed to the user for support.
res.statusCode = 500;
res.end(res.sentry+'\n');
}
/*
connect(
connect.bodyParser(),
connect.cookieParser(),
mainHandler,
raven.middleware.express(client),
onError
).listen(3000);
*/
var app = require('express').createServer();
app.error(raven.middleware.express(client));
app.error(onError);
app.get('/', function mainHandler(req, res) {
throw new Error('Broke!');
});
app.listen(3000);
// testing the patch_global method
ffdasfsd.fdasfd;

Sorry, the diff of this file is not supported yet