@honeybadger-io/js 6.15.3 → 6.16.1
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.ext.min.js +1 -1
- package/dist/browser/honeybadger.ext.min.js.map +1 -1
- package/dist/browser/honeybadger.js +464 -84
- 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/server/async_store.d.ts +2 -0
- package/dist/server/fastify.d.ts +31 -0
- package/dist/server/fastify.js +2228 -0
- package/dist/server/fastify.js.map +1 -0
- package/dist/server/honeybadger.js +819 -109
- package/dist/server/honeybadger.js.map +1 -1
- package/dist/server/instrumentation/http_event.d.ts +51 -0
- package/dist/server/integrations/shutdown_monitor.d.ts +2 -0
- package/dist/server/stacked_store.d.ts +2 -0
- package/package.json +17 -3
|
@@ -5,7 +5,8 @@ var require$$1$1 = require('domain');
|
|
|
5
5
|
var require$$1 = require('fs');
|
|
6
6
|
var require$$2 = require('path');
|
|
7
7
|
var require$$3 = require('util');
|
|
8
|
-
var require$$0$3 = require('
|
|
8
|
+
var require$$0$3 = require('crypto');
|
|
9
|
+
var require$$0$4 = require('url');
|
|
9
10
|
var require$$3$1 = require('http');
|
|
10
11
|
var require$$4 = require('https');
|
|
11
12
|
|
|
@@ -17,6 +18,7 @@ var require$$1__default = /*#__PURE__*/_interopDefaultLegacy(require$$1);
|
|
|
17
18
|
var require$$2__default = /*#__PURE__*/_interopDefaultLegacy(require$$2);
|
|
18
19
|
var require$$3__default = /*#__PURE__*/_interopDefaultLegacy(require$$3);
|
|
19
20
|
var require$$0__default$1 = /*#__PURE__*/_interopDefaultLegacy(require$$0$3);
|
|
21
|
+
var require$$0__default$2 = /*#__PURE__*/_interopDefaultLegacy(require$$0$4);
|
|
20
22
|
var require$$3__default$1 = /*#__PURE__*/_interopDefaultLegacy(require$$3$1);
|
|
21
23
|
var require$$4__default = /*#__PURE__*/_interopDefaultLegacy(require$$4);
|
|
22
24
|
|
|
@@ -51,7 +53,7 @@ var server$1 = {};
|
|
|
51
53
|
|
|
52
54
|
var src = {};
|
|
53
55
|
|
|
54
|
-
var
|
|
56
|
+
var console_events = {};
|
|
55
57
|
|
|
56
58
|
var util$1 = {};
|
|
57
59
|
|
|
@@ -258,7 +260,7 @@ var require$$0$1 = /*@__PURE__*/getAugmentedNamespace(stackTraceParser_esm);
|
|
|
258
260
|
}
|
|
259
261
|
};
|
|
260
262
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
261
|
-
exports.logDeprecatedMethod = exports.globalThisOrWindow = exports.isBrowserConfig = exports.clone = exports.formatCGIData = exports.filterUrl = exports.filter = exports.generateStackTrace = exports.endpoint = exports.instrumentConsole = exports.instrument = exports.isErrorObject = exports.makeNotice = exports.logger = exports.sanitize = exports.shallowClone = exports.runAfterNotifyHandlers = exports.runBeforeNotifyHandlers = exports.getSourceForBacktrace = exports.getCauses = exports.calculateBacktraceShift = exports.DEFAULT_BACKTRACE_SHIFT = exports.makeBacktrace = exports.objectIsExtensible = exports.objectIsEmpty = exports.mergeNotice = exports.merge = void 0;
|
|
263
|
+
exports.logDeprecatedMethod = exports.globalThisOrWindow = exports.isBrowserConfig = exports.clone = exports.formatCGIData = exports.filterUrl = exports.filter = exports.generateStackTrace = exports.endpoint = exports.instrumentConsole = exports.instrument = exports.isErrorObject = exports.makeNotice = exports.logger = exports.sanitize = exports.shallowClone = exports.runAfterNotifyHandlers = exports.shouldSampleEvent = exports.resolveInsights = exports.runBeforeEventHandlers = exports.runBeforeNotifyHandlers = exports.getSourceForBacktrace = exports.getCauses = exports.calculateBacktraceShift = exports.DEFAULT_BACKTRACE_SHIFT = exports.makeBacktrace = exports.objectIsExtensible = exports.objectIsEmpty = exports.mergeNotice = exports.merge = void 0;
|
|
262
264
|
/* eslint-disable prefer-rest-params */
|
|
263
265
|
var stackTraceParser = __importStar(require$$0$1);
|
|
264
266
|
function merge(obj1, obj2) {
|
|
@@ -434,6 +436,88 @@ var require$$0$1 = /*@__PURE__*/getAugmentedNamespace(stackTraceParser_esm);
|
|
|
434
436
|
};
|
|
435
437
|
}
|
|
436
438
|
exports.runBeforeNotifyHandlers = runBeforeNotifyHandlers;
|
|
439
|
+
function runBeforeEventHandlers(payload, handlers, logger) {
|
|
440
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
441
|
+
var i, len, result, err_1;
|
|
442
|
+
return __generator(this, function (_a) {
|
|
443
|
+
switch (_a.label) {
|
|
444
|
+
case 0:
|
|
445
|
+
i = 0, len = handlers.length;
|
|
446
|
+
_a.label = 1;
|
|
447
|
+
case 1:
|
|
448
|
+
if (!(i < len)) return [3 /*break*/, 7];
|
|
449
|
+
result = void 0;
|
|
450
|
+
_a.label = 2;
|
|
451
|
+
case 2:
|
|
452
|
+
_a.trys.push([2, 4, , 5]);
|
|
453
|
+
return [4 /*yield*/, handlers[i](payload)];
|
|
454
|
+
case 3:
|
|
455
|
+
result = _a.sent();
|
|
456
|
+
return [3 /*break*/, 5];
|
|
457
|
+
case 4:
|
|
458
|
+
err_1 = _a.sent();
|
|
459
|
+
// A buggy handler should not suppress unrelated events. Log and treat as no-op.
|
|
460
|
+
logger === null || logger === void 0 ? void 0 : logger.error('beforeEvent handler threw; continuing', err_1);
|
|
461
|
+
return [3 /*break*/, 6];
|
|
462
|
+
case 5:
|
|
463
|
+
if (result === false) {
|
|
464
|
+
return [2 /*return*/, false];
|
|
465
|
+
}
|
|
466
|
+
_a.label = 6;
|
|
467
|
+
case 6:
|
|
468
|
+
i++;
|
|
469
|
+
return [3 /*break*/, 1];
|
|
470
|
+
case 7: return [2 /*return*/, true];
|
|
471
|
+
}
|
|
472
|
+
});
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
exports.runBeforeEventHandlers = runBeforeEventHandlers;
|
|
476
|
+
function resolveInsights(config) {
|
|
477
|
+
var _a, _b;
|
|
478
|
+
var insights = config.insights;
|
|
479
|
+
if (!insights || insights.enabled !== true) {
|
|
480
|
+
return { console: false, http: false };
|
|
481
|
+
}
|
|
482
|
+
return {
|
|
483
|
+
console: (_a = insights.console) !== null && _a !== void 0 ? _a : false,
|
|
484
|
+
http: (_b = insights.http) !== null && _b !== void 0 ? _b : false,
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
exports.resolveInsights = resolveInsights;
|
|
488
|
+
function fnv1a(str) {
|
|
489
|
+
var h = 0x811c9dc5;
|
|
490
|
+
for (var i = 0, len = str.length; i < len; i++) {
|
|
491
|
+
h ^= str.charCodeAt(i);
|
|
492
|
+
h = Math.imul(h, 0x01000193);
|
|
493
|
+
}
|
|
494
|
+
return h >>> 0;
|
|
495
|
+
}
|
|
496
|
+
function clampSampleRate(rate) {
|
|
497
|
+
if (rate < 0)
|
|
498
|
+
return 0;
|
|
499
|
+
if (rate > 100)
|
|
500
|
+
return 100;
|
|
501
|
+
return rate;
|
|
502
|
+
}
|
|
503
|
+
function shouldSampleEvent(event, configRate) {
|
|
504
|
+
var meta = event._hb;
|
|
505
|
+
var override = meta && Number.isFinite(meta.sampleRate) ? meta.sampleRate : undefined;
|
|
506
|
+
var rawRate = override !== undefined ? override : configRate;
|
|
507
|
+
// Guard against non-finite rates (e.g. NaN from Number(invalidConfig)); an
|
|
508
|
+
// unusable rate must not silently drop every event, so fall back to send-all.
|
|
509
|
+
var rate = clampSampleRate(Number.isFinite(rawRate) ? rawRate : 100);
|
|
510
|
+
if (rate <= 0)
|
|
511
|
+
return false;
|
|
512
|
+
if (rate >= 100)
|
|
513
|
+
return true;
|
|
514
|
+
var requestId = event.request_id;
|
|
515
|
+
if (typeof requestId === 'string' && requestId.length > 0) {
|
|
516
|
+
return fnv1a(requestId) % 100 < rate;
|
|
517
|
+
}
|
|
518
|
+
return Math.random() * 100 < rate;
|
|
519
|
+
}
|
|
520
|
+
exports.shouldSampleEvent = shouldSampleEvent;
|
|
437
521
|
function runAfterNotifyHandlers(notice, handlers, error) {
|
|
438
522
|
if (notice && notice.afterNotify) {
|
|
439
523
|
notice.afterNotify(error, notice);
|
|
@@ -772,8 +856,36 @@ var require$$0$1 = /*@__PURE__*/getAugmentedNamespace(stackTraceParser_esm);
|
|
|
772
856
|
return formattedVars;
|
|
773
857
|
}
|
|
774
858
|
exports.formatCGIData = formatCGIData;
|
|
859
|
+
/**
|
|
860
|
+
* Deep-copies a value exactly the way a JSON round trip does -- `toJSON` is
|
|
861
|
+
* honored, so dates become ISO strings -- except that circular references are
|
|
862
|
+
* replaced with '[RECURSION]' instead of throwing.
|
|
863
|
+
*
|
|
864
|
+
* Only true cycles are replaced: a value referenced twice in sibling branches
|
|
865
|
+
* is copied twice, as a JSON round trip would.
|
|
866
|
+
*
|
|
867
|
+
* Anything else a round trip rejects (a BigInt, a getter that throws) still
|
|
868
|
+
* throws here. Callers that must not fail are expected to handle it: silently
|
|
869
|
+
* substituting a placeholder would let a malformed value -- a string where an
|
|
870
|
+
* object is expected, say -- travel on as though it were valid.
|
|
871
|
+
*/
|
|
775
872
|
function clone(obj) {
|
|
776
|
-
|
|
873
|
+
var ancestors = [];
|
|
874
|
+
return JSON.parse(JSON.stringify(obj, function (_key, value) {
|
|
875
|
+
if (typeof value !== 'object' || value === null) {
|
|
876
|
+
return value;
|
|
877
|
+
}
|
|
878
|
+
// `this` is the object `value` sits in, so anything stacked above it has
|
|
879
|
+
// been fully visited and is no longer an ancestor of `value`.
|
|
880
|
+
while (ancestors.length > 0 && ancestors[ancestors.length - 1] !== this) {
|
|
881
|
+
ancestors.pop();
|
|
882
|
+
}
|
|
883
|
+
if (ancestors.indexOf(value) !== -1) {
|
|
884
|
+
return '[RECURSION]';
|
|
885
|
+
}
|
|
886
|
+
ancestors.push(value);
|
|
887
|
+
return value;
|
|
888
|
+
}));
|
|
777
889
|
}
|
|
778
890
|
exports.clone = clone;
|
|
779
891
|
var THRESHOLD_COLUMN_NUMBER = 10000;
|
|
@@ -854,7 +966,7 @@ var require$$0$1 = /*@__PURE__*/getAugmentedNamespace(stackTraceParser_esm);
|
|
|
854
966
|
|
|
855
967
|
} (util$1));
|
|
856
968
|
|
|
857
|
-
Object.defineProperty(
|
|
969
|
+
Object.defineProperty(console_events, "__esModule", { value: true });
|
|
858
970
|
var util_1$8 = util$1;
|
|
859
971
|
function default_1$3(_window) {
|
|
860
972
|
if (_window === void 0) { _window = (0, util_1$8.globalThisOrWindow)(); }
|
|
@@ -862,7 +974,7 @@ function default_1$3(_window) {
|
|
|
862
974
|
shouldReloadOnConfigure: false,
|
|
863
975
|
load: function (client) {
|
|
864
976
|
function sendEventsToInsights() {
|
|
865
|
-
return client.config.
|
|
977
|
+
return (0, util_1$8.resolveInsights)(client.config).console;
|
|
866
978
|
}
|
|
867
979
|
if (!sendEventsToInsights()) {
|
|
868
980
|
return;
|
|
@@ -889,7 +1001,7 @@ function default_1$3(_window) {
|
|
|
889
1001
|
}
|
|
890
1002
|
};
|
|
891
1003
|
}
|
|
892
|
-
|
|
1004
|
+
console_events.default = default_1$3;
|
|
893
1005
|
|
|
894
1006
|
var client$1 = {};
|
|
895
1007
|
|
|
@@ -911,11 +1023,21 @@ var GlobalStore = /** @class */ (function () {
|
|
|
911
1023
|
};
|
|
912
1024
|
GlobalStore.prototype.getContents = function (key) {
|
|
913
1025
|
var value = key ? this.contents[key] : this.contents;
|
|
914
|
-
|
|
1026
|
+
// `clone` keeps JSON round trip semantics but tolerates values a bare
|
|
1027
|
+
// round trip throws on -- notably circular references, which arrive via
|
|
1028
|
+
// context or breadcrumb metadata the host application controls.
|
|
1029
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1030
|
+
return (0, util_1$7.clone)(value);
|
|
915
1031
|
};
|
|
916
1032
|
GlobalStore.prototype.setContext = function (context) {
|
|
917
1033
|
this.contents.context = (0, util_1$7.merge)(this.contents.context, context || {});
|
|
918
1034
|
};
|
|
1035
|
+
GlobalStore.prototype.setEventContext = function (eventContext) {
|
|
1036
|
+
this.contents.eventContext = (0, util_1$7.merge)(this.contents.eventContext, eventContext || {});
|
|
1037
|
+
};
|
|
1038
|
+
GlobalStore.prototype.clearEventContext = function () {
|
|
1039
|
+
this.contents.eventContext = {};
|
|
1040
|
+
};
|
|
919
1041
|
GlobalStore.prototype.addBreadcrumb = function (breadcrumb) {
|
|
920
1042
|
if (this.contents.breadcrumbs.length == this.breadcrumbsLimit) {
|
|
921
1043
|
this.contents.breadcrumbs.shift();
|
|
@@ -924,6 +1046,7 @@ var GlobalStore = /** @class */ (function () {
|
|
|
924
1046
|
};
|
|
925
1047
|
GlobalStore.prototype.clear = function () {
|
|
926
1048
|
this.contents.context = {};
|
|
1049
|
+
this.contents.eventContext = {};
|
|
927
1050
|
this.contents.breadcrumbs = [];
|
|
928
1051
|
};
|
|
929
1052
|
GlobalStore.prototype.run = function (callback) {
|
|
@@ -933,7 +1056,7 @@ var GlobalStore = /** @class */ (function () {
|
|
|
933
1056
|
}());
|
|
934
1057
|
store.GlobalStore = GlobalStore;
|
|
935
1058
|
|
|
936
|
-
var
|
|
1059
|
+
var throttled_events_worker = {};
|
|
937
1060
|
|
|
938
1061
|
class NdJson {
|
|
939
1062
|
static parse(data) {
|
|
@@ -968,8 +1091,18 @@ defaults.CONFIG = {
|
|
|
968
1091
|
revision: null,
|
|
969
1092
|
reportData: null,
|
|
970
1093
|
breadcrumbsEnabled: true,
|
|
971
|
-
//
|
|
1094
|
+
// deprecated: `eventsEnabled: true` auto-enables insights.enabled + insights.console
|
|
972
1095
|
eventsEnabled: false,
|
|
1096
|
+
insights: {
|
|
1097
|
+
enabled: false,
|
|
1098
|
+
console: false,
|
|
1099
|
+
http: false,
|
|
1100
|
+
},
|
|
1101
|
+
events: {
|
|
1102
|
+
dispatchIntervalSeconds: 10,
|
|
1103
|
+
bulkThreshold: 500,
|
|
1104
|
+
sampleRatePercentage: 100,
|
|
1105
|
+
},
|
|
973
1106
|
maxBreadcrumbs: 40,
|
|
974
1107
|
maxObjectDepth: 8,
|
|
975
1108
|
logger: console,
|
|
@@ -1032,72 +1165,179 @@ var __generator$4 = (commonjsGlobal && commonjsGlobal.__generator) || function (
|
|
|
1032
1165
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
1033
1166
|
}
|
|
1034
1167
|
};
|
|
1035
|
-
Object.defineProperty(
|
|
1036
|
-
|
|
1168
|
+
Object.defineProperty(throttled_events_worker, "__esModule", { value: true });
|
|
1169
|
+
throttled_events_worker.ThrottledEventsWorker = void 0;
|
|
1037
1170
|
var json_nd_1 = require$$0;
|
|
1038
1171
|
var util_1$6 = util$1;
|
|
1039
1172
|
var defaults_1$1 = defaults;
|
|
1040
|
-
var
|
|
1041
|
-
function
|
|
1173
|
+
var ThrottledEventsWorker = /** @class */ (function () {
|
|
1174
|
+
function ThrottledEventsWorker(config, transport) {
|
|
1042
1175
|
this.config = config;
|
|
1043
1176
|
this.transport = transport;
|
|
1044
1177
|
this.queue = [];
|
|
1045
|
-
this.
|
|
1178
|
+
this.cooldownTimer = null;
|
|
1179
|
+
// Timestamp (ms) until which the post-send cooldown window is active. A timer
|
|
1180
|
+
// is only armed while there are queued events waiting for this window; when the
|
|
1181
|
+
// queue drains empty we keep the timestamp but drop the timer, so an idle worker
|
|
1182
|
+
// never holds a pending timer (which would otherwise keep a Node process alive
|
|
1183
|
+
// for the full interval.
|
|
1184
|
+
this.cooldownUntil = 0;
|
|
1185
|
+
this.inFlight = null;
|
|
1046
1186
|
this.config = __assign$2(__assign$2({}, defaults_1$1.CONFIG), config);
|
|
1047
1187
|
this.logger = this.originalLogger();
|
|
1048
1188
|
}
|
|
1049
|
-
|
|
1189
|
+
ThrottledEventsWorker.prototype.configure = function (opts) {
|
|
1050
1190
|
for (var k in opts) {
|
|
1051
1191
|
this.config[k] = opts[k];
|
|
1052
1192
|
}
|
|
1053
1193
|
};
|
|
1054
|
-
|
|
1194
|
+
ThrottledEventsWorker.prototype.log = function (payload) {
|
|
1055
1195
|
this.queue.push(payload);
|
|
1056
|
-
if (
|
|
1196
|
+
if (this.inFlight) {
|
|
1197
|
+
return;
|
|
1198
|
+
}
|
|
1199
|
+
// Crossing the bulk threshold preempts any pending cooldown and dispatches now.
|
|
1200
|
+
if (this.queue.length >= this.bulkThreshold()) {
|
|
1201
|
+
this.clearCooldownTimer();
|
|
1057
1202
|
this.processQueue();
|
|
1203
|
+
return;
|
|
1058
1204
|
}
|
|
1205
|
+
// A timer is already counting down the cooldown window; the queued event
|
|
1206
|
+
// will be picked up when it fires.
|
|
1207
|
+
if (this.cooldownTimer) {
|
|
1208
|
+
return;
|
|
1209
|
+
}
|
|
1210
|
+
// We're inside a cooldown window but no timer is armed (the queue had drained
|
|
1211
|
+
// empty after the previous send). Arm one for the remaining time so this event
|
|
1212
|
+
// still respects the interval.
|
|
1213
|
+
var remaining = this.cooldownRemainingMs();
|
|
1214
|
+
if (remaining > 0) {
|
|
1215
|
+
this.scheduleCooldownTimer(remaining);
|
|
1216
|
+
return;
|
|
1217
|
+
}
|
|
1218
|
+
this.processQueue();
|
|
1059
1219
|
};
|
|
1060
|
-
|
|
1220
|
+
ThrottledEventsWorker.prototype.flushAsync = function () {
|
|
1221
|
+
var _this = this;
|
|
1222
|
+
var _a;
|
|
1061
1223
|
this.logger.debug('[Honeybadger] Flushing events');
|
|
1062
|
-
|
|
1224
|
+
this.clearCooldownTimer();
|
|
1225
|
+
var previous = (_a = this.inFlight) !== null && _a !== void 0 ? _a : Promise.resolve();
|
|
1226
|
+
var flush = previous.then(function () { return _this.drainAll(); });
|
|
1227
|
+
// Mark the flush as in-flight so a concurrent log() doesn't start an
|
|
1228
|
+
// overlapping processQueue() drain while we're draining here.
|
|
1229
|
+
this.inFlight = flush;
|
|
1230
|
+
var clear = function () {
|
|
1231
|
+
if (_this.inFlight === flush) {
|
|
1232
|
+
_this.inFlight = null;
|
|
1233
|
+
}
|
|
1234
|
+
};
|
|
1235
|
+
flush.then(clear, clear);
|
|
1236
|
+
return flush;
|
|
1237
|
+
};
|
|
1238
|
+
ThrottledEventsWorker.prototype.drainAll = function () {
|
|
1239
|
+
return __awaiter$4(this, void 0, void 0, function () {
|
|
1240
|
+
return __generator$4(this, function (_a) {
|
|
1241
|
+
switch (_a.label) {
|
|
1242
|
+
case 0:
|
|
1243
|
+
if (!(this.queue.length > 0)) return [3 /*break*/, 2];
|
|
1244
|
+
return [4 /*yield*/, this.send()];
|
|
1245
|
+
case 1:
|
|
1246
|
+
_a.sent();
|
|
1247
|
+
return [3 /*break*/, 0];
|
|
1248
|
+
case 2: return [2 /*return*/];
|
|
1249
|
+
}
|
|
1250
|
+
});
|
|
1251
|
+
});
|
|
1063
1252
|
};
|
|
1064
|
-
|
|
1253
|
+
ThrottledEventsWorker.prototype.processQueue = function () {
|
|
1065
1254
|
var _this = this;
|
|
1066
|
-
if (this.queue.length === 0 || this.
|
|
1255
|
+
if (this.queue.length === 0 || this.inFlight) {
|
|
1067
1256
|
return;
|
|
1068
1257
|
}
|
|
1069
|
-
|
|
1070
|
-
this.send()
|
|
1071
|
-
.then(function () {
|
|
1072
|
-
setTimeout(function () {
|
|
1073
|
-
_this.isProcessing = false;
|
|
1074
|
-
_this.processQueue();
|
|
1075
|
-
}, 50);
|
|
1076
|
-
})
|
|
1258
|
+
var inFlight = this.send()
|
|
1077
1259
|
.catch(function (error) {
|
|
1078
1260
|
_this.logger.error('[Honeybadger] Error making HTTP request:', error);
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1261
|
+
})
|
|
1262
|
+
.then(function () {
|
|
1263
|
+
// Only reset if we're still the current operation; a flushAsync() may
|
|
1264
|
+
// have taken ownership of inFlight while this send was resolving.
|
|
1265
|
+
if (_this.inFlight === inFlight) {
|
|
1266
|
+
_this.inFlight = null;
|
|
1267
|
+
_this.scheduleNextDispatch();
|
|
1268
|
+
}
|
|
1084
1269
|
});
|
|
1270
|
+
this.inFlight = inFlight;
|
|
1271
|
+
};
|
|
1272
|
+
ThrottledEventsWorker.prototype.scheduleNextDispatch = function () {
|
|
1273
|
+
var intervalMs = this.dispatchIntervalMs();
|
|
1274
|
+
// Capture the cooldown deadline at dispatch time so a later config change to
|
|
1275
|
+
// the interval doesn't retroactively shorten a window already in progress.
|
|
1276
|
+
this.cooldownUntil = Date.now() + intervalMs;
|
|
1277
|
+
if (this.queue.length >= this.bulkThreshold()) {
|
|
1278
|
+
this.processQueue();
|
|
1279
|
+
return;
|
|
1280
|
+
}
|
|
1281
|
+
// Only arm a timer when there's queued work waiting for it. If the queue is
|
|
1282
|
+
// empty, `cooldownUntil` alone enforces the window: the next log() will arm a
|
|
1283
|
+
// timer for whatever time remains, and an idle worker holds no timer at all.
|
|
1284
|
+
if (this.queue.length > 0) {
|
|
1285
|
+
this.scheduleCooldownTimer(intervalMs);
|
|
1286
|
+
}
|
|
1287
|
+
};
|
|
1288
|
+
ThrottledEventsWorker.prototype.cooldownRemainingMs = function () {
|
|
1289
|
+
if (!this.cooldownUntil) {
|
|
1290
|
+
return 0;
|
|
1291
|
+
}
|
|
1292
|
+
return Math.max(0, this.cooldownUntil - Date.now());
|
|
1085
1293
|
};
|
|
1086
|
-
|
|
1294
|
+
ThrottledEventsWorker.prototype.scheduleCooldownTimer = function (ms) {
|
|
1295
|
+
var _this = this;
|
|
1296
|
+
this.cooldownTimer = setTimeout(function () {
|
|
1297
|
+
_this.cooldownTimer = null;
|
|
1298
|
+
_this.processQueue();
|
|
1299
|
+
}, ms);
|
|
1300
|
+
// In Node, don't let a pending cooldown timer keep the process alive for the
|
|
1301
|
+
// whole batching interval. `unref` lets the event loop go idle so the process
|
|
1302
|
+
// can exit (or a shutdown / `beforeExit` handler can run) promptly instead of
|
|
1303
|
+
// blocking for `dispatchIntervalSeconds`. Queued events aren't lost: a
|
|
1304
|
+
// `flushAsync()` on the way out still drains them before exit. (`unref` is
|
|
1305
|
+
// Node-only; the browser's numeric setTimeout handle has no such method.)
|
|
1306
|
+
if (typeof this.cooldownTimer === 'object' && this.cooldownTimer !== null && typeof this.cooldownTimer.unref === 'function') {
|
|
1307
|
+
this.cooldownTimer.unref();
|
|
1308
|
+
}
|
|
1309
|
+
};
|
|
1310
|
+
ThrottledEventsWorker.prototype.clearCooldownTimer = function () {
|
|
1311
|
+
if (this.cooldownTimer) {
|
|
1312
|
+
clearTimeout(this.cooldownTimer);
|
|
1313
|
+
this.cooldownTimer = null;
|
|
1314
|
+
}
|
|
1315
|
+
};
|
|
1316
|
+
ThrottledEventsWorker.prototype.send = function () {
|
|
1087
1317
|
return __awaiter$4(this, void 0, void 0, function () {
|
|
1088
1318
|
var eventsData, data;
|
|
1089
1319
|
return __generator$4(this, function (_a) {
|
|
1090
1320
|
if (this.queue.length === 0) {
|
|
1091
1321
|
return [2 /*return*/];
|
|
1092
1322
|
}
|
|
1093
|
-
eventsData = this.queue.
|
|
1094
|
-
this.queue = [];
|
|
1323
|
+
eventsData = this.queue.splice(0, this.bulkThreshold());
|
|
1095
1324
|
data = json_nd_1.NdJson.stringify(eventsData);
|
|
1096
1325
|
return [2 /*return*/, this.makeHttpRequest(data)];
|
|
1097
1326
|
});
|
|
1098
1327
|
});
|
|
1099
1328
|
};
|
|
1100
|
-
|
|
1329
|
+
ThrottledEventsWorker.prototype.bulkThreshold = function () {
|
|
1330
|
+
var _a;
|
|
1331
|
+
var v = (_a = this.config.events) === null || _a === void 0 ? void 0 : _a.bulkThreshold;
|
|
1332
|
+
return typeof v === 'number' && v > 0 ? v : defaults_1$1.CONFIG.events.bulkThreshold;
|
|
1333
|
+
};
|
|
1334
|
+
ThrottledEventsWorker.prototype.dispatchIntervalMs = function () {
|
|
1335
|
+
var _a;
|
|
1336
|
+
var v = (_a = this.config.events) === null || _a === void 0 ? void 0 : _a.dispatchIntervalSeconds;
|
|
1337
|
+
var seconds = typeof v === 'number' && v >= 0 ? v : defaults_1$1.CONFIG.events.dispatchIntervalSeconds;
|
|
1338
|
+
return seconds * 1000;
|
|
1339
|
+
};
|
|
1340
|
+
ThrottledEventsWorker.prototype.makeHttpRequest = function (data) {
|
|
1101
1341
|
return __awaiter$4(this, void 0, void 0, function () {
|
|
1102
1342
|
var _this = this;
|
|
1103
1343
|
return __generator$4(this, function (_a) {
|
|
@@ -1112,10 +1352,13 @@ var ThrottledEventsLogger = /** @class */ (function () {
|
|
|
1112
1352
|
maxObjectDepth: this.config.maxObjectDepth,
|
|
1113
1353
|
logger: this.logger,
|
|
1114
1354
|
}, data)
|
|
1115
|
-
.then(function () {
|
|
1116
|
-
if (
|
|
1355
|
+
.then(function (resp) {
|
|
1356
|
+
if ([200, 201].includes(resp.statusCode)) {
|
|
1117
1357
|
_this.logger.debug('[Honeybadger] Events sent successfully');
|
|
1118
1358
|
}
|
|
1359
|
+
else {
|
|
1360
|
+
_this.logger.debug("[Honeybadger] Events failed[".concat(resp.statusCode, "]: ").concat(resp.body));
|
|
1361
|
+
}
|
|
1119
1362
|
})
|
|
1120
1363
|
.catch(function (err) {
|
|
1121
1364
|
_this.logger.error("[Honeybadger] Error sending events: ".concat(err.message));
|
|
@@ -1126,28 +1369,40 @@ var ThrottledEventsLogger = /** @class */ (function () {
|
|
|
1126
1369
|
/**
|
|
1127
1370
|
* todo: improve this
|
|
1128
1371
|
*
|
|
1129
|
-
* The
|
|
1372
|
+
* The events plugin overrides the console methods to enable automatic instrumentation
|
|
1130
1373
|
* of console logs to the Honeybadger API.
|
|
1131
1374
|
* So if we want to log something in here we need to use the original methods.
|
|
1132
1375
|
*/
|
|
1133
|
-
|
|
1134
|
-
var
|
|
1376
|
+
ThrottledEventsWorker.prototype.originalLogger = function () {
|
|
1377
|
+
var _this = this;
|
|
1378
|
+
var _a, _b, _c, _d;
|
|
1135
1379
|
return {
|
|
1136
1380
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1137
1381
|
log: (_a = console.log.__hb_original) !== null && _a !== void 0 ? _a : console.log,
|
|
1138
1382
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1139
1383
|
info: (_b = console.info.__hb_original) !== null && _b !== void 0 ? _b : console.info,
|
|
1384
|
+
debug: function () {
|
|
1385
|
+
var _a;
|
|
1386
|
+
var args = [];
|
|
1387
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
1388
|
+
args[_i] = arguments[_i];
|
|
1389
|
+
}
|
|
1390
|
+
if (!_this.config.debug) {
|
|
1391
|
+
return;
|
|
1392
|
+
}
|
|
1393
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1394
|
+
var func = (_a = console.debug.__hb_original) !== null && _a !== void 0 ? _a : console.debug;
|
|
1395
|
+
return func.apply(void 0, args);
|
|
1396
|
+
},
|
|
1140
1397
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1141
|
-
|
|
1142
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1143
|
-
warn: (_d = console.warn.__hb_original) !== null && _d !== void 0 ? _d : console.warn,
|
|
1398
|
+
warn: (_c = console.warn.__hb_original) !== null && _c !== void 0 ? _c : console.warn,
|
|
1144
1399
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1145
|
-
error: (
|
|
1400
|
+
error: (_d = console.error.__hb_original) !== null && _d !== void 0 ? _d : console.error,
|
|
1146
1401
|
};
|
|
1147
1402
|
};
|
|
1148
|
-
return
|
|
1403
|
+
return ThrottledEventsWorker;
|
|
1149
1404
|
}());
|
|
1150
|
-
|
|
1405
|
+
throttled_events_worker.ThrottledEventsWorker = ThrottledEventsWorker;
|
|
1151
1406
|
|
|
1152
1407
|
var __assign$1 = (commonjsGlobal && commonjsGlobal.__assign) || function () {
|
|
1153
1408
|
__assign$1 = Object.assign || function(t) {
|
|
@@ -1200,7 +1455,7 @@ Object.defineProperty(client$1, "__esModule", { value: true });
|
|
|
1200
1455
|
client$1.Client = void 0;
|
|
1201
1456
|
var util_1$5 = util$1;
|
|
1202
1457
|
var store_1 = store;
|
|
1203
|
-
var
|
|
1458
|
+
var throttled_events_worker_1 = throttled_events_worker;
|
|
1204
1459
|
var defaults_1 = defaults;
|
|
1205
1460
|
// Split at commas and spaces
|
|
1206
1461
|
var TAG_SEPARATOR = /,|\s+/;
|
|
@@ -1212,17 +1467,20 @@ var Client = /** @class */ (function () {
|
|
|
1212
1467
|
this.__pluginsLoaded = false;
|
|
1213
1468
|
this.__store = null;
|
|
1214
1469
|
this.__beforeNotifyHandlers = [];
|
|
1470
|
+
this.__beforeEventHandlers = [];
|
|
1215
1471
|
this.__afterNotifyHandlers = [];
|
|
1472
|
+
this.__pendingEvents = new Set();
|
|
1216
1473
|
this.__notifier = {
|
|
1217
1474
|
name: '@honeybadger-io/core',
|
|
1218
1475
|
url: 'https://github.com/honeybadger-io/honeybadger-js/tree/master/packages/core',
|
|
1219
|
-
version: '6.
|
|
1476
|
+
version: '6.16.1'
|
|
1220
1477
|
};
|
|
1221
1478
|
this.config = __assign$1(__assign$1({}, defaults_1.CONFIG), opts);
|
|
1222
1479
|
this.__initStore();
|
|
1223
1480
|
this.__transport = transport;
|
|
1224
|
-
this.
|
|
1481
|
+
this.__eventsWorker = new throttled_events_worker_1.ThrottledEventsWorker(this.config, this.__transport);
|
|
1225
1482
|
this.logger = (0, util_1$5.logger)(this);
|
|
1483
|
+
this.__applyEventsEnabledShim(opts);
|
|
1226
1484
|
}
|
|
1227
1485
|
Client.prototype.getVersion = function () {
|
|
1228
1486
|
return this.__notifier.version;
|
|
@@ -1245,10 +1503,24 @@ var Client = /** @class */ (function () {
|
|
|
1245
1503
|
for (var k in opts) {
|
|
1246
1504
|
this.config[k] = opts[k];
|
|
1247
1505
|
}
|
|
1248
|
-
this.
|
|
1506
|
+
this.__applyEventsEnabledShim(opts);
|
|
1507
|
+
this.__eventsWorker.configure(this.config);
|
|
1249
1508
|
this.loadPlugins();
|
|
1250
1509
|
return this;
|
|
1251
1510
|
};
|
|
1511
|
+
/**
|
|
1512
|
+
* Backwards compatibility: `eventsEnabled: true` used to opt into console events.
|
|
1513
|
+
* The deprecated flag auto-enables `insights.enabled` and `insights.console`;
|
|
1514
|
+
* explicit user-provided insights values win over the shim.
|
|
1515
|
+
*/
|
|
1516
|
+
Client.prototype.__applyEventsEnabledShim = function (opts) {
|
|
1517
|
+
var _a;
|
|
1518
|
+
if (opts.eventsEnabled !== true) {
|
|
1519
|
+
return;
|
|
1520
|
+
}
|
|
1521
|
+
this.logger.warn('Deprecation warning: `eventsEnabled` has been deprecated; please use `insights.enabled` and `insights.console` instead.');
|
|
1522
|
+
this.config.insights = __assign$1(__assign$1(__assign$1({}, ((_a = this.config.insights) !== null && _a !== void 0 ? _a : {})), { enabled: true, console: true }), opts.insights);
|
|
1523
|
+
};
|
|
1252
1524
|
Client.prototype.loadPlugins = function () {
|
|
1253
1525
|
var _this = this;
|
|
1254
1526
|
var pluginsToLoad = this.__pluginsLoaded
|
|
@@ -1258,12 +1530,16 @@ var Client = /** @class */ (function () {
|
|
|
1258
1530
|
this.__pluginsLoaded = true;
|
|
1259
1531
|
};
|
|
1260
1532
|
Client.prototype.__initStore = function () {
|
|
1261
|
-
this.__store = new store_1.GlobalStore({ context: {}, breadcrumbs: [] }, this.config.maxBreadcrumbs);
|
|
1533
|
+
this.__store = new store_1.GlobalStore({ context: {}, eventContext: {}, breadcrumbs: [] }, this.config.maxBreadcrumbs);
|
|
1262
1534
|
};
|
|
1263
1535
|
Client.prototype.beforeNotify = function (handler) {
|
|
1264
1536
|
this.__beforeNotifyHandlers.push(handler);
|
|
1265
1537
|
return this;
|
|
1266
1538
|
};
|
|
1539
|
+
Client.prototype.beforeEvent = function (handler) {
|
|
1540
|
+
this.__beforeEventHandlers.push(handler);
|
|
1541
|
+
return this;
|
|
1542
|
+
};
|
|
1267
1543
|
Client.prototype.afterNotify = function (handler) {
|
|
1268
1544
|
this.__afterNotifyHandlers.push(handler);
|
|
1269
1545
|
return this;
|
|
@@ -1274,6 +1550,16 @@ var Client = /** @class */ (function () {
|
|
|
1274
1550
|
}
|
|
1275
1551
|
return this;
|
|
1276
1552
|
};
|
|
1553
|
+
Client.prototype.setEventContext = function (eventContext) {
|
|
1554
|
+
if (typeof eventContext === 'object' && eventContext != null) {
|
|
1555
|
+
this.__store.setEventContext(eventContext);
|
|
1556
|
+
}
|
|
1557
|
+
return this;
|
|
1558
|
+
};
|
|
1559
|
+
Client.prototype.clearEventContext = function () {
|
|
1560
|
+
this.__store.clearEventContext();
|
|
1561
|
+
return this;
|
|
1562
|
+
};
|
|
1277
1563
|
Client.prototype.resetContext = function (context) {
|
|
1278
1564
|
this.logger.warn('Deprecation warning: `Honeybadger.resetContext()` has been deprecated; please use `Honeybadger.clear()` instead.');
|
|
1279
1565
|
this.__store.clear();
|
|
@@ -1286,31 +1572,63 @@ var Client = /** @class */ (function () {
|
|
|
1286
1572
|
this.__store.clear();
|
|
1287
1573
|
return this;
|
|
1288
1574
|
};
|
|
1575
|
+
/**
|
|
1576
|
+
* Reporting an error must never break the host application, so any failure
|
|
1577
|
+
* inside the reporting path is logged and swallowed rather than thrown back
|
|
1578
|
+
* into the caller.
|
|
1579
|
+
*/
|
|
1289
1580
|
Client.prototype.notify = function (noticeable, name, extra) {
|
|
1290
1581
|
var _this = this;
|
|
1291
1582
|
if (name === void 0) { name = undefined; }
|
|
1292
1583
|
if (extra === void 0) { extra = undefined; }
|
|
1293
|
-
|
|
1294
|
-
//
|
|
1295
|
-
//
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1584
|
+
// The body is inlined in this try/catch rather than delegated to a private
|
|
1585
|
+
// method: generated backtraces are trimmed by a fixed frame count
|
|
1586
|
+
// (DEFAULT_BACKTRACE_SHIFT), so an extra call frame here would shift every
|
|
1587
|
+
// generated backtrace into Honeybadger's own source.
|
|
1588
|
+
try {
|
|
1589
|
+
var notice_1 = this.makeNotice(noticeable, name, extra);
|
|
1590
|
+
// we need to have the source file data before the beforeNotifyHandlers,
|
|
1591
|
+
// in case they modify them
|
|
1592
|
+
var sourceCodeData_1 = notice_1 && notice_1.backtrace ? notice_1.backtrace.map(function (trace) { return (0, util_1$5.shallowClone)(trace); }) : null;
|
|
1593
|
+
var preConditionsResult = this.__runPreconditions(notice_1);
|
|
1594
|
+
if (preConditionsResult instanceof Error) {
|
|
1595
|
+
(0, util_1$5.runAfterNotifyHandlers)(notice_1, this.__afterNotifyHandlers, preConditionsResult);
|
|
1596
|
+
return false;
|
|
1597
|
+
}
|
|
1598
|
+
if (preConditionsResult instanceof Promise) {
|
|
1599
|
+
preConditionsResult.then(function (result) {
|
|
1600
|
+
if (result instanceof Error) {
|
|
1601
|
+
(0, util_1$5.runAfterNotifyHandlers)(notice_1, _this.__afterNotifyHandlers, result);
|
|
1602
|
+
return false;
|
|
1603
|
+
}
|
|
1604
|
+
return _this.__send(notice_1, sourceCodeData_1);
|
|
1605
|
+
}).catch(function (err) {
|
|
1606
|
+
// __send installs its own catch, which logs and runs the afterNotify
|
|
1607
|
+
// handlers. Anything arriving here failed before that chain existed,
|
|
1608
|
+
// so it is still unreported -- and notify() has already returned
|
|
1609
|
+
// true, leaving notifyAsync() waiting on those handlers.
|
|
1610
|
+
_this.__logReportingFailure(err);
|
|
1611
|
+
(0, util_1$5.runAfterNotifyHandlers)(notice_1, _this.__afterNotifyHandlers, err instanceof Error ? err : new Error(String(err)));
|
|
1612
|
+
});
|
|
1613
|
+
return true;
|
|
1614
|
+
}
|
|
1615
|
+
this.__send(notice_1, sourceCodeData_1).catch(function (_err) { });
|
|
1616
|
+
return true;
|
|
1617
|
+
}
|
|
1618
|
+
catch (err) {
|
|
1619
|
+
// Reporting an error must never break the host application, so a failure
|
|
1620
|
+
// in the reporting path is logged rather than thrown back at the caller.
|
|
1621
|
+
// notifyAsync() settles on the false return below.
|
|
1622
|
+
this.__logReportingFailure(err);
|
|
1300
1623
|
return false;
|
|
1301
1624
|
}
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
}
|
|
1308
|
-
return _this.__send(notice, sourceCodeData);
|
|
1309
|
-
});
|
|
1310
|
-
return true;
|
|
1625
|
+
};
|
|
1626
|
+
/** The logger is host-supplied, so even reporting a failure gets a guard. */
|
|
1627
|
+
Client.prototype.__logReportingFailure = function (err) {
|
|
1628
|
+
try {
|
|
1629
|
+
this.logger.error('Error report failed: an internal error occurred while reporting', err);
|
|
1311
1630
|
}
|
|
1312
|
-
|
|
1313
|
-
return true;
|
|
1631
|
+
catch (_loggerErr) { /* nothing left to report it with */ }
|
|
1314
1632
|
};
|
|
1315
1633
|
/**
|
|
1316
1634
|
* An async version of {@link notify} that resolves only after the notice has been reported to Honeybadger.
|
|
@@ -1326,11 +1644,19 @@ var Client = /** @class */ (function () {
|
|
|
1326
1644
|
var applyAfterNotify = function (partialNotice) {
|
|
1327
1645
|
var originalAfterNotify = partialNotice.afterNotify;
|
|
1328
1646
|
partialNotice.afterNotify = function (err) {
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1647
|
+
// Settle from a `finally` so a throwing handler cannot leave the
|
|
1648
|
+
// caller awaiting forever; its error propagates as it always has.
|
|
1649
|
+
try {
|
|
1650
|
+
originalAfterNotify === null || originalAfterNotify === void 0 ? void 0 : originalAfterNotify.call(_this, err);
|
|
1651
|
+
}
|
|
1652
|
+
finally {
|
|
1653
|
+
if (err) {
|
|
1654
|
+
reject(err);
|
|
1655
|
+
}
|
|
1656
|
+
else {
|
|
1657
|
+
resolve();
|
|
1658
|
+
}
|
|
1332
1659
|
}
|
|
1333
|
-
resolve();
|
|
1334
1660
|
};
|
|
1335
1661
|
};
|
|
1336
1662
|
// We have to respect any afterNotify hooks that come from the arguments
|
|
@@ -1354,7 +1680,14 @@ var Client = /** @class */ (function () {
|
|
|
1354
1680
|
objectToOverride = name = {};
|
|
1355
1681
|
}
|
|
1356
1682
|
applyAfterNotify(objectToOverride);
|
|
1357
|
-
|
|
1683
|
+
// `notify` never throws, so a false return is the only signal that the
|
|
1684
|
+
// report was abandoned. Every expected failure has already settled this
|
|
1685
|
+
// promise through the afterNotify hook above (a second reject is a
|
|
1686
|
+
// no-op); this catches the unexpected ones, which would otherwise leave
|
|
1687
|
+
// the caller awaiting forever.
|
|
1688
|
+
if (!_this.notify(noticeable, name, extra)) {
|
|
1689
|
+
reject(new Error('Error report failed: see logs for details'));
|
|
1690
|
+
}
|
|
1358
1691
|
});
|
|
1359
1692
|
};
|
|
1360
1693
|
Client.prototype.makeNotice = function (noticeable, name, extra) {
|
|
@@ -1428,19 +1761,59 @@ var Client = /** @class */ (function () {
|
|
|
1428
1761
|
this.event('log', data);
|
|
1429
1762
|
};
|
|
1430
1763
|
Client.prototype.event = function (type, data) {
|
|
1764
|
+
var _this = this;
|
|
1431
1765
|
var _a;
|
|
1432
1766
|
if (typeof type === 'object') {
|
|
1433
1767
|
data = type;
|
|
1434
1768
|
type = (_a = type['event_type']) !== null && _a !== void 0 ? _a : undefined;
|
|
1435
1769
|
}
|
|
1436
|
-
|
|
1770
|
+
var eventContext = this.__store.getContents('eventContext') || {};
|
|
1771
|
+
var payload = __assign$1(__assign$1({ event_type: type, ts: new Date().toISOString() }, eventContext), data);
|
|
1772
|
+
// Track in-flight handler chains so flushAsync() can await them before
|
|
1773
|
+
// delegating to the events logger; otherwise a caller that awaits flushAsync()
|
|
1774
|
+
// immediately after event() may flush before the payload enters the queue.
|
|
1775
|
+
var inFlight = (0, util_1$5.runBeforeEventHandlers)(payload, this.__beforeEventHandlers, this.logger)
|
|
1776
|
+
.then(function (shouldSend) {
|
|
1777
|
+
var _a, _b;
|
|
1778
|
+
if (!shouldSend) {
|
|
1779
|
+
_this.logger.debug('skipping event: beforeEvent handler returned false');
|
|
1780
|
+
return;
|
|
1781
|
+
}
|
|
1782
|
+
var sampleRate = (_b = (_a = _this.config.events) === null || _a === void 0 ? void 0 : _a.sampleRatePercentage) !== null && _b !== void 0 ? _b : 100;
|
|
1783
|
+
if (!(0, util_1$5.shouldSampleEvent)(payload, sampleRate)) {
|
|
1784
|
+
_this.logger.debug('skipping event: dropped by sampleRatePercentage');
|
|
1785
|
+
return;
|
|
1786
|
+
}
|
|
1787
|
+
delete payload._hb;
|
|
1788
|
+
_this.__eventsWorker.log(payload);
|
|
1789
|
+
})
|
|
1790
|
+
.catch(function (err) {
|
|
1791
|
+
// should not happen, because each handler is wrapped with a try/catch
|
|
1792
|
+
_this.logger.error('beforeEvent handler chain failed; dropping event', err);
|
|
1793
|
+
})
|
|
1794
|
+
.finally(function () {
|
|
1795
|
+
_this.__pendingEvents.delete(inFlight);
|
|
1796
|
+
});
|
|
1797
|
+
this.__pendingEvents.add(inFlight);
|
|
1437
1798
|
};
|
|
1438
1799
|
/**
|
|
1439
1800
|
* This method currently flushes the event (Insights) queue.
|
|
1440
1801
|
* In the future, it should also flush the error queue (assuming an error throttler is implemented).
|
|
1441
1802
|
*/
|
|
1442
1803
|
Client.prototype.flushAsync = function () {
|
|
1443
|
-
return this
|
|
1804
|
+
return __awaiter$3(this, void 0, void 0, function () {
|
|
1805
|
+
return __generator$3(this, function (_a) {
|
|
1806
|
+
switch (_a.label) {
|
|
1807
|
+
case 0:
|
|
1808
|
+
if (!(this.__pendingEvents.size > 0)) return [3 /*break*/, 2];
|
|
1809
|
+
return [4 /*yield*/, Promise.allSettled(Array.from(this.__pendingEvents))];
|
|
1810
|
+
case 1:
|
|
1811
|
+
_a.sent();
|
|
1812
|
+
_a.label = 2;
|
|
1813
|
+
case 2: return [2 /*return*/, this.__eventsWorker.flushAsync()];
|
|
1814
|
+
}
|
|
1815
|
+
});
|
|
1816
|
+
});
|
|
1444
1817
|
};
|
|
1445
1818
|
Client.prototype.__getBreadcrumbs = function () {
|
|
1446
1819
|
return this.__store.getContents('breadcrumbs').slice();
|
|
@@ -1632,7 +2005,7 @@ Object.defineProperty(types, "__esModule", { value: true });
|
|
|
1632
2005
|
};
|
|
1633
2006
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1634
2007
|
exports.Plugins = exports.Defaults = exports.Util = exports.Types = exports.Client = void 0;
|
|
1635
|
-
var
|
|
2008
|
+
var console_events_1 = __importDefault(console_events);
|
|
1636
2009
|
var client_1 = client$1;
|
|
1637
2010
|
Object.defineProperty(exports, "Client", { enumerable: true, get: function () { return client_1.Client; } });
|
|
1638
2011
|
__exportStar(store, exports);
|
|
@@ -1640,7 +2013,12 @@ Object.defineProperty(types, "__esModule", { value: true });
|
|
|
1640
2013
|
exports.Util = __importStar(util$1);
|
|
1641
2014
|
exports.Defaults = __importStar(defaults);
|
|
1642
2015
|
exports.Plugins = {
|
|
1643
|
-
|
|
2016
|
+
consoleEvents: console_events_1.default,
|
|
2017
|
+
/**
|
|
2018
|
+
* @deprecated Use `consoleEvents` instead. Kept as an alias for backwards
|
|
2019
|
+
* compatibility and will be removed in a future major version.
|
|
2020
|
+
*/
|
|
2021
|
+
events: console_events_1.default,
|
|
1644
2022
|
};
|
|
1645
2023
|
|
|
1646
2024
|
} (src));
|
|
@@ -1802,8 +2180,145 @@ var uncaught_exception_monitor = {};
|
|
|
1802
2180
|
|
|
1803
2181
|
var aws_lambda = {};
|
|
1804
2182
|
|
|
2183
|
+
var http_event = {};
|
|
2184
|
+
|
|
2185
|
+
/**
|
|
2186
|
+
* Shared helpers for HTTP-event instrumentation.
|
|
2187
|
+
*
|
|
2188
|
+
* Used by inbound (Express, Fastify, Lambda, Next.js) and — in a later PR —
|
|
2189
|
+
* outbound (`http`, `https`, `fetch`) integrations.
|
|
2190
|
+
*/
|
|
2191
|
+
Object.defineProperty(http_event, "__esModule", { value: true });
|
|
2192
|
+
http_event.buildRequestEventPayload = http_event.durationMs = http_event.startTimer = http_event.seedRequestEventContext = http_event.getOrCreateCorrelationId = http_event.getOrCreateRequestId = void 0;
|
|
2193
|
+
var crypto_1 = require$$0__default$1["default"];
|
|
2194
|
+
/**
|
|
2195
|
+
* Reads a header value from a Node-style headers bag in a case-insensitive
|
|
2196
|
+
* manner. When the value is an array (e.g. `Set-Cookie`), returns the first
|
|
2197
|
+
* element. Returns `undefined` when the header is missing or empty.
|
|
2198
|
+
*/
|
|
2199
|
+
function readHeader(headers, name) {
|
|
2200
|
+
if (!headers)
|
|
2201
|
+
return undefined;
|
|
2202
|
+
var lower = name.toLowerCase();
|
|
2203
|
+
var value = headers[lower];
|
|
2204
|
+
if (value === undefined) {
|
|
2205
|
+
for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) {
|
|
2206
|
+
var key = _a[_i];
|
|
2207
|
+
if (key.toLowerCase() === lower) {
|
|
2208
|
+
value = headers[key];
|
|
2209
|
+
break;
|
|
2210
|
+
}
|
|
2211
|
+
}
|
|
2212
|
+
}
|
|
2213
|
+
if (Array.isArray(value))
|
|
2214
|
+
value = value[0];
|
|
2215
|
+
if (typeof value !== 'string')
|
|
2216
|
+
return undefined;
|
|
2217
|
+
var trimmed = value.trim();
|
|
2218
|
+
return trimmed.length ? trimmed : undefined;
|
|
2219
|
+
}
|
|
2220
|
+
/**
|
|
2221
|
+
* Generates a UUID-like identifier. Prefers Node's `crypto.randomUUID()` when
|
|
2222
|
+
* available (Node 14.17+); falls back to a Math.random-based v4-shaped string
|
|
2223
|
+
* for older Node versions.
|
|
2224
|
+
*/
|
|
2225
|
+
function generateId() {
|
|
2226
|
+
if (typeof crypto_1.randomUUID === 'function') {
|
|
2227
|
+
try {
|
|
2228
|
+
return (0, crypto_1.randomUUID)();
|
|
2229
|
+
}
|
|
2230
|
+
catch (_e) {
|
|
2231
|
+
// fall through to manual generation
|
|
2232
|
+
}
|
|
2233
|
+
}
|
|
2234
|
+
// v4-shaped, not crypto-quality. Acceptable since this is a correlation id,
|
|
2235
|
+
// not a security token.
|
|
2236
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (ch) {
|
|
2237
|
+
var r = (Math.random() * 16) | 0;
|
|
2238
|
+
var v = ch === 'x' ? r : (r & 0x3) | 0x8;
|
|
2239
|
+
return v.toString(16);
|
|
2240
|
+
});
|
|
2241
|
+
}
|
|
2242
|
+
/**
|
|
2243
|
+
* Returns a unique-per-request id. Reads `x-request-id`, then `request-id`
|
|
2244
|
+
* headers; falls back to a generated id when neither is present.
|
|
2245
|
+
*/
|
|
2246
|
+
function getOrCreateRequestId(headers) {
|
|
2247
|
+
var _a, _b;
|
|
2248
|
+
return ((_b = (_a = readHeader(headers, 'x-request-id')) !== null && _a !== void 0 ? _a : readHeader(headers, 'request-id')) !== null && _b !== void 0 ? _b : generateId());
|
|
2249
|
+
}
|
|
2250
|
+
http_event.getOrCreateRequestId = getOrCreateRequestId;
|
|
2251
|
+
/**
|
|
2252
|
+
* Returns a correlation id that may span multiple requests in a logical trace.
|
|
2253
|
+
* Reads `x-correlation-id`, then `x-amzn-trace-id`; falls back to the supplied
|
|
2254
|
+
* `requestId` so callers always have both fields populated.
|
|
2255
|
+
*/
|
|
2256
|
+
function getOrCreateCorrelationId(headers, requestId) {
|
|
2257
|
+
var _a, _b;
|
|
2258
|
+
return ((_b = (_a = readHeader(headers, 'x-correlation-id')) !== null && _a !== void 0 ? _a : readHeader(headers, 'x-amzn-trace-id')) !== null && _b !== void 0 ? _b : requestId);
|
|
2259
|
+
}
|
|
2260
|
+
http_event.getOrCreateCorrelationId = getOrCreateCorrelationId;
|
|
2261
|
+
/**
|
|
2262
|
+
* Convenience helper for framework integrations: read request/correlation ids
|
|
2263
|
+
* from the request headers and return both. When no headers contain either
|
|
2264
|
+
* value, both ids are generated and `requestId === correlationId`.
|
|
2265
|
+
*/
|
|
2266
|
+
function seedRequestEventContext(headers) {
|
|
2267
|
+
var requestId = getOrCreateRequestId(headers);
|
|
2268
|
+
var correlationId = getOrCreateCorrelationId(headers, requestId);
|
|
2269
|
+
return { request_id: requestId, correlation_id: correlationId };
|
|
2270
|
+
}
|
|
2271
|
+
http_event.seedRequestEventContext = seedRequestEventContext;
|
|
2272
|
+
/**
|
|
2273
|
+
* Starts a high-resolution timer.
|
|
2274
|
+
*/
|
|
2275
|
+
function startTimer() {
|
|
2276
|
+
return process.hrtime.bigint();
|
|
2277
|
+
}
|
|
2278
|
+
http_event.startTimer = startTimer;
|
|
2279
|
+
var NS_PER_MS = BigInt(1000000);
|
|
2280
|
+
/**
|
|
2281
|
+
* Returns the integer number of milliseconds elapsed since `start`.
|
|
2282
|
+
*/
|
|
2283
|
+
function durationMs(start) {
|
|
2284
|
+
var diff = process.hrtime.bigint() - start;
|
|
2285
|
+
return Number(diff / NS_PER_MS);
|
|
2286
|
+
}
|
|
2287
|
+
http_event.durationMs = durationMs;
|
|
2288
|
+
/**
|
|
2289
|
+
* Builds the per-request event payload. `request_id` and `correlation_id` are
|
|
2290
|
+
* NOT added here — they live on `eventContext` and are merged onto every event
|
|
2291
|
+
* by the client.
|
|
2292
|
+
*/
|
|
2293
|
+
function buildRequestEventPayload(input) {
|
|
2294
|
+
var payload = {};
|
|
2295
|
+
if (input.method !== undefined)
|
|
2296
|
+
payload.method = input.method;
|
|
2297
|
+
if (input.path !== undefined)
|
|
2298
|
+
payload.path = input.path;
|
|
2299
|
+
if (input.route !== undefined)
|
|
2300
|
+
payload.route = input.route;
|
|
2301
|
+
if (input.status !== undefined)
|
|
2302
|
+
payload.status = input.status;
|
|
2303
|
+
if (input.duration !== undefined)
|
|
2304
|
+
payload.duration = input.duration;
|
|
2305
|
+
if (input.extra) {
|
|
2306
|
+
for (var _i = 0, _a = Object.keys(input.extra); _i < _a.length; _i++) {
|
|
2307
|
+
var k = _a[_i];
|
|
2308
|
+
if (!Object.prototype.hasOwnProperty.call(payload, k)) {
|
|
2309
|
+
payload[k] = input.extra[k];
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
}
|
|
2313
|
+
return payload;
|
|
2314
|
+
}
|
|
2315
|
+
http_event.buildRequestEventPayload = buildRequestEventPayload;
|
|
2316
|
+
|
|
1805
2317
|
Object.defineProperty(aws_lambda, "__esModule", { value: true });
|
|
1806
2318
|
aws_lambda.removeAwsDefaultUncaughtExceptionListener = aws_lambda.lambdaHandler = void 0;
|
|
2319
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2320
|
+
var core_1$5 = src;
|
|
2321
|
+
var http_event_1$1 = http_event;
|
|
1807
2322
|
function isHandlerSync(handler) {
|
|
1808
2323
|
return handler.length > 2;
|
|
1809
2324
|
}
|
|
@@ -1815,28 +2330,132 @@ function reportToHoneybadger(hb, err, callback) {
|
|
|
1815
2330
|
}
|
|
1816
2331
|
});
|
|
1817
2332
|
}
|
|
2333
|
+
// Detects inbound HTTP Lambda events (API Gateway v1 REST, API Gateway v2 HTTP, and ALB).
|
|
2334
|
+
// API Gateway v1 and ALB carry `httpMethod` at the top level; API Gateway v2 nests
|
|
2335
|
+
// method under `requestContext.http`.
|
|
2336
|
+
function isHttpLambdaEvent(event) {
|
|
2337
|
+
if (!event || typeof event !== 'object') {
|
|
2338
|
+
return false;
|
|
2339
|
+
}
|
|
2340
|
+
var e = event;
|
|
2341
|
+
if (typeof e.httpMethod === 'string') {
|
|
2342
|
+
return true;
|
|
2343
|
+
}
|
|
2344
|
+
var rc = e.requestContext;
|
|
2345
|
+
var http = rc && rc.http;
|
|
2346
|
+
return !!(http && typeof http.method === 'string');
|
|
2347
|
+
}
|
|
2348
|
+
function getLambdaMethod(event) {
|
|
2349
|
+
if (!event || typeof event !== 'object') {
|
|
2350
|
+
return undefined;
|
|
2351
|
+
}
|
|
2352
|
+
var e = event;
|
|
2353
|
+
if (typeof e.httpMethod === 'string') {
|
|
2354
|
+
return e.httpMethod;
|
|
2355
|
+
}
|
|
2356
|
+
var rc = e.requestContext;
|
|
2357
|
+
var http = rc && rc.http;
|
|
2358
|
+
if (http && typeof http.method === 'string') {
|
|
2359
|
+
return http.method;
|
|
2360
|
+
}
|
|
2361
|
+
return undefined;
|
|
2362
|
+
}
|
|
2363
|
+
function getLambdaPath(event) {
|
|
2364
|
+
if (!event || typeof event !== 'object') {
|
|
2365
|
+
return undefined;
|
|
2366
|
+
}
|
|
2367
|
+
var e = event;
|
|
2368
|
+
var rc = e.requestContext;
|
|
2369
|
+
var http = rc && rc.http;
|
|
2370
|
+
if (http && typeof http.path === 'string') {
|
|
2371
|
+
return http.path;
|
|
2372
|
+
}
|
|
2373
|
+
if (typeof e.rawPath === 'string') {
|
|
2374
|
+
return e.rawPath;
|
|
2375
|
+
}
|
|
2376
|
+
if (typeof e.path === 'string') {
|
|
2377
|
+
return e.path;
|
|
2378
|
+
}
|
|
2379
|
+
return undefined;
|
|
2380
|
+
}
|
|
2381
|
+
function lambdaStatus(result) {
|
|
2382
|
+
if (result && typeof result === 'object') {
|
|
2383
|
+
var status_1 = result.statusCode;
|
|
2384
|
+
if (typeof status_1 === 'number')
|
|
2385
|
+
return status_1;
|
|
2386
|
+
}
|
|
2387
|
+
return 200;
|
|
2388
|
+
}
|
|
2389
|
+
function getLambdaHeaders(event) {
|
|
2390
|
+
if (!event || typeof event !== 'object')
|
|
2391
|
+
return {};
|
|
2392
|
+
var headers = event.headers;
|
|
2393
|
+
if (!headers || typeof headers !== 'object')
|
|
2394
|
+
return {};
|
|
2395
|
+
return headers;
|
|
2396
|
+
}
|
|
2397
|
+
function seedLambdaEventContext(hb, event, context) {
|
|
2398
|
+
if (isHttpLambdaEvent(event)) {
|
|
2399
|
+
hb.setEventContext((0, http_event_1$1.seedRequestEventContext)(getLambdaHeaders(event)));
|
|
2400
|
+
return;
|
|
2401
|
+
}
|
|
2402
|
+
// Non-HTTP triggers (SQS, S3, EventBridge, scheduled) have no inbound headers.
|
|
2403
|
+
// Use the AWS request id as the request_id, and X-Ray's trace id (if set) as
|
|
2404
|
+
// the correlation_id, otherwise mirror request_id.
|
|
2405
|
+
var requestId = context.awsRequestId;
|
|
2406
|
+
var correlationId = process.env._X_AMZN_TRACE_ID || requestId;
|
|
2407
|
+
hb.setEventContext({ request_id: requestId, correlation_id: correlationId });
|
|
2408
|
+
}
|
|
2409
|
+
// Returns an emitter for the `request.handled` event, or null when HTTP
|
|
2410
|
+
// instrumentation is off (nothing to emit). The emitter also owns delivery:
|
|
2411
|
+
// Lambda may freeze the execution environment the moment the handler completes,
|
|
2412
|
+
// so after recording the event it flushes the queue and returns that promise.
|
|
2413
|
+
// Callers must await it before resolving/invoking the callback. Delivery failures
|
|
2414
|
+
// are logged by the events worker and must not break the handler.
|
|
2415
|
+
function createLambdaRequestEmitter(hb, event) {
|
|
2416
|
+
if (!isHttpLambdaEvent(event))
|
|
2417
|
+
return null;
|
|
2418
|
+
if (!core_1$5.Util.resolveInsights(hb.config).http)
|
|
2419
|
+
return null;
|
|
2420
|
+
var start = (0, http_event_1$1.startTimer)();
|
|
2421
|
+
var emitted = false;
|
|
2422
|
+
return function emit(status) {
|
|
2423
|
+
if (emitted)
|
|
2424
|
+
return Promise.resolve();
|
|
2425
|
+
emitted = true;
|
|
2426
|
+
hb.event('request.handled', (0, http_event_1$1.buildRequestEventPayload)({
|
|
2427
|
+
method: getLambdaMethod(event),
|
|
2428
|
+
path: getLambdaPath(event),
|
|
2429
|
+
status: status,
|
|
2430
|
+
duration: (0, http_event_1$1.durationMs)(start),
|
|
2431
|
+
}));
|
|
2432
|
+
return hb.flushAsync().catch(function () { });
|
|
2433
|
+
};
|
|
2434
|
+
}
|
|
1818
2435
|
function asyncHandler(handler, hb) {
|
|
1819
2436
|
return function wrappedLambdaHandler(event, context) {
|
|
1820
2437
|
return new Promise(function (resolve, reject) {
|
|
1821
2438
|
hb.run(function () {
|
|
2439
|
+
seedLambdaEventContext(hb, event, context);
|
|
2440
|
+
var emit = createLambdaRequestEmitter(hb, event);
|
|
1822
2441
|
var timeoutHandler = setupTimeoutWarning(hb, context);
|
|
1823
2442
|
try {
|
|
1824
|
-
var
|
|
2443
|
+
var result_1 = handler(event, context);
|
|
1825
2444
|
// check if handler returns a promise
|
|
1826
|
-
if (
|
|
1827
|
-
|
|
1828
|
-
.then(resolve)
|
|
1829
|
-
.catch(function (err) { return reportToHoneybadger(hb, err, reject); })
|
|
2445
|
+
if (result_1 && result_1.then) {
|
|
2446
|
+
result_1
|
|
2447
|
+
.then(function (value) { return Promise.resolve(emit === null || emit === void 0 ? void 0 : emit(lambdaStatus(value))).then(function () { return resolve(value); }); })
|
|
2448
|
+
.catch(function (err) { return Promise.resolve(emit === null || emit === void 0 ? void 0 : emit(500)).then(function () { return reportToHoneybadger(hb, err, reject); }); })
|
|
1830
2449
|
.finally(function () { return clearTimeout(timeoutHandler); });
|
|
1831
2450
|
}
|
|
1832
2451
|
else {
|
|
1833
2452
|
clearTimeout(timeoutHandler);
|
|
1834
|
-
resolve(
|
|
2453
|
+
Promise.resolve(emit === null || emit === void 0 ? void 0 : emit(lambdaStatus(result_1))).then(function () { return resolve(result_1); });
|
|
1835
2454
|
}
|
|
1836
2455
|
}
|
|
1837
2456
|
catch (err) {
|
|
1838
2457
|
clearTimeout(timeoutHandler);
|
|
1839
|
-
reportToHoneybadger(hb, err, reject);
|
|
2458
|
+
Promise.resolve(emit === null || emit === void 0 ? void 0 : emit(500)).then(function () { return reportToHoneybadger(hb, err, reject); });
|
|
1840
2459
|
}
|
|
1841
2460
|
});
|
|
1842
2461
|
});
|
|
@@ -1845,19 +2464,22 @@ function asyncHandler(handler, hb) {
|
|
|
1845
2464
|
function syncHandler(handler, hb) {
|
|
1846
2465
|
return function wrappedLambdaHandler(event, context, cb) {
|
|
1847
2466
|
hb.run(function () {
|
|
2467
|
+
seedLambdaEventContext(hb, event, context);
|
|
2468
|
+
var emit = createLambdaRequestEmitter(hb, event);
|
|
1848
2469
|
var timeoutHandler = setupTimeoutWarning(hb, context);
|
|
1849
2470
|
try {
|
|
1850
2471
|
handler(event, context, function (error, result) {
|
|
1851
2472
|
clearTimeout(timeoutHandler);
|
|
1852
2473
|
if (error) {
|
|
1853
|
-
return reportToHoneybadger(hb, error, cb);
|
|
2474
|
+
Promise.resolve(emit === null || emit === void 0 ? void 0 : emit(500)).then(function () { return reportToHoneybadger(hb, error, cb); });
|
|
2475
|
+
return;
|
|
1854
2476
|
}
|
|
1855
|
-
cb(null, result);
|
|
2477
|
+
Promise.resolve(emit === null || emit === void 0 ? void 0 : emit(lambdaStatus(result))).then(function () { return cb(null, result); });
|
|
1856
2478
|
});
|
|
1857
2479
|
}
|
|
1858
2480
|
catch (err) {
|
|
1859
2481
|
clearTimeout(timeoutHandler);
|
|
1860
|
-
reportToHoneybadger(hb, err, cb);
|
|
2482
|
+
Promise.resolve(emit === null || emit === void 0 ? void 0 : emit(500)).then(function () { return reportToHoneybadger(hb, err, cb); });
|
|
1861
2483
|
}
|
|
1862
2484
|
});
|
|
1863
2485
|
};
|
|
@@ -2130,6 +2752,7 @@ var ShutdownMonitor = /** @class */ (function () {
|
|
|
2130
2752
|
function ShutdownMonitor() {
|
|
2131
2753
|
this.__isReporting = false;
|
|
2132
2754
|
this.__listener = this.makeListener();
|
|
2755
|
+
this.__beforeExitListener = this.makeBeforeExitListener();
|
|
2133
2756
|
}
|
|
2134
2757
|
ShutdownMonitor.prototype.setClient = function (client) {
|
|
2135
2758
|
this.__client = client;
|
|
@@ -2158,6 +2781,35 @@ var ShutdownMonitor = /** @class */ (function () {
|
|
|
2158
2781
|
}); };
|
|
2159
2782
|
return honeybadgerShutdownListener;
|
|
2160
2783
|
};
|
|
2784
|
+
// `beforeExit` fires when the event loop drains and the process is about to
|
|
2785
|
+
// exit on its own — a natural exit, which the SIGTERM/SIGINT listeners above do
|
|
2786
|
+
// *not* cover. We flush any queued events (e.g. batched Insights events whose
|
|
2787
|
+
// cooldown timer is unref'd and therefore won't hold the process open) so they
|
|
2788
|
+
// aren't dropped on the way out. Unlike the signal path we don't force-exit;
|
|
2789
|
+
// flushing schedules real I/O, which keeps the process alive until delivery, and
|
|
2790
|
+
// then Node exits naturally. The `__isReporting` guard stops the flush's own I/O
|
|
2791
|
+
// from re-triggering us.
|
|
2792
|
+
ShutdownMonitor.prototype.makeBeforeExitListener = function () {
|
|
2793
|
+
var _this = this;
|
|
2794
|
+
// noinspection UnnecessaryLocalVariableJS
|
|
2795
|
+
var honeybadgerBeforeExitListener = function () { return __awaiter$1(_this, void 0, void 0, function () {
|
|
2796
|
+
return __generator$1(this, function (_a) {
|
|
2797
|
+
switch (_a.label) {
|
|
2798
|
+
case 0:
|
|
2799
|
+
if (this.__isReporting || !this.__client) {
|
|
2800
|
+
return [2 /*return*/];
|
|
2801
|
+
}
|
|
2802
|
+
this.__isReporting = true;
|
|
2803
|
+
return [4 /*yield*/, this.__client.flushAsync()];
|
|
2804
|
+
case 1:
|
|
2805
|
+
_a.sent();
|
|
2806
|
+
this.__isReporting = false;
|
|
2807
|
+
return [2 /*return*/];
|
|
2808
|
+
}
|
|
2809
|
+
});
|
|
2810
|
+
}); };
|
|
2811
|
+
return honeybadgerBeforeExitListener;
|
|
2812
|
+
};
|
|
2161
2813
|
ShutdownMonitor.prototype.maybeAddListener = function () {
|
|
2162
2814
|
for (var _i = 0, _a = ShutdownMonitor.KILL_SIGNALS; _i < _a.length; _i++) {
|
|
2163
2815
|
var signal = _a[_i];
|
|
@@ -2166,6 +2818,10 @@ var ShutdownMonitor = /** @class */ (function () {
|
|
|
2166
2818
|
process.on(signal, this.__listener);
|
|
2167
2819
|
}
|
|
2168
2820
|
}
|
|
2821
|
+
var beforeExitListeners = process.listeners('beforeExit') || [];
|
|
2822
|
+
if (!beforeExitListeners.includes(this.__beforeExitListener)) {
|
|
2823
|
+
process.on('beforeExit', this.__beforeExitListener);
|
|
2824
|
+
}
|
|
2169
2825
|
};
|
|
2170
2826
|
ShutdownMonitor.prototype.maybeRemoveListener = function () {
|
|
2171
2827
|
for (var _i = 0, _a = ShutdownMonitor.KILL_SIGNALS; _i < _a.length; _i++) {
|
|
@@ -2175,6 +2831,10 @@ var ShutdownMonitor = /** @class */ (function () {
|
|
|
2175
2831
|
process.removeListener(signal, this.__listener);
|
|
2176
2832
|
}
|
|
2177
2833
|
}
|
|
2834
|
+
var beforeExitListeners = process.listeners('beforeExit') || [];
|
|
2835
|
+
if (beforeExitListeners.includes(this.__beforeExitListener)) {
|
|
2836
|
+
process.removeListener('beforeExit', this.__beforeExitListener);
|
|
2837
|
+
}
|
|
2178
2838
|
};
|
|
2179
2839
|
ShutdownMonitor.prototype.hasOtherShutdownListeners = function (signal) {
|
|
2180
2840
|
var _this = this;
|
|
@@ -2199,14 +2859,9 @@ function default_1() {
|
|
|
2199
2859
|
return {
|
|
2200
2860
|
load: function (client) {
|
|
2201
2861
|
shutdownMonitor.setClient(client);
|
|
2202
|
-
//
|
|
2203
|
-
//
|
|
2204
|
-
|
|
2205
|
-
shutdownMonitor.maybeAddListener();
|
|
2206
|
-
}
|
|
2207
|
-
else {
|
|
2208
|
-
shutdownMonitor.maybeRemoveListener();
|
|
2209
|
-
}
|
|
2862
|
+
// programmatic events can be queued at any time, so the flush listener
|
|
2863
|
+
// is always registered
|
|
2864
|
+
shutdownMonitor.maybeAddListener();
|
|
2210
2865
|
},
|
|
2211
2866
|
shouldReloadOnConfigure: true,
|
|
2212
2867
|
};
|
|
@@ -2220,7 +2875,9 @@ var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || func
|
|
|
2220
2875
|
};
|
|
2221
2876
|
Object.defineProperty(middleware, "__esModule", { value: true });
|
|
2222
2877
|
middleware.errorHandler = middleware.requestHandler = void 0;
|
|
2223
|
-
var url_1$1 = __importDefault(require$$0__default$
|
|
2878
|
+
var url_1$1 = __importDefault(require$$0__default$2["default"]);
|
|
2879
|
+
var core_1$4 = src;
|
|
2880
|
+
var http_event_1 = http_event;
|
|
2224
2881
|
function fullUrl(req) {
|
|
2225
2882
|
var connection = req.connection;
|
|
2226
2883
|
var address = connection && connection.address();
|
|
@@ -2235,8 +2892,43 @@ function fullUrl(req) {
|
|
|
2235
2892
|
query: req.query
|
|
2236
2893
|
});
|
|
2237
2894
|
}
|
|
2895
|
+
function instrumentInboundRequest(client, req, res) {
|
|
2896
|
+
// Completion is observed via response events, which requires a Node
|
|
2897
|
+
// ServerResponse. A non-EventEmitter response (e.g. a FastifyReply when this
|
|
2898
|
+
// middleware is mistakenly registered as a fastify preHandler) would break
|
|
2899
|
+
// every request — degrade to "no request event" instead. Fastify users
|
|
2900
|
+
// should register fastifyPlugin() from server/fastify.
|
|
2901
|
+
if (typeof res.once !== 'function') {
|
|
2902
|
+
client.logger.debug('skipping insights instrumentation for http requests: response object is not an EventEmitter and does not have a .once() hook');
|
|
2903
|
+
return;
|
|
2904
|
+
}
|
|
2905
|
+
var start = (0, http_event_1.startTimer)();
|
|
2906
|
+
var emitted = false;
|
|
2907
|
+
var emit = function () {
|
|
2908
|
+
var _a;
|
|
2909
|
+
if (emitted)
|
|
2910
|
+
return;
|
|
2911
|
+
emitted = true;
|
|
2912
|
+
client.event('request.handled', (0, http_event_1.buildRequestEventPayload)({
|
|
2913
|
+
method: req.method,
|
|
2914
|
+
path: req.path,
|
|
2915
|
+
route: (_a = req.route) === null || _a === void 0 ? void 0 : _a.path,
|
|
2916
|
+
status: res.statusCode,
|
|
2917
|
+
duration: (0, http_event_1.durationMs)(start),
|
|
2918
|
+
}));
|
|
2919
|
+
};
|
|
2920
|
+
res.once('finish', emit);
|
|
2921
|
+
res.once('close', emit);
|
|
2922
|
+
}
|
|
2238
2923
|
function requestHandler(req, res, next) {
|
|
2239
|
-
|
|
2924
|
+
var _this = this;
|
|
2925
|
+
this.withRequest(req, function () {
|
|
2926
|
+
_this.setEventContext((0, http_event_1.seedRequestEventContext)(req.headers));
|
|
2927
|
+
if (core_1$4.Util.resolveInsights(_this.config).http) {
|
|
2928
|
+
instrumentInboundRequest(_this, req, res);
|
|
2929
|
+
}
|
|
2930
|
+
next();
|
|
2931
|
+
}, next);
|
|
2240
2932
|
}
|
|
2241
2933
|
middleware.requestHandler = requestHandler;
|
|
2242
2934
|
function errorHandler(err, req, _res, next) {
|
|
@@ -2294,12 +2986,12 @@ var __importStar = (commonjsGlobal && commonjsGlobal.__importStar) || function (
|
|
|
2294
2986
|
};
|
|
2295
2987
|
Object.defineProperty(transport, "__esModule", { value: true });
|
|
2296
2988
|
transport.ServerTransport = void 0;
|
|
2297
|
-
var core_1$
|
|
2298
|
-
var url_1 = require$$0__default$
|
|
2989
|
+
var core_1$3 = src;
|
|
2990
|
+
var url_1 = require$$0__default$2["default"];
|
|
2299
2991
|
var util_1 = util;
|
|
2300
2992
|
var http = __importStar(require$$3__default$1["default"]);
|
|
2301
2993
|
var https = __importStar(require$$4__default["default"]);
|
|
2302
|
-
var sanitize = core_1$
|
|
2994
|
+
var sanitize = core_1$3.Util.sanitize;
|
|
2303
2995
|
var ServerTransport = /** @class */ (function () {
|
|
2304
2996
|
function ServerTransport(headers) {
|
|
2305
2997
|
if (headers === void 0) { headers = {}; }
|
|
@@ -2375,6 +3067,8 @@ var async_store = {};
|
|
|
2375
3067
|
|
|
2376
3068
|
Object.defineProperty(async_store, "__esModule", { value: true });
|
|
2377
3069
|
async_store.AsyncStore = void 0;
|
|
3070
|
+
var core_1$2 = src;
|
|
3071
|
+
var clone = core_1$2.Util.clone;
|
|
2378
3072
|
var kHoneybadgerStore = Symbol.for('kHoneybadgerStore');
|
|
2379
3073
|
var AsyncStore = /** @class */ (function () {
|
|
2380
3074
|
function AsyncStore(asyncLocalStorage, contents, breadcrumbsLimit) {
|
|
@@ -2405,7 +3099,10 @@ var AsyncStore = /** @class */ (function () {
|
|
|
2405
3099
|
};
|
|
2406
3100
|
AsyncStore.prototype.getContents = function (key) {
|
|
2407
3101
|
var value = key ? this.__currentContents()[key] : this.__currentContents();
|
|
2408
|
-
|
|
3102
|
+
// Deep copy like a JSON round trip, but tolerate circular references in
|
|
3103
|
+
// host-supplied context and breadcrumb metadata. See GlobalStore.
|
|
3104
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
3105
|
+
return clone(value);
|
|
2409
3106
|
};
|
|
2410
3107
|
AsyncStore.prototype.available = function () {
|
|
2411
3108
|
return !!this.als.getStore();
|
|
@@ -2413,6 +3110,12 @@ var AsyncStore = /** @class */ (function () {
|
|
|
2413
3110
|
AsyncStore.prototype.setContext = function (context) {
|
|
2414
3111
|
Object.assign(this.__currentContents().context, context || {});
|
|
2415
3112
|
};
|
|
3113
|
+
AsyncStore.prototype.setEventContext = function (eventContext) {
|
|
3114
|
+
Object.assign(this.__currentContents().eventContext, eventContext || {});
|
|
3115
|
+
};
|
|
3116
|
+
AsyncStore.prototype.clearEventContext = function () {
|
|
3117
|
+
this.__currentContents().eventContext = {};
|
|
3118
|
+
};
|
|
2416
3119
|
AsyncStore.prototype.addBreadcrumb = function (breadcrumb) {
|
|
2417
3120
|
if (this.__currentContents().breadcrumbs.length == this.breadcrumbsLimit) {
|
|
2418
3121
|
this.__currentContents().breadcrumbs.shift();
|
|
@@ -2421,6 +3124,7 @@ var AsyncStore = /** @class */ (function () {
|
|
|
2421
3124
|
};
|
|
2422
3125
|
AsyncStore.prototype.clear = function () {
|
|
2423
3126
|
this.__currentContents().context = {};
|
|
3127
|
+
this.__currentContents().eventContext = {};
|
|
2424
3128
|
this.__currentContents().breadcrumbs = [];
|
|
2425
3129
|
};
|
|
2426
3130
|
AsyncStore.prototype.run = function (callback, request) {
|
|
@@ -2457,7 +3161,7 @@ var async_store_1 = async_store;
|
|
|
2457
3161
|
*/
|
|
2458
3162
|
var StackedStore = /** @class */ (function () {
|
|
2459
3163
|
function StackedStore(breadcrumbsLimit) {
|
|
2460
|
-
this.contents = { context: {}, breadcrumbs: [] };
|
|
3164
|
+
this.contents = { context: {}, eventContext: {}, breadcrumbs: [] };
|
|
2461
3165
|
this.asyncStore = async_store_1.AsyncStore.create(this.contents, breadcrumbsLimit);
|
|
2462
3166
|
this.globalStore = core_1$1.GlobalStore.create(this.contents, breadcrumbsLimit);
|
|
2463
3167
|
}
|
|
@@ -2475,6 +3179,12 @@ var StackedStore = /** @class */ (function () {
|
|
|
2475
3179
|
StackedStore.prototype.setContext = function (context) {
|
|
2476
3180
|
this.__activeStore().setContext(context);
|
|
2477
3181
|
};
|
|
3182
|
+
StackedStore.prototype.setEventContext = function (eventContext) {
|
|
3183
|
+
this.__activeStore().setEventContext(eventContext);
|
|
3184
|
+
};
|
|
3185
|
+
StackedStore.prototype.clearEventContext = function () {
|
|
3186
|
+
this.__activeStore().clearEventContext();
|
|
3187
|
+
};
|
|
2478
3188
|
StackedStore.prototype.addBreadcrumb = function (breadcrumb) {
|
|
2479
3189
|
this.__activeStore().addBreadcrumb(breadcrumb);
|
|
2480
3190
|
};
|
|
@@ -3121,7 +3831,7 @@ client.CheckInsClient = CheckInsClient;
|
|
|
3121
3831
|
(0, uncaught_exception_plugin_1.default)(),
|
|
3122
3832
|
(0, unhandled_rejection_plugin_1.default)(),
|
|
3123
3833
|
(0, shutdown_plugin_1.default)(),
|
|
3124
|
-
core_1.Plugins.
|
|
3834
|
+
core_1.Plugins.consoleEvents(),
|
|
3125
3835
|
];
|
|
3126
3836
|
var Honeybadger = /** @class */ (function (_super) {
|
|
3127
3837
|
__extends(Honeybadger, _super);
|
|
@@ -3279,7 +3989,7 @@ client.CheckInsClient = CheckInsClient;
|
|
|
3279
3989
|
var NOTIFIER = {
|
|
3280
3990
|
name: '@honeybadger-io/js',
|
|
3281
3991
|
url: 'https://github.com/honeybadger-io/honeybadger-js/tree/master/packages/js',
|
|
3282
|
-
version: '6.
|
|
3992
|
+
version: '6.16.1'
|
|
3283
3993
|
};
|
|
3284
3994
|
var userAgent = function () {
|
|
3285
3995
|
return "Honeybadger JS Server Client ".concat(NOTIFIER.version, ", ").concat(os_1.default.version(), "; ").concat(os_1.default.platform());
|