Comparing version 1.4.2 to 2.0.0
179
index.js
'use strict'; | ||
var envIs = require('101/env-is'); | ||
var exists = require('101/exists'); | ||
var isFunction = require('101/is-function'); | ||
var rollbar = require('rollbar'); | ||
var autoDebug = require('auto-debug'); | ||
var Boom = require('boom'); | ||
var ErrorCat = require('./error-cat'); | ||
/** | ||
* A friendly feline companion that helps you create, track, and report errors. | ||
* Default ErrorCat instance. | ||
* @module error-cat | ||
* @author Ryan Sandor Richards | ||
*/ | ||
module.exports = ErrorCat; | ||
/** | ||
* Creates a new ErrorCat and initializes rollbar if available. | ||
* @class | ||
*/ | ||
function ErrorCat () { | ||
if (this.canUseRollbar()) { | ||
rollbar.init(process.env.ROLLBAR_KEY, { | ||
environment: process.env.NODE_ENV, | ||
branch: process.env.ROLLBAR_OPTIONS_BRANCH, | ||
codeVersion: process.env._VERSION_GIT_COMMIT, | ||
root: process.env.ROOT_DIR | ||
}); | ||
} | ||
this.debug = autoDebug(); | ||
} | ||
/** | ||
* Determines if the application is using rollbar. Specifically it checks to see | ||
* if `process.env.ROLLBAR_KEY` is defined, and that the application is not | ||
* executing under a test environment (i.e. `process.env.NODE_ENV !== 'test'`). | ||
* @return {Boolean} `true` If ErrorCat should use rollbar, `false` otherwise. | ||
*/ | ||
ErrorCat.prototype.canUseRollbar = function () { | ||
return exists(process.env.ROLLBAR_KEY) && !envIs('test'); | ||
}; | ||
/** | ||
* Factory method that creates and logs new boom errors. | ||
* Does NOT report errors - use createAndReport | ||
* @param {Number} code HTTP error code for the error | ||
* @param {string} message Message describing the error. | ||
* @param {mixed} data Additional data for the error. | ||
* @return {Error} The error object as specified by the parameters. | ||
*/ | ||
ErrorCat.prototype.create = function (code, message, data) { | ||
var err = Boom.create(code, message, data); | ||
this.log(err); | ||
return err; | ||
}; | ||
/** | ||
* Factory method to create AND report boom errors. | ||
* Logs with debug AND reports error to rollbar (if able) | ||
* @param {Number} code HTTP error code for the error | ||
* @param {string} message Message describing the error. | ||
* @param {mixed} data Additional data for the error. | ||
* @param [Function] cb Optional callback with sigature (err, generatedError). | ||
* @return {Error} The error object as specified by the parameters. | ||
*/ | ||
ErrorCat.prototype.createAndReport = function (code, message, data, cb) { | ||
var generatedError = this.create(code, message, data); // calls this.log | ||
if (isFunction(cb)) { | ||
this.report(generatedError, function (reportingError) { | ||
cb(reportingError, generatedError); | ||
}); | ||
} else { | ||
this.report(generatedError); | ||
return generatedError; | ||
} | ||
}; | ||
/** | ||
* Wraps an error as a boom error and logs it. | ||
* @param {Error} err Error to wrap. | ||
* @param {Number} code HTTP Response code for the boom error. | ||
* @param {String} message Additional message for the error. | ||
* @return {Error} The boom error that wraps the given error. | ||
*/ | ||
ErrorCat.prototype.wrap = function (err, code, message) { | ||
var boomError = Boom.wrap(err, code, message); | ||
this.log(boomError); | ||
return boomError; | ||
}; | ||
/** | ||
* Wraps an error as a boom error and reports it via rollbar. | ||
* @param {Error} err Error to wrap. | ||
* @param {Number} code HTTP Response code for the boom error. | ||
* @param {String} message Additional message for the error. | ||
* @return {Error} The boom error that wraps the given error. | ||
*/ | ||
ErrorCat.prototype.wrapAndReport = function (err, code, message) { | ||
var boomError = this.wrap(err, code, message); | ||
this.report(boomError); | ||
return boomError; | ||
}; | ||
/** | ||
* Responder that sends error information along with a 500 status code. | ||
* @param {Error} err Error to use for the response. | ||
* @param {boolean} err.isBoom Indicates whether or not `err` is a boom error. | ||
* @param {Number} err.output.statusCode Overrides the status code for the | ||
* response (only used if `err.isBoom` property is true). | ||
* @param {object} err.output.payload Overrides the default | ||
* @param {object} res The response object. | ||
*/ | ||
/* jslint unused:false */ | ||
ErrorCat.prototype.respond = function (err, req, res, next) { | ||
res.writeHead( | ||
err.isBoom ? err.output.statusCode : 500, | ||
{'Content-Type': 'application/json'} | ||
); | ||
res.end(JSON.stringify( | ||
err.isBoom ? err.output.payload : 'Internal Server Error' | ||
)); | ||
}; | ||
/* jslint unused:true */ | ||
/** | ||
* Logs errors via debug | ||
* @param {Error} err The error to log. | ||
*/ | ||
ErrorCat.prototype.log = function (err) { | ||
this.debug(err); | ||
}; | ||
/** | ||
* Reports errors to rollbar. Note this method is automatically bypassed in test | ||
* environments (i.e. `process.env.NODE_ENV === 'test'`). | ||
* @param {Error} err The error to report. | ||
* @param {object} [req] optional request to report. | ||
* @param {object} [cb] optional cb after reporting. | ||
*/ | ||
ErrorCat.prototype.report = function (err, req, cb) { | ||
if (!exists(err) || err.report === false || !this.canUseRollbar()) { | ||
return; | ||
} | ||
if (isFunction(req)) { | ||
cb = req; | ||
req = null; | ||
} | ||
// rollbar.handleErrorWithPayloadData usage: | ||
// https://github.com/rollbar/node_rollbar/blob/a03b3a6e6e0a2734e2657cbf41e21927003f505d/lib/notifier.js#L359 | ||
var payload = { | ||
level: err.level || 'error', | ||
custom: err.data || {} | ||
}; | ||
rollbar.handleErrorWithPayloadData(err, payload, req, cb); | ||
}; | ||
/** | ||
* Maps exposed function names to default instance method names. | ||
* @type {object} | ||
*/ | ||
var defaultMethods = { | ||
'middleware': 'respond', | ||
'create': 'create', | ||
'log': 'log', | ||
'report': 'report' | ||
}; | ||
/** | ||
* Default instance used for module level functions. | ||
* @type {ErrorCat} | ||
*/ | ||
var instance = new ErrorCat(); | ||
// Expose module functions by adding immutable static methods to ErrorCat | ||
Object.keys(defaultMethods).forEach(function (name) { | ||
Object.defineProperty(ErrorCat, name, { | ||
value: instance[defaultMethods[name]].bind(instance), | ||
writable: envIs('test'), // bc tests like to spy on things | ||
enumerable: true | ||
}); | ||
}); | ||
module.exports = new ErrorCat(); |
{ | ||
"name": "error-cat", | ||
"version": "1.4.2", | ||
"version": "2.0.0", | ||
"description": "A friendly feline companion that helps you create, track, and report errors.", | ||
@@ -10,4 +10,6 @@ "main": "index.js", | ||
"scripts": { | ||
"build": "babel --out-dir . lib", | ||
"prepublish": "not-in-install && npm run build || in-install", | ||
"doc": "jsdoc index.js -d doc/; open -a 'Google Chrome' doc/index.html", | ||
"lint": "jshint index.js", | ||
"lint": "standard --verbose", | ||
"unit": "lab -v -c -a code", | ||
@@ -38,13 +40,19 @@ "test": "npm run lint && npm run unit" | ||
"101": "^0.18.0", | ||
"auto-debug": "^1.0.1", | ||
"array-find": "^1.0.0", | ||
"boom": "^2.7.1", | ||
"es6-error": "^2.1.0", | ||
"in-publish": "^2.0.0", | ||
"rollbar": "^0.5.3" | ||
}, | ||
"devDependencies": { | ||
"babel-cli": "^6.5.1", | ||
"babel-eslint": "^5.0.0", | ||
"babel-preset-es2015": "^6.5.0", | ||
"babel-register": "^6.5.2", | ||
"code": "^1.4.0", | ||
"jsdoc": "^3.3.0-beta3", | ||
"jshint": "^2.7.0", | ||
"lab": "^5.8.0", | ||
"sinon": "^1.14.1" | ||
"sinon": "^1.14.1", | ||
"standard": "^6.0.8" | ||
} | ||
} |
241
README.md
@@ -7,19 +7,18 @@ # error-cat | ||
A friendly feline companion that helps you create errors, track them, and report them via rollbar. | ||
A friendly feline companion that helps you build error heirarchies and report | ||
application errors to rollbar. | ||
## Basic usage | ||
```js | ||
var ErrorCat = require('error-cat'); | ||
// Import the library. Uses the environment's `ROLLBAR_KEY` to automatically | ||
// setup rollbar reporting. | ||
const cat = require('error-cat') | ||
// Create and Log Errors (does not send to external service) | ||
var err = ErrorCat.create(404, 'Not Found'); | ||
// Fire-and-forget error reporting | ||
cat.report(new Error('Something bad')) | ||
// Create, Log, and Report Errors (i.e., also sends to Rollbar) | ||
var teapot = ErrorCat.createAndReport(418, 'I am a Teapot'); | ||
// Log Errors (to stdout/stderr, e.g. w/ `auto-debug`) | ||
ErrorCat.log(someError); | ||
// Report Errors via Rollbar | ||
ErrorCat.report(anotherError, req); | ||
// Optionally, pass a callback to execute once the error has been reported | ||
cat.report(new Error('No good'), function () { | ||
// ... | ||
}) | ||
``` | ||
@@ -32,123 +31,161 @@ | ||
```js | ||
var express = require('express'); | ||
var app = express() | ||
const express = require('express') | ||
const app = express() | ||
// 1. Require error-cat | ||
var ErrorCat = require('error-cat'); | ||
const cat = require('error-cat') | ||
// 2. Log and report errors using the static responder method | ||
app.use(ErrorCat.middleware); | ||
app.use(cat.middleware) | ||
``` | ||
## Extending error-cat | ||
Error cat was designed as a prototypal class, so you can easily extend it using | ||
pure javascript: | ||
## Using error-cat in promise-based applications | ||
Error cat exposes a *pass-through* promise catch handler that will automatically | ||
report and then re-throw errors in a promise chain. Here's how to use it: | ||
```js | ||
var util = require('util'); | ||
var ErrorCat = require('error-cat'); | ||
Promise | ||
.try(something) | ||
.then(somethingElse) | ||
.catch(cat.catch) | ||
.catch(function (err) { | ||
// You'll still need this since `ErrorCat.catch` re-throws the error... | ||
}) | ||
``` | ||
// | ||
// 1. Define your own ErrorCat class | ||
// | ||
function MyErrorCat() { | ||
ErrorCat.apply(this, arguments); | ||
## Core Error Classes | ||
Error-cat exposes a set of extendable error classes that are specifically | ||
suited to work with the main library. Application programmers can use these | ||
classes to build their own error hierarchies that allow for higher level | ||
error handling and management. | ||
These error classes are very well suited for Promise based applications (for | ||
use with `.catch`) and `try-catch` based synchronous applications. | ||
In this section we will show you how to use the provided core error classes and | ||
extend them to create your own error zoology. | ||
#### Extending Error Classes | ||
Each of the error types, detailed below, can be extended for your own application. | ||
Building a robust error zoology is key in correctly implmenting a `try-catch` based | ||
error handling strategy in your application. | ||
Error-cat makes this easy, here's an example of how you can extend the core | ||
base error class to automatically increment an error counter in data-dog (via | ||
[monitor-dog](https://github.com/runnable/monitor-dog)) during construction: | ||
```js | ||
'use strict' | ||
const BaseError = require('error-cat/errors/base-error') | ||
const monitor = require('monitor-dog') | ||
/** | ||
* Base class for all errors that should be monitored in data-dog. | ||
* @param {[type]} message Message for the error. | ||
* @param {[type]} data Custom data to report to rollbar. | ||
*/ | ||
class MonitoredError extends BaseError { | ||
constructor (message, data, reporting) { | ||
super(message, data, reporting) | ||
monitor.increment('errors') | ||
} | ||
} | ||
util.inherits(MyErrorCat, ErrorCat); | ||
MyErrorCat.prototype.respond = function (err, req, res) { | ||
// Custom middleware... | ||
}; | ||
/** | ||
* Monitored Error Class | ||
* @module my-application:error | ||
*/ | ||
module.exports = MonitoredError | ||
``` | ||
MyErrorCat.prototype.report = function (err, req, res) { | ||
// Perhaps you want to report errors to more than just rollbar? | ||
}; | ||
#### class `BaseError(message, data, reporting)` extends `Error` | ||
At the top of the core error hierarchy is `BaseError`. This class provides the | ||
following: | ||
1. An easy-to-use and extendable error class for application programmers | ||
2. Allow for meaningful "extra data" | ||
3. A method of defining how an error should be reported | ||
// | ||
// 2. Use an instance with an application | ||
// | ||
var express = require('express'); | ||
var app = express(); | ||
var error = new MyErrorCat(); | ||
app.use(error.respond); | ||
Here's an example that shows everything the base error has to offer: | ||
```js | ||
const BaseError = require('error-cat/errors/base-error') | ||
// Use it as a normal error... | ||
new BaseError('a message') | ||
// Pass data that should be reported in the constructor... | ||
new BaseError('message', { myData: 123 }) | ||
// Pass reporting information on how it should be reported... | ||
new BaseError('message', {}, { | ||
level: 'critical', // the reporting level | ||
fingerprint: 'mygroup' // a grouping fingerprint | ||
}) | ||
``` | ||
## API | ||
The `error-cat` module exposes a single class named `ErrorCat`. Below is a | ||
complete listing of its methods. | ||
#### class `Warning(message, data, reporting)` extends `BaseError` | ||
Used to denote an exceptional case that isn't as serious as an error. By default | ||
these types of errors are not reported. | ||
#### ErrorCat.middleware(err, req, res, next) | ||
An express middleware that can be used to handle error responses with | ||
`error-cat` (uses the method `respond` detailed in the next section). | ||
#### class `RouteError(message, statusCode, data, reporting)` extends `BaseError` | ||
Used to denote exceptions that arise during the handling of RESTful routes. | ||
The class is automatically annotated with additional metadata via the | ||
[boom](https://github.com/hapijs/boom) library. | ||
Note, this static method is set as `writable: false`, and will throw an error | ||
if you attempt to assign it a different value. If you need to change the default | ||
behavior please see the `Extending error-cat` section above. | ||
#### class `WorkerError(message, data, reporting, queue, job)` extends `BaseError` | ||
This error class is specifically setup for use in worker servers. It serves as the | ||
root error for the [ponos](https://github.com/runnable/ponos) worker server library. | ||
It specifically sets information about the queue name and the job being processed | ||
when the error occured. | ||
### ErrorCat Methods | ||
Furthermore it exposes two methods that are used by external worker server libraries | ||
for automatically setting this data when task handlers for workers throw this type | ||
of error: | ||
#### {ErrorCat} `new ErrorCat()` | ||
Constructs a new `ErrorCat` instance and initializes Rollbar if it is available. | ||
- (void) `setQueue(name)` - Sets the queue name data | ||
- (void) `setJob(job)` - Sets the job data | ||
#### {boolean} `canUseRollbar()` | ||
Determines whether or not ErrorCat can use Rollbar to report errors. This method | ||
will return `true` if, and only if, `process.env.NODE_ENV !== 'test'` and | ||
`process.env.ROLLBAR_KEY` is defined. | ||
#### class `WorkerStopError(message, data, reporting, queue, job)` extends `WorkerError` | ||
Error class that is designed to be thrown when a worker server task handler | ||
encounters a scenario where it cannot possibly proceed with the processing of | ||
the given job. Worker server implementations should automatically acknowledge the | ||
job (even though it was not completed) when encountering this type of error. | ||
Note: Error cat uses the [loadenv](http://www.npmjs.com/package/loadenv) package | ||
to load the environment so feel free to use its conventions to define | ||
`ROLLBAR_KEY`. | ||
#### class `InvalidJobError(message, data, reporting, queue, job)` extends `WorkerStopError` | ||
An error class designed to be thrown when a worker server task handler encounters | ||
a malformed or invalid job. | ||
#### {Boom~Error} `create(code, message, data)` | ||
Creates and automatically logs a new [boom](https://www.npmjs.com/package/boom) | ||
via the `ErrorCat.log` method (see below). The parameters mirror `Boom.create`. | ||
#### {Boom~Error} `createAndReport(code, message, data)` | ||
Creates a new [boom](https://www.npmjs.com/package/boom) error, logs it via the | ||
`ErrorCat.log` method (see below), and reports it to rollbar via the | ||
`ErrorCat.report` method (see below). | ||
## Reporters | ||
By default ErrorCat reports errors to rollbar. In order to support other services | ||
the library exposes an `AbstractReporter` class that can be extended as needed. | ||
The only method that is "required" to define in a subclass is `.report`, but the | ||
class has many other methods that can be easily overriden. | ||
#### {Boom~Error} `wrap(err, code, message)` | ||
Creates a new [boom](https://www.npmjs.com/package/boom) error from an existing | ||
error, and logs it via the `ErrorCat.log` method (see below). Data can be | ||
supplied to the resulting boom error by setting the `.data` attribute on the | ||
error before wrapping it. Here's an example: | ||
A full treatment of building a custom reporter is outside the scope of this document. | ||
We advise that you simply read the `lib/abstract-reporter.js` class file thoroughly | ||
(it is fairly short) to get an understanding how to do so. | ||
For usage reference here is an example of how to implement a custom reporter: | ||
```js | ||
var reqBody = 'Information that may cause request to fail.'; | ||
var options = { | ||
url: 'http://api.service.com/route', | ||
body: reqBody | ||
}; | ||
const AbstractReporter = require('error-cat/abstract-reporter') | ||
const ErrorCat = require('error-cat/error-cat') | ||
const noop = require('101/noop') | ||
// Send an http request to an external service... | ||
request.post(options, function (err) { | ||
if (err) { | ||
// Add some data about the state that caused the error | ||
err.data = { body: reqBody }; | ||
// 1) Define the reporter... | ||
class ConsoleReporter extends AbstractReporter { | ||
report (err, cb) { | ||
if (!this.shouldReport(err)) { | ||
return (cb || noop)() | ||
} | ||
console.error(this.getLevel(err), err.message) | ||
} | ||
} | ||
// And then wrap the error so it can be logged appropriately | ||
ErrorCat.wrap(err, 502); | ||
} | ||
}); | ||
// 2) Use it with a custom error-cat instance | ||
const cat = new ErrorCat(new ConsoleReporter('warn')) | ||
``` | ||
#### {Boom~Error} `wrapAndReport(err, code, message)` | ||
Creates a new [boom](https://www.npmjs.com/package/boom) error from an existing | ||
error, and logs it via the `ErrorCat.log` method (see below), and reports it to | ||
rollbar via the `ErrorCat.report` method (see blow). Note: as with `wrap` above | ||
data can be supplied to the resulting boom error by setting the `.data` | ||
attribute on the error before wrapping it. | ||
#### {void} `log(err)` | ||
Logs the given error using [auto-debug](https://www.npmjs.com/package/auto-debug) | ||
and reports it to rollbar via `ErrorCat.report` (see below). | ||
#### {void} `report(err, [req], [cb])` | ||
Reports the given error via Rollbar. This method is automatically bypassed if | ||
`ErrorCat.canUseRollbar()` returns false (see above). | ||
optional req argument to add more data | ||
optional cb which is called after reporting | ||
## Contributing | ||
@@ -155,0 +192,0 @@ If you wish to contribute to `error-cat` please adhere to the following rules: |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
38819
14
628
200
6
6
9
1
+ Addedarray-find@^1.0.0
+ Addedes6-error@^2.1.0
+ Addedin-publish@^2.0.0
+ Addedarray-find@1.0.0(transitive)
+ Addedes6-error@2.1.1(transitive)
+ Addedin-publish@2.0.1(transitive)
- Removedauto-debug@^1.0.1
- Removed101@0.14.1(transitive)
- Removedauto-debug@1.0.2(transitive)
- Removedcallsite@1.0.0(transitive)
- Removeddebug@2.6.9(transitive)
- Removedms@2.0.0(transitive)