Skip to content

Commit b3bc106

Browse files
committed
support logging "duck typed" Error objects
In TypeScript Error objects might be implemented instead of extended (i.e. HttpErrorResponse [1]). This causes the `instanceof` check in createItem to fail to recognize the argument as an error, and this change fixes that. [1]: https://github.com/angular/angular/blob/9a5ac47331faf0f6030bff75ad8ef8dab2f8d2d9/packages/common/http/src/response.ts#L319
1 parent cc0a5fa commit b3bc106

File tree

3 files changed

+39
-5
lines changed

3 files changed

+39
-5
lines changed

src/server/rollbar.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ Rollbar.prototype.errorHandler = function () {
280280
return next(err, request, response);
281281
}
282282

283-
if (err instanceof Error) {
283+
if (_.isError(err)) {
284284
return this.error(err, request, cb);
285285
}
286286
return this.error('Error: ' + err, request, cb);

src/utility.js

+6-4
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,10 @@ function isIterable(i) {
139139
* @returns true if e is an error
140140
*/
141141
function isError(e) {
142-
// Detect both Error and Firefox Exception type
143-
return isType(e, 'error') || isType(e, 'exception');
142+
// Detect Error, Firefox Exception type and error like object
143+
return (isType(e, 'error')
144+
|| isType(e, 'exception')
145+
|| (typeof e === 'object' && e && e.name && e.message));
144146
}
145147

146148
function redact() {
@@ -410,7 +412,7 @@ function createItem(args, logger, notifier, requestKeys, lambdaContext) {
410412
break;
411413
case 'object':
412414
case 'array':
413-
if (arg instanceof Error || (typeof DOMException !== 'undefined' && arg instanceof DOMException)) {
415+
if (isError(arg)) {
414416
err ? extraArgs.push(arg) : err = arg;
415417
break;
416418
}
@@ -428,7 +430,7 @@ function createItem(args, logger, notifier, requestKeys, lambdaContext) {
428430
custom ? extraArgs.push(arg) : custom = arg;
429431
break;
430432
default:
431-
if (arg instanceof Error || (typeof DOMException !== 'undefined' && arg instanceof DOMException)) {
433+
if (isError(arg)) {
432434
err ? extraArgs.push(arg) : err = arg;
433435
break;
434436
}

test/utility.test.js

+32
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,38 @@ describe('isError', function() {
244244
expect(_.isError(e)).to.be.ok();
245245
done();
246246
});
247+
it('should handle classes implementing the error interface', function(done) {
248+
// This is a mostly browser compliant way of doing this
249+
// just for the sake of doing it, even though we mostly
250+
// need this to work in node environments
251+
function TestCustomError(message) {
252+
Object.defineProperty(this, 'name', {
253+
enumerable: false,
254+
writable: false,
255+
value: 'TestCustomError'
256+
});
257+
258+
Object.defineProperty(this, 'message', {
259+
enumerable: false,
260+
writable: true,
261+
value: message
262+
});
263+
264+
if (Error.hasOwnProperty('captureStackTrace')) {
265+
Error.captureStackTrace(this, TestCustomError);
266+
} else {
267+
Object.defineProperty(this, 'stack', {
268+
enumerable: false,
269+
writable: false,
270+
value: (new Error(message)).stack
271+
});
272+
}
273+
}
274+
275+
var e = new TestCustomError('bork');
276+
expect(_.isError(e)).to.be.ok();
277+
done();
278+
});
247279
});
248280

249281
describe('merge', function() {

0 commit comments

Comments
 (0)