├── .gitignore ├── example └── demo.js ├── package.json ├── test ├── wickit.js └── exceptional-test.js ├── README.markdown └── lib └── exceptional.js /.gitignore: -------------------------------------------------------------------------------- 1 | DS_Store 2 | -------------------------------------------------------------------------------- /example/demo.js: -------------------------------------------------------------------------------- 1 | var Exceptional = require('../lib/exceptional').Exceptional; 2 | 3 | Exceptional.API_KEY = 'your-api-key-here'; 4 | 5 | process.addListener('uncaughtException', function(err) { 6 | Exceptional.handle(err); 7 | }); 8 | 9 | try { 10 | throw new Error("Test Error 1"); 11 | } catch(error) { 12 | console.log("Error occurred ", error.message); 13 | Exceptional.handle(error); 14 | } 15 | 16 | 17 | throw new Error("Test Error 2"); 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { "name" : "exceptional-node", 2 | "version" : "0.1.1", 3 | "description" : "node.js module for getexceptional.com", 4 | "homepage" : "http://getexceptional.com", 5 | "author" : "Wal McConnell ", 6 | "contributors" : [ 7 | "Wal McConnell " 8 | ], 9 | "repository" : { 10 | "type" : "git", 11 | "url" : "http://github.com/contrast/exceptional-node.git" 12 | }, 13 | "bugs" : { 14 | "web" : "http://github.com/contrast/exceptional-node/issues", 15 | "mail" : "support@getexceptional.com" 16 | }, 17 | "main" : "./lib/exceptional", 18 | "engines" : { "node" : ">=0.2.0" }, 19 | "scripts" : { "test" : "test/exceptional-test.js" }, 20 | "dependencies" : {}, 21 | "licenses" : [ 22 | { "type" : "MIT", 23 | "url" : "http://github.com/contrast/exceptional-node" 24 | } 25 | ] 26 | } 27 | 28 | -------------------------------------------------------------------------------- /test/wickit.js: -------------------------------------------------------------------------------- 1 | // http://github.com/wal/wickit 2 | 3 | var utils = require('utils'); 4 | var path = require('path'); 5 | 6 | Wick = { 7 | passed: 0, 8 | failed: 0, 9 | current_context: undefined, 10 | 11 | context: function(name, block) { 12 | utils.puts(""); 13 | utils.puts(path.basename(process.argv[1])); 14 | utils.puts("-"); 15 | Wick.current_context = name; 16 | block(); 17 | Wick.current_context = undefined; 18 | }, 19 | 20 | it: function(name, block){ 21 | if (Wick.current_context) { 22 | utils.print(Wick.current_context + " - "); 23 | } 24 | 25 | utils.print(" [ " + name + " ] \t"); 26 | 27 | try { 28 | block(); 29 | utils.puts("PASS"); 30 | Wick.passed += 1; 31 | } catch(error) { 32 | utils.puts("FAIL " + error.stack); 33 | Wick.failed += 1; 34 | } 35 | } 36 | }; 37 | 38 | exports.Wick = Wick; 39 | 40 | process.on('exit', function (code) { 41 | utils.puts("\n-------\n"); 42 | utils.puts("" + Wick.passed + " passed, " + Wick.failed + " failed"); 43 | utils.puts("\n\n"); 44 | }); 45 | 46 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | # Exceptional for node.js 2 | 3 | Exceptional helps you track errors in your node.js apps! 4 | 5 | This module posts exception data from your node.js apps to Exceptional . When an exception occurs, data about the environment and backtrace of the exception are sent. 6 | 7 | To use Exceptional for node.js you must have an account at . 8 | 9 | ## Installation 10 | 11 | Install from [NPM](http://npmjs.com): 12 | 13 | ```bash 14 | npm install exceptional-node 15 | ``` 16 | 17 | ```javascript 18 | var Exceptional = require('exceptional-node').Exceptional; 19 | 20 | Exceptional.API_KEY = **YOUR-API-KEY**; 21 | ``` 22 | 23 | Alternately, include the exceptional.js file in your application, and set your Exceptional API-KEY 24 | 25 | ```javascript 26 | var Exceptional = require('./exceptional').Exceptional; 27 | 28 | Exceptional.API_KEY = **YOUR-API-KEY**; 29 | ``` 30 | 31 | ## Usage 32 | 33 | There a are multiple ways you can use exceptional with your node.js app. 34 | 35 | * The process.uncaughtException event can be used to catch exceptions that bubble all the way up to the event loop. 36 | 37 | ```javascript 38 | process.addListener('uncaughtException', function(err) { 39 | Exceptional.handle(err); 40 | }); 41 | ``` 42 | 43 | * You can send exception data to exceptional from inside your own try/catch blocks 44 | 45 | ```javascript 46 | try { 47 | // Your Code 48 | } catch(error) { 49 | // Your own error processing 50 | Exceptional.handle(error); 51 | } 52 | ``` 53 | 54 | ## Example 55 | 56 | Check out the small example in examples/demo.js (replace 'your-api-key-here' with your read API-KEY). 57 | 58 | ```bash 59 | node example/demo.js 60 | ``` 61 | 62 | Copyright © 2008, 2010, 2012 getexceptional.com -------------------------------------------------------------------------------- /lib/exceptional.js: -------------------------------------------------------------------------------- 1 | var http = require('http'); 2 | var zlib = require('zlib'); 3 | 4 | var PROTOCOL_VERSION = 6; 5 | var VERSION = 1.0; 6 | 7 | var Exceptional = { 8 | apiKey: undefined, 9 | 10 | host: "api.getexceptional.com", 11 | port: 80, 12 | 13 | handle: function(error, callback) { 14 | if (this.apiKey === undefined) { 15 | if (callback) { 16 | callback(new Error("Exceptional API key must be set")); 17 | } 18 | return; 19 | } 20 | this.send(this.mapErrorToJSON(error), callback); 21 | }, 22 | 23 | mapErrorToJSON: function(error) { 24 | return JSON.stringify({ 25 | "application_environment": { 26 | "application_root_directory": process.cwd(), 27 | "language": "node-javascript", 28 | "framework": "node" + process.version, 29 | "env": { 30 | "args": process.argv, 31 | "execPath": process.execPath, 32 | "cwd": process.cwd(), 33 | "env": process.env, 34 | "gid": process.getgid(), 35 | "uid": process.getuid(), 36 | "version": process.version, 37 | "installPrefix": process.installPrefix, 38 | "pid": process.pid, 39 | "platform": process.platform, 40 | "memory": process.memoryUsage() 41 | } 42 | }, 43 | 44 | "exception": { 45 | "occurred_at": new Date(), 46 | "message": error.message, 47 | "backtrace": error.stack.split("\n"), 48 | "exception_class": error.name || "Error", 49 | }, 50 | "client": { 51 | "name": "Exceptional for node.js", 52 | "version": VERSION, 53 | "protocol_version": PROTOCOL_VERSION 54 | } 55 | }); 56 | }, 57 | 58 | send: function(doc, callback) { 59 | if (!Buffer.isBuffer(doc)) { 60 | doc = new Buffer(doc); 61 | } 62 | 63 | zlib.gzip(doc, function(err, data) { 64 | var options = { 65 | host: this.host, 66 | port: this.port, 67 | method: "POST", 68 | path: '/api/errors?api_key=' + this.apiKey + 69 | "&protocol_version=" + PROTOCOL_VERSION, 70 | headers: { 71 | 'Host' : this.host, 72 | 'Content-Length' : data.length, 73 | } 74 | } 75 | 76 | var request = http.request(options, function (response) { 77 | if (callback) { 78 | if (response.statusCode === 200) { 79 | callback(null); 80 | } else { 81 | callback(response.statusCode); 82 | } 83 | } 84 | }); 85 | 86 | request.write(data); 87 | request.end(); 88 | }.bind(this)); 89 | } 90 | }; 91 | 92 | module.exports = Exceptional; 93 | -------------------------------------------------------------------------------- /test/exceptional-test.js: -------------------------------------------------------------------------------- 1 | var Wick = require('./wickit').Wick; 2 | var Exceptional = require('../lib/exceptional').Exceptional; 3 | var assert = require('assert'); 4 | 5 | Wick.it("has default API_KEY undefined", function() { 6 | assert.equal(undefined, Exceptional.API_KEY); 7 | }); 8 | 9 | Wick.it("has default protocol version set", function() { 10 | assert.equal(6, Exceptional.PROTOCOL_VERSION); 11 | }); 12 | 13 | 14 | Wick.it("has default module version set", function() { 15 | assert.equal(1.0, Exceptional.VERSION); 16 | }); 17 | 18 | Wick.it("has default host set", function() { 19 | assert.equal('api.getexceptional.com', Exceptional.Host); 20 | }); 21 | 22 | Wick.it("has default port set", function() { 23 | assert.equal(80, Exceptional.Port); 24 | }); 25 | 26 | Wick.it('test set API key', function() { 27 | assert.equal(Exceptional.API_KEY, undefined); 28 | Exceptional.API_KEY = "test-api-key"; 29 | assert.equal(Exceptional.API_KEY, "test-api-key"); 30 | }); 31 | 32 | Wick.it('Exceptional.handle requires API_KEY to be set', function() { 33 | Exceptional.API_KEY = undefined; 34 | assert.throws(function() { 35 | Exceptional.handle("error"); 36 | }, "API_KEY must be set"); 37 | }); 38 | 39 | Wick.it('creates error JSON document with exception details', function() { 40 | Exceptional.API_KEY = 'test-api-key'; 41 | try { 42 | throw new Error("Big Problem"); 43 | } catch(error) { 44 | var doc = Exceptional.error_json(error); 45 | var json = JSON.parse(doc); 46 | 47 | assert.equal("Big Problem", json.exception.message); 48 | assert.equal("node", json.exception.exception_class); 49 | assert.equal(11, json.exception.backtrace.length); 50 | assert.ok(json.exception.occurred_at !== undefined); 51 | } 52 | }); 53 | 54 | Wick.it('creates error JSON document with client details', function() { 55 | Exceptional.API_KEY = 'test-api-key'; 56 | try { 57 | throw new Error("Big Problem"); 58 | } catch(error) { 59 | var doc = Exceptional.error_json(error); 60 | var json = JSON.parse(doc); 61 | 62 | assert.equal("Exceptional for node.js", json.client.name); 63 | assert.equal(1.0, json.client.version); 64 | assert.equal(6, json.client.protocol_version); 65 | } 66 | }); 67 | 68 | Wick.it('creates error JSON document with application environment set', function() { 69 | Exceptional.API_KEY = 'test-api-key'; 70 | try { 71 | throw new Error("Big Problem"); 72 | } catch(error) { 73 | var doc = Exceptional.error_json(error); 74 | var json = JSON.parse(doc); 75 | 76 | assert.equal("node-javascript", json.application_environment.language); 77 | assert.ok(json.application_environment.application_root_directory !== undefined); 78 | assert.ok(json.application_environment.framework !== undefined); 79 | assert.ok(json.application_environment.env !== undefined); 80 | } 81 | }); 82 | 83 | --------------------------------------------------------------------------------