@honeybadger-io/js 4.0.0-beta.0 → 4.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/honeybadger.js +89 -45
- package/dist/browser/honeybadger.js.map +1 -1
- package/dist/browser/honeybadger.min.js +1 -1
- package/dist/browser/honeybadger.min.js.map +1 -1
- package/dist/browser/types/core/client.d.ts +14 -2
- package/dist/browser/types/core/store.d.ts +7 -0
- package/dist/browser/types/core/types.d.ts +7 -0
- package/dist/browser/types/core/util.d.ts +1 -1
- package/dist/browser/types/server/async_store.d.ts +5 -0
- package/dist/browser/types/server.d.ts +1 -0
- package/dist/server/honeybadger.d.ts +1 -0
- package/dist/server/honeybadger.js +174 -133
- package/dist/server/types/core/client.d.ts +14 -2
- package/dist/server/types/core/store.d.ts +7 -0
- package/dist/server/types/core/types.d.ts +7 -0
- package/dist/server/types/core/util.d.ts +1 -1
- package/dist/server/types/server/async_store.d.ts +5 -0
- package/dist/server/types/server.d.ts +1 -0
- package/package.json +5 -4
- package/dist/browser/types/core/error.d.ts +0 -3
- package/dist/server/types/core/error.d.ts +0 -3
|
@@ -4,8 +4,8 @@ var https = require('https');
|
|
|
4
4
|
var http = require('http');
|
|
5
5
|
var url = require('url');
|
|
6
6
|
var os = require('os');
|
|
7
|
-
var fs = require('fs');
|
|
8
7
|
var domain = require('domain');
|
|
8
|
+
var fs = require('fs');
|
|
9
9
|
|
|
10
10
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
11
11
|
|
|
@@ -13,8 +13,8 @@ var https__default = /*#__PURE__*/_interopDefaultLegacy(https);
|
|
|
13
13
|
var http__default = /*#__PURE__*/_interopDefaultLegacy(http);
|
|
14
14
|
var url__default = /*#__PURE__*/_interopDefaultLegacy(url);
|
|
15
15
|
var os__default = /*#__PURE__*/_interopDefaultLegacy(os);
|
|
16
|
-
var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
|
|
17
16
|
var domain__default = /*#__PURE__*/_interopDefaultLegacy(domain);
|
|
17
|
+
var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
|
|
18
18
|
|
|
19
19
|
/*! *****************************************************************************
|
|
20
20
|
Copyright (c) Microsoft Corporation.
|
|
@@ -56,45 +56,7 @@ var __assign = function() {
|
|
|
56
56
|
return t;
|
|
57
57
|
};
|
|
58
58
|
return __assign.apply(this, arguments);
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
62
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
63
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
64
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
65
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
66
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
67
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function __generator(thisArg, body) {
|
|
72
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
73
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
74
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
75
|
-
function step(op) {
|
|
76
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
77
|
-
while (_) try {
|
|
78
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
79
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
80
|
-
switch (op[0]) {
|
|
81
|
-
case 0: case 1: t = op; break;
|
|
82
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
83
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
84
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
85
|
-
default:
|
|
86
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
87
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
88
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
89
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
90
|
-
if (t[2]) _.ops.pop();
|
|
91
|
-
_.trys.pop(); continue;
|
|
92
|
-
}
|
|
93
|
-
op = body.call(thisArg, _);
|
|
94
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
95
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
96
|
-
}
|
|
97
|
-
}
|
|
59
|
+
};
|
|
98
60
|
|
|
99
61
|
var UNKNOWN_FUNCTION = '<unknown>';
|
|
100
62
|
/**
|
|
@@ -307,7 +269,7 @@ function runBeforeNotifyHandlers(notice, handlers) {
|
|
|
307
269
|
}
|
|
308
270
|
function runAfterNotifyHandlers(notice, handlers, error) {
|
|
309
271
|
if (notice && notice.afterNotify) {
|
|
310
|
-
|
|
272
|
+
notice.afterNotify(error, notice);
|
|
311
273
|
}
|
|
312
274
|
for (var i = 0, len = handlers.length; i < len; i++) {
|
|
313
275
|
handlers[i](error, notice);
|
|
@@ -315,7 +277,7 @@ function runAfterNotifyHandlers(notice, handlers, error) {
|
|
|
315
277
|
return true;
|
|
316
278
|
}
|
|
317
279
|
// Returns a new object with properties from other object.
|
|
318
|
-
function
|
|
280
|
+
function shallowClone(obj) {
|
|
319
281
|
if (typeof (obj) !== 'object' || obj === null) {
|
|
320
282
|
return {};
|
|
321
283
|
}
|
|
@@ -342,8 +304,14 @@ function sanitize(obj, maxDepth) {
|
|
|
342
304
|
return false;
|
|
343
305
|
}
|
|
344
306
|
function canSerialize(obj) {
|
|
345
|
-
|
|
346
|
-
|
|
307
|
+
var typeOfObj = typeof obj;
|
|
308
|
+
// Functions are TMI
|
|
309
|
+
if (/function/.test(typeOfObj)) {
|
|
310
|
+
// Let special toJSON method pass as it's used by JSON.stringify (#722)
|
|
311
|
+
return obj.name === 'toJSON';
|
|
312
|
+
}
|
|
313
|
+
// Symbols can't convert to strings.
|
|
314
|
+
if (/symbol/.test(typeOfObj)) {
|
|
347
315
|
return false;
|
|
348
316
|
}
|
|
349
317
|
if (obj === null) {
|
|
@@ -370,7 +338,7 @@ function sanitize(obj, maxDepth) {
|
|
|
370
338
|
}
|
|
371
339
|
// Serialize inside arrays
|
|
372
340
|
if (Array.isArray(obj)) {
|
|
373
|
-
return obj.map(function (o) { return
|
|
341
|
+
return obj.map(function (o) { return safeSerialize(o, depth + 1); });
|
|
374
342
|
}
|
|
375
343
|
// Serialize inside objects
|
|
376
344
|
if (typeof (obj) === 'object') {
|
|
@@ -378,7 +346,7 @@ function sanitize(obj, maxDepth) {
|
|
|
378
346
|
for (var k in obj) {
|
|
379
347
|
var v = obj[k];
|
|
380
348
|
if (Object.prototype.hasOwnProperty.call(obj, k) && (k != null) && (v != null)) {
|
|
381
|
-
ret[k] =
|
|
349
|
+
ret[k] = safeSerialize(v, depth + 1);
|
|
382
350
|
}
|
|
383
351
|
}
|
|
384
352
|
return ret;
|
|
@@ -386,7 +354,16 @@ function sanitize(obj, maxDepth) {
|
|
|
386
354
|
// Return everything else untouched
|
|
387
355
|
return obj;
|
|
388
356
|
}
|
|
389
|
-
|
|
357
|
+
function safeSerialize(obj, depth) {
|
|
358
|
+
if (depth === void 0) { depth = 0; }
|
|
359
|
+
try {
|
|
360
|
+
return serialize(obj, depth);
|
|
361
|
+
}
|
|
362
|
+
catch (e) {
|
|
363
|
+
return "[ERROR] ".concat(e);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return safeSerialize(obj);
|
|
390
367
|
}
|
|
391
368
|
function logger(client) {
|
|
392
369
|
var log = function (method) {
|
|
@@ -425,12 +402,12 @@ function makeNotice(thing) {
|
|
|
425
402
|
if (!thing) {
|
|
426
403
|
notice = {};
|
|
427
404
|
}
|
|
428
|
-
else if (Object.prototype.toString.call(thing) === '[object Error]') {
|
|
405
|
+
else if (thing instanceof Error || Object.prototype.toString.call(thing) === '[object Error]') {
|
|
429
406
|
var e = thing;
|
|
430
407
|
notice = merge(thing, { name: e.name, message: e.message, stack: e.stack });
|
|
431
408
|
}
|
|
432
409
|
else if (typeof thing === 'object') {
|
|
433
|
-
notice =
|
|
410
|
+
notice = shallowClone(thing);
|
|
434
411
|
}
|
|
435
412
|
else {
|
|
436
413
|
var m = String(thing);
|
|
@@ -572,33 +549,44 @@ function getSourceCodeSnippet(fileData, lineNumber, sourceRadius) {
|
|
|
572
549
|
return result;
|
|
573
550
|
}
|
|
574
551
|
|
|
552
|
+
var GlobalStore$1 = /** @class */ (function () {
|
|
553
|
+
function GlobalStore(store) {
|
|
554
|
+
this.store = store;
|
|
555
|
+
}
|
|
556
|
+
GlobalStore.prototype.getStore = function () {
|
|
557
|
+
return this.store;
|
|
558
|
+
};
|
|
559
|
+
GlobalStore.prototype.run = function (store, callback) {
|
|
560
|
+
var args = [];
|
|
561
|
+
for (var _i = 2; _i < arguments.length; _i++) {
|
|
562
|
+
args[_i - 2] = arguments[_i];
|
|
563
|
+
}
|
|
564
|
+
this.store = store;
|
|
565
|
+
return callback.apply(void 0, args);
|
|
566
|
+
};
|
|
567
|
+
return GlobalStore;
|
|
568
|
+
}());
|
|
569
|
+
|
|
575
570
|
var notifier = {
|
|
576
571
|
name: 'honeybadger-js',
|
|
577
572
|
url: 'https://github.com/honeybadger-io/honeybadger-js',
|
|
578
|
-
version: '4.0.0-beta.
|
|
573
|
+
version: '4.0.0-beta.3'
|
|
579
574
|
};
|
|
580
|
-
// Split at commas
|
|
581
|
-
var TAG_SEPARATOR =
|
|
582
|
-
// Removes any non-word characters
|
|
583
|
-
var TAG_SANITIZER = /[^\w]/g;
|
|
584
|
-
// Checks for blank strings
|
|
585
|
-
var STRING_EMPTY = '';
|
|
575
|
+
// Split at commas and spaces
|
|
576
|
+
var TAG_SEPARATOR = /,|\s+/;
|
|
586
577
|
// Checks for non-blank characters
|
|
587
578
|
var NOT_BLANK = /\S/;
|
|
588
579
|
var Client = /** @class */ (function () {
|
|
589
580
|
function Client(opts) {
|
|
590
581
|
if (opts === void 0) { opts = {}; }
|
|
591
|
-
/** @internal */
|
|
592
582
|
this.__pluginsExecuted = false;
|
|
593
|
-
|
|
594
|
-
this.__context = {};
|
|
595
|
-
/** @internal */
|
|
596
|
-
this.__breadcrumbs = [];
|
|
597
|
-
/** @internal */
|
|
583
|
+
this.__store = null;
|
|
598
584
|
this.__beforeNotifyHandlers = [];
|
|
599
|
-
/** @internal */
|
|
600
585
|
this.__afterNotifyHandlers = [];
|
|
601
586
|
this.config = __assign({ apiKey: null, endpoint: 'https://api.honeybadger.io', environment: null, hostname: null, projectRoot: null, component: null, action: null, revision: null, reportData: null, breadcrumbsEnabled: true, maxBreadcrumbs: 40, maxObjectDepth: 8, logger: console, developmentEnvironments: ['dev', 'development', 'test'], debug: false, tags: null, enableUncaught: true, enableUnhandledRejection: true, afterUncaught: function () { return true; }, filters: ['creditcard', 'password'], __plugins: [] }, opts);
|
|
587
|
+
// First, we go with the global (shared) store.
|
|
588
|
+
// Webserver middleware can then switch to the AsyncStore for async context tracking.
|
|
589
|
+
this.__store = new GlobalStore$1({ context: {}, breadcrumbs: [] });
|
|
602
590
|
this.logger = logger(this);
|
|
603
591
|
}
|
|
604
592
|
Client.prototype.factory = function (_opts) {
|
|
@@ -619,6 +607,10 @@ var Client = /** @class */ (function () {
|
|
|
619
607
|
}
|
|
620
608
|
return this;
|
|
621
609
|
};
|
|
610
|
+
/** @internal */
|
|
611
|
+
Client.prototype.__setStore = function (store) {
|
|
612
|
+
this.__store = store;
|
|
613
|
+
};
|
|
622
614
|
Client.prototype.beforeNotify = function (handler) {
|
|
623
615
|
this.__beforeNotifyHandlers.push(handler);
|
|
624
616
|
return this;
|
|
@@ -629,23 +621,26 @@ var Client = /** @class */ (function () {
|
|
|
629
621
|
};
|
|
630
622
|
Client.prototype.setContext = function (context) {
|
|
631
623
|
if (typeof context === 'object') {
|
|
632
|
-
|
|
624
|
+
var store = this.__store.getStore();
|
|
625
|
+
store.context = merge(store.context, context);
|
|
633
626
|
}
|
|
634
627
|
return this;
|
|
635
628
|
};
|
|
636
629
|
Client.prototype.resetContext = function (context) {
|
|
637
630
|
this.logger.warn('Deprecation warning: `Honeybadger.resetContext()` has been deprecated; please use `Honeybadger.clear()` instead.');
|
|
631
|
+
var store = this.__store.getStore();
|
|
638
632
|
if (typeof context === 'object' && context !== null) {
|
|
639
|
-
|
|
633
|
+
store.context = context;
|
|
640
634
|
}
|
|
641
635
|
else {
|
|
642
|
-
|
|
636
|
+
store.context = {};
|
|
643
637
|
}
|
|
644
638
|
return this;
|
|
645
639
|
};
|
|
646
640
|
Client.prototype.clear = function () {
|
|
647
|
-
|
|
648
|
-
|
|
641
|
+
var store = this.__store.getStore();
|
|
642
|
+
store.context = {};
|
|
643
|
+
store.breadcrumbs = [];
|
|
649
644
|
return this;
|
|
650
645
|
};
|
|
651
646
|
Client.prototype.notify = function (noticeable, name, extra) {
|
|
@@ -687,10 +682,11 @@ var Client = /** @class */ (function () {
|
|
|
687
682
|
stack: notice.stack
|
|
688
683
|
}
|
|
689
684
|
});
|
|
690
|
-
|
|
685
|
+
var breadcrumbs = this.__getStoreContentsOrDefault().breadcrumbs;
|
|
686
|
+
notice.__breadcrumbs = this.config.breadcrumbsEnabled ? breadcrumbs.slice() : [];
|
|
691
687
|
// we need to have the source file data before the beforeNotifyHandlers,
|
|
692
688
|
// in case they modify them
|
|
693
|
-
var sourceCodeData = notice ? notice.backtrace.
|
|
689
|
+
var sourceCodeData = notice && notice.backtrace ? notice.backtrace.map(function (trace) { return shallowClone(trace); }) : null;
|
|
694
690
|
getSourceForBacktrace(sourceCodeData, this.__getSourceFileHandler, function (sourcePerTrace) {
|
|
695
691
|
sourcePerTrace.forEach(function (source, index) {
|
|
696
692
|
notice.backtrace[index].source = source;
|
|
@@ -761,15 +757,16 @@ var Client = /** @class */ (function () {
|
|
|
761
757
|
if (objectIsEmpty(notice)) {
|
|
762
758
|
return null;
|
|
763
759
|
}
|
|
760
|
+
var context = this.__getStoreContentsOrDefault().context;
|
|
764
761
|
var noticeTags = this.__constructTags(notice.tags);
|
|
765
|
-
var contextTags = this.__constructTags(
|
|
762
|
+
var contextTags = this.__constructTags(context["tags"]);
|
|
766
763
|
var configTags = this.__constructTags(this.config.tags);
|
|
767
764
|
// Turning into a Set will remove duplicates
|
|
768
765
|
var tags = noticeTags.concat(contextTags).concat(configTags);
|
|
769
766
|
var uniqueTags = tags.filter(function (item, index) { return tags.indexOf(item) === index; });
|
|
770
767
|
notice = merge(notice, {
|
|
771
768
|
name: notice.name || 'Error',
|
|
772
|
-
context: merge(
|
|
769
|
+
context: merge(context, notice.context),
|
|
773
770
|
projectRoot: notice.projectRoot || this.config.projectRoot,
|
|
774
771
|
environment: notice.environment || this.config.environment,
|
|
775
772
|
component: notice.component || this.config.component,
|
|
@@ -790,33 +787,33 @@ var Client = /** @class */ (function () {
|
|
|
790
787
|
return;
|
|
791
788
|
}
|
|
792
789
|
opts = opts || {};
|
|
793
|
-
var metadata =
|
|
790
|
+
var metadata = shallowClone(opts.metadata);
|
|
794
791
|
var category = opts.category || 'custom';
|
|
795
792
|
var timestamp = new Date().toISOString();
|
|
796
|
-
this.
|
|
793
|
+
var store = this.__store.getStore();
|
|
794
|
+
var breadcrumbs = store.breadcrumbs;
|
|
795
|
+
breadcrumbs.push({
|
|
797
796
|
category: category,
|
|
798
797
|
message: message,
|
|
799
798
|
metadata: metadata,
|
|
800
799
|
timestamp: timestamp
|
|
801
800
|
});
|
|
802
801
|
var limit = this.config.maxBreadcrumbs;
|
|
803
|
-
if (
|
|
804
|
-
|
|
802
|
+
if (breadcrumbs.length > limit) {
|
|
803
|
+
breadcrumbs = breadcrumbs.slice(breadcrumbs.length - limit);
|
|
805
804
|
}
|
|
805
|
+
store.breadcrumbs = breadcrumbs;
|
|
806
806
|
return this;
|
|
807
807
|
};
|
|
808
|
-
/** @internal */
|
|
809
808
|
Client.prototype.__developmentMode = function () {
|
|
810
809
|
if (this.config.reportData === true) {
|
|
811
810
|
return false;
|
|
812
811
|
}
|
|
813
812
|
return (this.config.environment && this.config.developmentEnvironments.includes(this.config.environment));
|
|
814
813
|
};
|
|
815
|
-
/** @internal */
|
|
816
814
|
Client.prototype.__send = function (_notice) {
|
|
817
815
|
throw (new Error('Must implement send in subclass'));
|
|
818
816
|
};
|
|
819
|
-
/** @internal */
|
|
820
817
|
Client.prototype.__buildPayload = function (notice) {
|
|
821
818
|
var headers = filter(notice.headers, this.config.filters) || {};
|
|
822
819
|
var cgiData = filter(__assign(__assign({}, notice.cgiData), formatCGIData(headers, 'HTTP_')), this.config.filters);
|
|
@@ -852,14 +849,22 @@ var Client = /** @class */ (function () {
|
|
|
852
849
|
details: notice.details || {}
|
|
853
850
|
};
|
|
854
851
|
};
|
|
855
|
-
/** @internal */
|
|
856
852
|
Client.prototype.__constructTags = function (tags) {
|
|
857
853
|
if (!tags) {
|
|
858
854
|
return [];
|
|
859
855
|
}
|
|
860
|
-
return tags.toString().split(TAG_SEPARATOR).
|
|
861
|
-
|
|
862
|
-
|
|
856
|
+
return tags.toString().split(TAG_SEPARATOR).filter(function (tag) { return NOT_BLANK.test(tag); });
|
|
857
|
+
};
|
|
858
|
+
/**
|
|
859
|
+
* For ALS, the store may be uninitialized (if .run()` has not been called).
|
|
860
|
+
* This provides an easy way to read the existing store object or fall back to a default.
|
|
861
|
+
* Returns *a copy* of the store contents.
|
|
862
|
+
* @internal
|
|
863
|
+
*/
|
|
864
|
+
Client.prototype.__getStoreContentsOrDefault = function () {
|
|
865
|
+
var existingStoreContents = this.__store.getStore();
|
|
866
|
+
var storeContents = existingStoreContents || {};
|
|
867
|
+
return __assign({ context: {}, breadcrumbs: [] }, storeContents);
|
|
863
868
|
};
|
|
864
869
|
return Client;
|
|
865
870
|
}());
|
|
@@ -920,55 +925,63 @@ function getSourceFile(path, cb) {
|
|
|
920
925
|
});
|
|
921
926
|
}
|
|
922
927
|
|
|
928
|
+
var Store;
|
|
929
|
+
try {
|
|
930
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
931
|
+
var AsyncLocalStorage = require('async_hooks').AsyncLocalStorage;
|
|
932
|
+
Store = new AsyncLocalStorage();
|
|
933
|
+
}
|
|
934
|
+
catch (e) {
|
|
935
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
936
|
+
var GlobalStore = require('../core/store').GlobalStore;
|
|
937
|
+
Store = new GlobalStore();
|
|
938
|
+
}
|
|
939
|
+
var AsyncStore = Store;
|
|
940
|
+
|
|
923
941
|
function isHandlerSync(handler) {
|
|
924
942
|
return handler.length > 2;
|
|
925
943
|
}
|
|
926
|
-
function
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
_a.trys.push([0, 2, , 3]);
|
|
934
|
-
return [4 /*yield*/, handler(event, context)];
|
|
935
|
-
case 1: return [2 /*return*/, _a.sent()];
|
|
936
|
-
case 2:
|
|
937
|
-
err_1 = _a.sent();
|
|
938
|
-
return [2 /*return*/, new Promise(function (_, reject) {
|
|
939
|
-
hb.notify(err_1, {
|
|
940
|
-
afterNotify: function () {
|
|
941
|
-
hb.clear();
|
|
942
|
-
reject(err_1);
|
|
943
|
-
}
|
|
944
|
-
});
|
|
945
|
-
})];
|
|
946
|
-
case 3: return [2 /*return*/];
|
|
947
|
-
}
|
|
948
|
-
});
|
|
949
|
-
}); };
|
|
944
|
+
function reportToHoneybadger(hb, err, callback) {
|
|
945
|
+
hb.notify(err, {
|
|
946
|
+
afterNotify: function () {
|
|
947
|
+
hb.clear();
|
|
948
|
+
callback(err);
|
|
949
|
+
}
|
|
950
|
+
});
|
|
950
951
|
}
|
|
951
|
-
function
|
|
952
|
-
return function (event, context
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
952
|
+
function asyncHandler(handler, hb) {
|
|
953
|
+
return function wrappedLambdaHandler(event, context) {
|
|
954
|
+
hb.__setStore(AsyncStore);
|
|
955
|
+
return new Promise(function (resolve, reject) {
|
|
956
|
+
AsyncStore.run({ context: {}, breadcrumbs: [] }, function () {
|
|
957
|
+
try {
|
|
958
|
+
handler(event, context)
|
|
959
|
+
.then(resolve)
|
|
960
|
+
.catch(function (err) { return reportToHoneybadger(hb, err, reject); });
|
|
958
961
|
}
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
try {
|
|
962
|
-
handler(event, context, function (error, result) {
|
|
963
|
-
if (error) {
|
|
964
|
-
return hbHandler(error);
|
|
962
|
+
catch (err) {
|
|
963
|
+
reportToHoneybadger(hb, err, reject);
|
|
965
964
|
}
|
|
966
|
-
cb(null, result);
|
|
967
965
|
});
|
|
968
|
-
}
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
966
|
+
});
|
|
967
|
+
};
|
|
968
|
+
}
|
|
969
|
+
function syncHandler(handler, hb) {
|
|
970
|
+
return function wrappedLambdaHandler(event, context, cb) {
|
|
971
|
+
hb.__setStore(AsyncStore);
|
|
972
|
+
AsyncStore.run({ context: {}, breadcrumbs: [] }, function () {
|
|
973
|
+
try {
|
|
974
|
+
handler(event, context, function (error, result) {
|
|
975
|
+
if (error) {
|
|
976
|
+
return reportToHoneybadger(hb, error, cb);
|
|
977
|
+
}
|
|
978
|
+
cb(null, result);
|
|
979
|
+
});
|
|
980
|
+
}
|
|
981
|
+
catch (err) {
|
|
982
|
+
reportToHoneybadger(hb, err, cb);
|
|
983
|
+
}
|
|
984
|
+
});
|
|
972
985
|
};
|
|
973
986
|
}
|
|
974
987
|
function lambdaHandler(handler) {
|
|
@@ -1065,10 +1078,7 @@ function fullUrl(req) {
|
|
|
1065
1078
|
});
|
|
1066
1079
|
}
|
|
1067
1080
|
function requestHandler(req, res, next) {
|
|
1068
|
-
this.
|
|
1069
|
-
var dom = domain__default["default"].create();
|
|
1070
|
-
dom.on('error', next);
|
|
1071
|
-
dom.run(next);
|
|
1081
|
+
this.withRequest(req, next, next);
|
|
1072
1082
|
}
|
|
1073
1083
|
function errorHandler(err, req, _res, next) {
|
|
1074
1084
|
this.notify(err, {
|
|
@@ -1081,9 +1091,12 @@ function errorHandler(err, req, _res, next) {
|
|
|
1081
1091
|
REQUEST_METHOD: req.method
|
|
1082
1092
|
}
|
|
1083
1093
|
});
|
|
1084
|
-
|
|
1094
|
+
if (next) {
|
|
1095
|
+
return next(err);
|
|
1096
|
+
}
|
|
1085
1097
|
}
|
|
1086
1098
|
|
|
1099
|
+
var kHoneybadgerStore = Symbol.for("kHoneybadgerStore");
|
|
1087
1100
|
var Honeybadger = /** @class */ (function (_super) {
|
|
1088
1101
|
__extends(Honeybadger, _super);
|
|
1089
1102
|
function Honeybadger(opts) {
|
|
@@ -1144,7 +1157,7 @@ var Honeybadger = /** @class */ (function (_super) {
|
|
|
1144
1157
|
runAfterNotifyHandlers(merge(notice, {
|
|
1145
1158
|
id: uuid
|
|
1146
1159
|
}), _this.__afterNotifyHandlers);
|
|
1147
|
-
_this.logger.info(
|
|
1160
|
+
_this.logger.info("Error report sent \u26A1 https://app.honeybadger.io/notice/".concat(uuid));
|
|
1148
1161
|
});
|
|
1149
1162
|
});
|
|
1150
1163
|
req.on('error', function (err) {
|
|
@@ -1155,13 +1168,41 @@ var Honeybadger = /** @class */ (function (_super) {
|
|
|
1155
1168
|
req.end();
|
|
1156
1169
|
});
|
|
1157
1170
|
};
|
|
1171
|
+
// This method is intended for web frameworks.
|
|
1172
|
+
// It allows us to track context for individual requests without leaking to other requests
|
|
1173
|
+
// by doing two things:
|
|
1174
|
+
// 1. Using AsyncLocalStorage so the context is tracked across async operations.
|
|
1175
|
+
// 2. Attaching the store contents to the request object,
|
|
1176
|
+
// so, even if the store is destroyed, we can still recover the context for a given request
|
|
1177
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1178
|
+
Honeybadger.prototype.withRequest = function (request, handler, onError) {
|
|
1179
|
+
var _this = this;
|
|
1180
|
+
var storeObject = (request[kHoneybadgerStore] || this.__getStoreContentsOrDefault());
|
|
1181
|
+
this.__setStore(AsyncStore);
|
|
1182
|
+
if (!request[kHoneybadgerStore]) {
|
|
1183
|
+
request[kHoneybadgerStore] = storeObject;
|
|
1184
|
+
}
|
|
1185
|
+
if (onError) {
|
|
1186
|
+
// ALS is fine for context-tracking, but `domain` allows us to catch errors
|
|
1187
|
+
// thrown asynchronously (timers, event emitters)
|
|
1188
|
+
// We can't use unhandledRejection/uncaughtException listeners; they're global and shared across all requests
|
|
1189
|
+
// But the `onError` handler might be request-specific.
|
|
1190
|
+
// Note that this doesn't still handle all cases. `domain` has its own problems:
|
|
1191
|
+
// See https://github.com/honeybadger-io/honeybadger-js/pull/711
|
|
1192
|
+
var dom = domain__default["default"].create();
|
|
1193
|
+
var onErrorWithContext = function (err) { return _this.__store.run(storeObject, function () { return onError(err); }); };
|
|
1194
|
+
dom.on('error', onErrorWithContext);
|
|
1195
|
+
handler = dom.bind(handler);
|
|
1196
|
+
}
|
|
1197
|
+
return this.__store.run(storeObject, handler);
|
|
1198
|
+
};
|
|
1158
1199
|
return Honeybadger;
|
|
1159
1200
|
}(Client));
|
|
1160
1201
|
var server = new Honeybadger({
|
|
1161
1202
|
__plugins: [
|
|
1162
1203
|
uncaughtException(),
|
|
1163
1204
|
unhandledRejection()
|
|
1164
|
-
]
|
|
1205
|
+
],
|
|
1165
1206
|
});
|
|
1166
1207
|
|
|
1167
1208
|
module.exports = server;
|
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
import { Config, Logger, BeforeNotifyHandler, AfterNotifyHandler, Notice, Noticeable } from './types';
|
|
1
|
+
import { Config, Logger, BeforeNotifyHandler, AfterNotifyHandler, Notice, Noticeable, HoneybadgerStore, BreadcrumbRecord } from './types';
|
|
2
2
|
export default class Client {
|
|
3
|
+
private __pluginsExecuted;
|
|
4
|
+
protected __store: HoneybadgerStore<{
|
|
5
|
+
context: Record<string, unknown>;
|
|
6
|
+
breadcrumbs: BreadcrumbRecord[];
|
|
7
|
+
}>;
|
|
8
|
+
protected __beforeNotifyHandlers: BeforeNotifyHandler[];
|
|
9
|
+
protected __afterNotifyHandlers: AfterNotifyHandler[];
|
|
10
|
+
protected __getSourceFileHandler: (path: string, cb: (fileContent: string) => void) => void;
|
|
3
11
|
config: Config;
|
|
4
12
|
logger: Logger;
|
|
5
13
|
constructor(opts?: Partial<Config>);
|
|
6
|
-
factory(_opts?:
|
|
14
|
+
factory(_opts?: Partial<Config>): Client;
|
|
7
15
|
getVersion(): string;
|
|
8
16
|
configure(opts?: Partial<Config>): Client;
|
|
9
17
|
beforeNotify(handler: BeforeNotifyHandler): Client;
|
|
@@ -21,4 +29,8 @@ export default class Client {
|
|
|
21
29
|
notifyAsync(noticeable: Noticeable, name?: string | Partial<Notice>, extra?: Partial<Notice>): Promise<void>;
|
|
22
30
|
protected makeNotice(noticeable: Noticeable, name?: string | Partial<Notice>, extra?: Partial<Notice>): Notice | null;
|
|
23
31
|
addBreadcrumb(message: string, opts?: Record<string, unknown>): Client;
|
|
32
|
+
protected __developmentMode(): boolean;
|
|
33
|
+
protected __send(_notice: Partial<Notice>): void;
|
|
34
|
+
protected __buildPayload(notice: Notice): Record<string, Record<string, unknown>>;
|
|
35
|
+
protected __constructTags(tags: unknown): Array<string>;
|
|
24
36
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { HoneybadgerStore } from "./types";
|
|
2
|
+
export declare class GlobalStore<T> implements HoneybadgerStore<T> {
|
|
3
|
+
private store;
|
|
4
|
+
constructor(store: T);
|
|
5
|
+
getStore(): T;
|
|
6
|
+
run<R, TArgs extends never[]>(store: T, callback: (...args: TArgs) => R, ...args: TArgs): R;
|
|
7
|
+
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
import Client from './client';
|
|
3
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
2
4
|
export interface Logger {
|
|
3
5
|
log(...args: unknown[]): unknown;
|
|
4
6
|
info(...args: unknown[]): unknown;
|
|
@@ -88,3 +90,8 @@ export interface CGIData {
|
|
|
88
90
|
HTTP_COOKIE: string | undefined;
|
|
89
91
|
[x: string]: unknown;
|
|
90
92
|
}
|
|
93
|
+
export declare type HoneybadgerStore<T> = Pick<AsyncLocalStorage<T>, 'getStore' | 'run'>;
|
|
94
|
+
export declare type DefaultStoreContents = {
|
|
95
|
+
context: Record<string, unknown>;
|
|
96
|
+
breadcrumbs: BreadcrumbRecord[];
|
|
97
|
+
};
|
|
@@ -8,7 +8,7 @@ export declare function makeBacktrace(stack: string, shift?: number): BacktraceF
|
|
|
8
8
|
export declare function getSourceForBacktrace(backtrace: BacktraceFrame[], getSourceFileHandler: (path: string, cb: (fileContent: string) => void) => void, cb: (sourcePerTrace: Record<string, string>[]) => void): void;
|
|
9
9
|
export declare function runBeforeNotifyHandlers(notice: Notice | null, handlers: BeforeNotifyHandler[]): boolean;
|
|
10
10
|
export declare function runAfterNotifyHandlers(notice: Notice | null, handlers: AfterNotifyHandler[], error?: Error): boolean;
|
|
11
|
-
export declare function
|
|
11
|
+
export declare function shallowClone<T>(obj: T): T | Record<string, unknown>;
|
|
12
12
|
export declare function sanitize(obj: any, maxDepth?: number): any;
|
|
13
13
|
export declare function logger(client: Client): Logger;
|
|
14
14
|
/**
|
|
@@ -8,6 +8,7 @@ declare class Honeybadger extends Client {
|
|
|
8
8
|
lambdaHandler: typeof lambdaHandler;
|
|
9
9
|
constructor(opts?: Partial<Config>);
|
|
10
10
|
factory(opts?: Partial<Config>): Honeybadger;
|
|
11
|
+
withRequest<R>(request: Record<symbol, unknown>, handler: (...args: never[]) => R, onError?: (...args: any[]) => any): R | void;
|
|
11
12
|
}
|
|
12
13
|
declare const _default: Honeybadger;
|
|
13
14
|
export default _default;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@honeybadger-io/js",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"homepage": "https://github.com/honeybadger-io/honeybadger-js",
|
|
6
6
|
"author": {
|
|
@@ -46,11 +46,12 @@
|
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@rollup/plugin-node-resolve": "^13.0.6",
|
|
49
|
-
"@rollup/plugin-replace": "^
|
|
49
|
+
"@rollup/plugin-replace": "^4.0.0",
|
|
50
50
|
"@rollup/plugin-typescript": "^8.3.0",
|
|
51
51
|
"@types/aws-lambda": "^8.10.89",
|
|
52
52
|
"@types/express": "^4.17.13",
|
|
53
53
|
"@types/jest": "^27.0.3",
|
|
54
|
+
"@types/node": "^12.20.46",
|
|
54
55
|
"@typescript-eslint/eslint-plugin": "^5.6.0",
|
|
55
56
|
"@typescript-eslint/parser": "^5.6.0",
|
|
56
57
|
"axios": ">=0.24.0",
|
|
@@ -64,11 +65,11 @@
|
|
|
64
65
|
"nock": "^13.2.1",
|
|
65
66
|
"rollup": "^2.61.1",
|
|
66
67
|
"rollup-plugin-uglify": "^6.0.2",
|
|
67
|
-
"shipjs": "0.24.
|
|
68
|
+
"shipjs": "0.24.3",
|
|
68
69
|
"sinon": "^13.0.1",
|
|
69
70
|
"supertest": "^6.1.6",
|
|
70
71
|
"ts-jest": "^27.1.1",
|
|
71
|
-
"tsd": "^0.
|
|
72
|
+
"tsd": "^0.20.0",
|
|
72
73
|
"tslib": "^2.3.1",
|
|
73
74
|
"typescript": "^4.5.3"
|
|
74
75
|
},
|