@honeybadger-io/js 4.0.0-beta.5 → 4.0.2
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.d.ts +4 -7
- package/dist/browser/honeybadger.js +140 -66
- 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/browser/transport.d.ts +7 -0
- package/dist/browser/types/browser.d.ts +4 -7
- package/dist/browser/types/core/client.d.ts +9 -8
- package/dist/browser/types/core/store.d.ts +1 -1
- package/dist/browser/types/core/types.d.ts +64 -1
- package/dist/browser/types/core/util.d.ts +4 -3
- package/dist/browser/types/server/async_store.d.ts +1 -1
- package/dist/browser/types/server/aws_lambda.d.ts +2 -1
- package/dist/browser/types/server/transport.d.ts +9 -0
- package/dist/browser/types/server/util.d.ts +3 -3
- package/dist/browser/types/server.d.ts +7 -4
- package/dist/server/honeybadger.d.ts +7 -4
- package/dist/server/honeybadger.js +283 -127
- package/dist/server/types/browser/transport.d.ts +7 -0
- package/dist/server/types/browser.d.ts +4 -7
- package/dist/server/types/core/client.d.ts +9 -8
- package/dist/server/types/core/store.d.ts +1 -1
- package/dist/server/types/core/types.d.ts +64 -1
- package/dist/server/types/core/util.d.ts +4 -3
- package/dist/server/types/server/async_store.d.ts +1 -1
- package/dist/server/types/server/aws_lambda.d.ts +2 -1
- package/dist/server/types/server/transport.d.ts +9 -0
- package/dist/server/types/server/util.d.ts +3 -3
- package/dist/server/types/server.d.ts +7 -4
- package/package.json +4 -4
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var https = require('https');
|
|
4
|
-
var http = require('http');
|
|
5
|
-
var url = require('url');
|
|
6
3
|
var os = require('os');
|
|
7
4
|
var domain = require('domain');
|
|
8
5
|
var fs = require('fs');
|
|
6
|
+
var util = require('util');
|
|
7
|
+
var url = require('url');
|
|
8
|
+
var http = require('http');
|
|
9
|
+
var https = require('https');
|
|
9
10
|
|
|
10
11
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
11
12
|
|
|
12
|
-
var https__default = /*#__PURE__*/_interopDefaultLegacy(https);
|
|
13
|
-
var http__default = /*#__PURE__*/_interopDefaultLegacy(http);
|
|
14
|
-
var url__default = /*#__PURE__*/_interopDefaultLegacy(url);
|
|
15
13
|
var os__default = /*#__PURE__*/_interopDefaultLegacy(os);
|
|
16
14
|
var domain__default = /*#__PURE__*/_interopDefaultLegacy(domain);
|
|
17
15
|
var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
|
|
16
|
+
var url__default = /*#__PURE__*/_interopDefaultLegacy(url);
|
|
17
|
+
var http__default = /*#__PURE__*/_interopDefaultLegacy(http);
|
|
18
|
+
var https__default = /*#__PURE__*/_interopDefaultLegacy(https);
|
|
18
19
|
|
|
19
20
|
/*! *****************************************************************************
|
|
20
21
|
Copyright (c) Microsoft Corporation.
|
|
@@ -56,7 +57,45 @@ var __assign = function() {
|
|
|
56
57
|
return t;
|
|
57
58
|
};
|
|
58
59
|
return __assign.apply(this, arguments);
|
|
59
|
-
};
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
63
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
64
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
65
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
66
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
67
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
68
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function __generator(thisArg, body) {
|
|
73
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
74
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
75
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
76
|
+
function step(op) {
|
|
77
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
78
|
+
while (_) try {
|
|
79
|
+
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;
|
|
80
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
81
|
+
switch (op[0]) {
|
|
82
|
+
case 0: case 1: t = op; break;
|
|
83
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
84
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
85
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
86
|
+
default:
|
|
87
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
88
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
89
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
90
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
91
|
+
if (t[2]) _.ops.pop();
|
|
92
|
+
_.trys.pop(); continue;
|
|
93
|
+
}
|
|
94
|
+
op = body.call(thisArg, _);
|
|
95
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
96
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
60
99
|
|
|
61
100
|
var UNKNOWN_FUNCTION = '<unknown>';
|
|
62
101
|
/**
|
|
@@ -238,24 +277,31 @@ function makeBacktrace(stack, shift) {
|
|
|
238
277
|
return [];
|
|
239
278
|
}
|
|
240
279
|
}
|
|
241
|
-
function getSourceForBacktrace(backtrace, getSourceFileHandler
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
return
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
280
|
+
function getSourceForBacktrace(backtrace, getSourceFileHandler) {
|
|
281
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
282
|
+
var result, index, trace, fileContent;
|
|
283
|
+
return __generator(this, function (_a) {
|
|
284
|
+
switch (_a.label) {
|
|
285
|
+
case 0:
|
|
286
|
+
result = [];
|
|
287
|
+
if (!getSourceFileHandler || !backtrace || !backtrace.length) {
|
|
288
|
+
return [2 /*return*/, result];
|
|
289
|
+
}
|
|
290
|
+
index = 0;
|
|
291
|
+
_a.label = 1;
|
|
292
|
+
case 1:
|
|
293
|
+
if (!backtrace.length) return [3 /*break*/, 3];
|
|
294
|
+
trace = backtrace.splice(0)[index];
|
|
295
|
+
return [4 /*yield*/, getSourceFileHandler(trace.file)];
|
|
296
|
+
case 2:
|
|
297
|
+
fileContent = _a.sent();
|
|
298
|
+
result[index] = getSourceCodeSnippet(fileContent, trace.number);
|
|
299
|
+
index++;
|
|
300
|
+
return [3 /*break*/, 1];
|
|
301
|
+
case 3: return [2 /*return*/, result];
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
});
|
|
259
305
|
}
|
|
260
306
|
function runBeforeNotifyHandlers(notice, handlers) {
|
|
261
307
|
var result = true;
|
|
@@ -415,8 +461,8 @@ function makeNotice(thing) {
|
|
|
415
461
|
}
|
|
416
462
|
return notice;
|
|
417
463
|
}
|
|
418
|
-
function endpoint(
|
|
419
|
-
var endpoint =
|
|
464
|
+
function endpoint(base, path) {
|
|
465
|
+
var endpoint = base.trim().replace(/\/$/, '');
|
|
420
466
|
path = path.trim().replace(/(^\/|\/$)/g, '');
|
|
421
467
|
return "".concat(endpoint, "/").concat(path);
|
|
422
468
|
}
|
|
@@ -548,6 +594,9 @@ function getSourceCodeSnippet(fileData, lineNumber, sourceRadius) {
|
|
|
548
594
|
}
|
|
549
595
|
return result;
|
|
550
596
|
}
|
|
597
|
+
function isBrowserConfig(config) {
|
|
598
|
+
return config.async !== undefined;
|
|
599
|
+
}
|
|
551
600
|
|
|
552
601
|
var GlobalStore$1 = /** @class */ (function () {
|
|
553
602
|
function GlobalStore(store) {
|
|
@@ -570,14 +619,14 @@ var GlobalStore$1 = /** @class */ (function () {
|
|
|
570
619
|
var notifier = {
|
|
571
620
|
name: 'honeybadger-js',
|
|
572
621
|
url: 'https://github.com/honeybadger-io/honeybadger-js',
|
|
573
|
-
version: '4.0.
|
|
622
|
+
version: '4.0.2'
|
|
574
623
|
};
|
|
575
624
|
// Split at commas and spaces
|
|
576
625
|
var TAG_SEPARATOR = /,|\s+/;
|
|
577
626
|
// Checks for non-blank characters
|
|
578
627
|
var NOT_BLANK = /\S/;
|
|
579
628
|
var Client = /** @class */ (function () {
|
|
580
|
-
function Client(opts) {
|
|
629
|
+
function Client(opts, transport) {
|
|
581
630
|
if (opts === void 0) { opts = {}; }
|
|
582
631
|
this.__pluginsExecuted = false;
|
|
583
632
|
this.__store = null;
|
|
@@ -587,11 +636,9 @@ var Client = /** @class */ (function () {
|
|
|
587
636
|
// First, we go with the global (shared) store.
|
|
588
637
|
// Webserver middleware can then switch to the AsyncStore for async context tracking.
|
|
589
638
|
this.__store = new GlobalStore$1({ context: {}, breadcrumbs: [] });
|
|
639
|
+
this.__transport = transport;
|
|
590
640
|
this.logger = logger(this);
|
|
591
641
|
}
|
|
592
|
-
Client.prototype.factory = function (_opts) {
|
|
593
|
-
throw (new Error('Must implement __factory in subclass'));
|
|
594
|
-
};
|
|
595
642
|
Client.prototype.getVersion = function () {
|
|
596
643
|
return notifier.version;
|
|
597
644
|
};
|
|
@@ -665,6 +712,9 @@ var Client = /** @class */ (function () {
|
|
|
665
712
|
this.logger.warn('could not send error report: no API key has been configured', notice);
|
|
666
713
|
preConditionError = new Error('missing API key');
|
|
667
714
|
}
|
|
715
|
+
// we need to have the source file data before the beforeNotifyHandlers,
|
|
716
|
+
// in case they modify them
|
|
717
|
+
var sourceCodeData = notice && notice.backtrace ? notice.backtrace.map(function (trace) { return shallowClone(trace); }) : null;
|
|
668
718
|
var beforeNotifyResult = runBeforeNotifyHandlers(notice, this.__beforeNotifyHandlers);
|
|
669
719
|
if (!preConditionError && !beforeNotifyResult) {
|
|
670
720
|
this.logger.debug('skipping error report: beforeNotify handlers returned false', notice);
|
|
@@ -684,14 +734,41 @@ var Client = /** @class */ (function () {
|
|
|
684
734
|
});
|
|
685
735
|
var breadcrumbs = this.__getStoreContentsOrDefault().breadcrumbs;
|
|
686
736
|
notice.__breadcrumbs = this.config.breadcrumbsEnabled ? breadcrumbs.slice() : [];
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
var sourceCodeData = notice && notice.backtrace ? notice.backtrace.map(function (trace) { return shallowClone(trace); }) : null;
|
|
690
|
-
getSourceForBacktrace(sourceCodeData, this.__getSourceFileHandler, function (sourcePerTrace) {
|
|
737
|
+
getSourceForBacktrace(sourceCodeData, this.__getSourceFileHandler)
|
|
738
|
+
.then(function (sourcePerTrace) {
|
|
691
739
|
sourcePerTrace.forEach(function (source, index) {
|
|
692
740
|
notice.backtrace[index].source = source;
|
|
693
741
|
});
|
|
694
|
-
_this.
|
|
742
|
+
var payload = _this.__buildPayload(notice);
|
|
743
|
+
_this.__transport
|
|
744
|
+
.send({
|
|
745
|
+
headers: {
|
|
746
|
+
'X-API-Key': _this.config.apiKey,
|
|
747
|
+
'Content-Type': 'application/json',
|
|
748
|
+
'Accept': 'text/json, application/json'
|
|
749
|
+
},
|
|
750
|
+
method: 'POST',
|
|
751
|
+
endpoint: endpoint(_this.config.endpoint, '/v1/notices/js'),
|
|
752
|
+
maxObjectDepth: _this.config.maxObjectDepth,
|
|
753
|
+
logger: _this.logger,
|
|
754
|
+
async: isBrowserConfig(_this.config) ? _this.config.async : undefined,
|
|
755
|
+
}, payload)
|
|
756
|
+
.then(function (res) {
|
|
757
|
+
if (res.statusCode !== 201) {
|
|
758
|
+
runAfterNotifyHandlers(notice, _this.__afterNotifyHandlers, new Error("Bad HTTP response: ".concat(res.statusCode)));
|
|
759
|
+
_this.logger.warn("Error report failed: unknown response from server. code=".concat(res.statusCode));
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
var uuid = JSON.parse(res.body).id;
|
|
763
|
+
runAfterNotifyHandlers(merge(notice, {
|
|
764
|
+
id: uuid
|
|
765
|
+
}), _this.__afterNotifyHandlers);
|
|
766
|
+
_this.logger.info("Error report sent \u26A1 https://app.honeybadger.io/notice/".concat(uuid));
|
|
767
|
+
})
|
|
768
|
+
.catch(function (err) {
|
|
769
|
+
_this.logger.error('Error report failed: an unknown error occurred.', "message=".concat(err.message));
|
|
770
|
+
runAfterNotifyHandlers(notice, _this.__afterNotifyHandlers, err);
|
|
771
|
+
});
|
|
695
772
|
});
|
|
696
773
|
return true;
|
|
697
774
|
};
|
|
@@ -759,7 +836,7 @@ var Client = /** @class */ (function () {
|
|
|
759
836
|
}
|
|
760
837
|
var context = this.__getStoreContentsOrDefault().context;
|
|
761
838
|
var noticeTags = this.__constructTags(notice.tags);
|
|
762
|
-
var contextTags = this.__constructTags(context[
|
|
839
|
+
var contextTags = this.__constructTags(context['tags']);
|
|
763
840
|
var configTags = this.__constructTags(this.config.tags);
|
|
764
841
|
// Turning into a Set will remove duplicates
|
|
765
842
|
var tags = noticeTags.concat(contextTags).concat(configTags);
|
|
@@ -811,9 +888,6 @@ var Client = /** @class */ (function () {
|
|
|
811
888
|
}
|
|
812
889
|
return (this.config.environment && this.config.developmentEnvironments.includes(this.config.environment));
|
|
813
890
|
};
|
|
814
|
-
Client.prototype.__send = function (_notice) {
|
|
815
|
-
throw (new Error('Must implement send in subclass'));
|
|
816
|
-
};
|
|
817
891
|
Client.prototype.__buildPayload = function (notice) {
|
|
818
892
|
var headers = filter(notice.headers, this.config.filters) || {};
|
|
819
893
|
var cgiData = filter(__assign(__assign({}, notice.cgiData), formatCGIData(headers, 'HTTP_')), this.config.filters);
|
|
@@ -869,59 +943,86 @@ var Client = /** @class */ (function () {
|
|
|
869
943
|
return Client;
|
|
870
944
|
}());
|
|
871
945
|
|
|
946
|
+
var readFile = util.promisify(fs__default["default"].readFile);
|
|
872
947
|
function fatallyLogAndExit(err) {
|
|
873
948
|
console.error('[Honeybadger] Exiting process due to uncaught exception');
|
|
874
949
|
console.error(err.stack || err);
|
|
875
950
|
process.exit(1);
|
|
876
951
|
}
|
|
877
|
-
function getStats(
|
|
878
|
-
|
|
879
|
-
load
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
952
|
+
function getStats() {
|
|
953
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
954
|
+
var load, stats, fallback, memData, data, results;
|
|
955
|
+
return __generator(this, function (_a) {
|
|
956
|
+
switch (_a.label) {
|
|
957
|
+
case 0:
|
|
958
|
+
load = os__default["default"].loadavg();
|
|
959
|
+
stats = {
|
|
960
|
+
load: {
|
|
961
|
+
one: load[0],
|
|
962
|
+
five: load[1],
|
|
963
|
+
fifteen: load[2]
|
|
964
|
+
},
|
|
965
|
+
mem: {}
|
|
966
|
+
};
|
|
967
|
+
fallback = function () {
|
|
968
|
+
stats.mem = {
|
|
969
|
+
free: os__default["default"].freemem(),
|
|
970
|
+
total: os__default["default"].totalmem()
|
|
971
|
+
};
|
|
972
|
+
};
|
|
973
|
+
if (!fs__default["default"].existsSync('/proc/meminfo')) {
|
|
974
|
+
fallback();
|
|
975
|
+
return [2 /*return*/, stats];
|
|
976
|
+
}
|
|
977
|
+
_a.label = 1;
|
|
978
|
+
case 1:
|
|
979
|
+
_a.trys.push([1, 3, , 4]);
|
|
980
|
+
return [4 /*yield*/, readFile('/proc/meminfo', 'utf8')
|
|
981
|
+
// The first four lines, in order, are Total, Free, Buffers, Cached.
|
|
982
|
+
// @TODO: Figure out if there's a way to only read these lines
|
|
983
|
+
];
|
|
984
|
+
case 2:
|
|
985
|
+
memData = _a.sent();
|
|
986
|
+
data = memData.split('\n').slice(0, 4);
|
|
987
|
+
results = data.map(function (i) {
|
|
988
|
+
return parseInt(/\s+(\d+)\skB/i.exec(i)[1], 10) / 1024.0;
|
|
989
|
+
});
|
|
990
|
+
stats.mem = {
|
|
991
|
+
total: results[0],
|
|
992
|
+
free: results[1],
|
|
993
|
+
buffers: results[2],
|
|
994
|
+
cached: results[3],
|
|
995
|
+
free_total: results[1] + results[2] + results[3]
|
|
996
|
+
};
|
|
997
|
+
return [3 /*break*/, 4];
|
|
998
|
+
case 3:
|
|
999
|
+
_a.sent();
|
|
1000
|
+
fallback();
|
|
1001
|
+
return [3 /*break*/, 4];
|
|
1002
|
+
case 4: return [2 /*return*/, stats];
|
|
1003
|
+
}
|
|
898
1004
|
});
|
|
899
|
-
|
|
900
|
-
total: results[0],
|
|
901
|
-
free: results[1],
|
|
902
|
-
buffers: results[2],
|
|
903
|
-
cached: results[3],
|
|
904
|
-
free_total: results[1] + results[2] + results[3]
|
|
905
|
-
};
|
|
906
|
-
return cb(stats);
|
|
907
|
-
}
|
|
908
|
-
function fallback() {
|
|
909
|
-
stats.mem = {
|
|
910
|
-
free: os__default["default"].freemem(),
|
|
911
|
-
total: os__default["default"].totalmem()
|
|
912
|
-
};
|
|
913
|
-
return cb(stats);
|
|
914
|
-
}
|
|
1005
|
+
});
|
|
915
1006
|
}
|
|
916
1007
|
/**
|
|
917
1008
|
* Get source file if possible, used to build `notice.backtrace.source`
|
|
918
1009
|
*
|
|
919
1010
|
* @param path to source code
|
|
920
|
-
* @param cb callback with fileContent
|
|
921
1011
|
*/
|
|
922
|
-
function getSourceFile(path
|
|
923
|
-
|
|
924
|
-
|
|
1012
|
+
function getSourceFile(path) {
|
|
1013
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1014
|
+
return __generator(this, function (_a) {
|
|
1015
|
+
switch (_a.label) {
|
|
1016
|
+
case 0:
|
|
1017
|
+
_a.trys.push([0, 2, , 3]);
|
|
1018
|
+
return [4 /*yield*/, readFile(path, 'utf-8')];
|
|
1019
|
+
case 1: return [2 /*return*/, _a.sent()];
|
|
1020
|
+
case 2:
|
|
1021
|
+
_a.sent();
|
|
1022
|
+
return [2 /*return*/, null];
|
|
1023
|
+
case 3: return [2 /*return*/];
|
|
1024
|
+
}
|
|
1025
|
+
});
|
|
925
1026
|
});
|
|
926
1027
|
}
|
|
927
1028
|
|
|
@@ -954,12 +1055,15 @@ function asyncHandler(handler, hb) {
|
|
|
954
1055
|
hb.__setStore(AsyncStore);
|
|
955
1056
|
return new Promise(function (resolve, reject) {
|
|
956
1057
|
AsyncStore.run({ context: {}, breadcrumbs: [] }, function () {
|
|
1058
|
+
var timeoutHandler = setupTimeoutWarning(hb, context);
|
|
957
1059
|
try {
|
|
958
1060
|
handler(event, context)
|
|
959
1061
|
.then(resolve)
|
|
960
|
-
.catch(function (err) { return reportToHoneybadger(hb, err, reject); })
|
|
1062
|
+
.catch(function (err) { return reportToHoneybadger(hb, err, reject); })
|
|
1063
|
+
.finally(function () { return clearTimeout(timeoutHandler); });
|
|
961
1064
|
}
|
|
962
1065
|
catch (err) {
|
|
1066
|
+
clearTimeout(timeoutHandler);
|
|
963
1067
|
reportToHoneybadger(hb, err, reject);
|
|
964
1068
|
}
|
|
965
1069
|
});
|
|
@@ -970,8 +1074,10 @@ function syncHandler(handler, hb) {
|
|
|
970
1074
|
return function wrappedLambdaHandler(event, context, cb) {
|
|
971
1075
|
hb.__setStore(AsyncStore);
|
|
972
1076
|
AsyncStore.run({ context: {}, breadcrumbs: [] }, function () {
|
|
1077
|
+
var timeoutHandler = setupTimeoutWarning(hb, context);
|
|
973
1078
|
try {
|
|
974
1079
|
handler(event, context, function (error, result) {
|
|
1080
|
+
clearTimeout(timeoutHandler);
|
|
975
1081
|
if (error) {
|
|
976
1082
|
return reportToHoneybadger(hb, error, cb);
|
|
977
1083
|
}
|
|
@@ -979,11 +1085,24 @@ function syncHandler(handler, hb) {
|
|
|
979
1085
|
});
|
|
980
1086
|
}
|
|
981
1087
|
catch (err) {
|
|
1088
|
+
clearTimeout(timeoutHandler);
|
|
982
1089
|
reportToHoneybadger(hb, err, cb);
|
|
983
1090
|
}
|
|
984
1091
|
});
|
|
985
1092
|
};
|
|
986
1093
|
}
|
|
1094
|
+
function shouldReportTimeoutWarning(hb, context) {
|
|
1095
|
+
return typeof context.getRemainingTimeInMillis === 'function' && !!(hb.config.reportTimeoutWarning);
|
|
1096
|
+
}
|
|
1097
|
+
function setupTimeoutWarning(hb, context) {
|
|
1098
|
+
if (!shouldReportTimeoutWarning(hb, context)) {
|
|
1099
|
+
return;
|
|
1100
|
+
}
|
|
1101
|
+
var delay = context.getRemainingTimeInMillis() - (hb.config.timeoutWarningThresholdMs);
|
|
1102
|
+
return setTimeout(function () {
|
|
1103
|
+
hb.notify("".concat(context.functionName, "[").concat(context.functionVersion, "] may have timed out"));
|
|
1104
|
+
}, delay > 0 ? delay : 0);
|
|
1105
|
+
}
|
|
987
1106
|
function lambdaHandler(handler) {
|
|
988
1107
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
989
1108
|
var hb = this;
|
|
@@ -1096,12 +1215,69 @@ function errorHandler(err, req, _res, next) {
|
|
|
1096
1215
|
}
|
|
1097
1216
|
}
|
|
1098
1217
|
|
|
1099
|
-
var
|
|
1218
|
+
var ServerTransport = /** @class */ (function () {
|
|
1219
|
+
function ServerTransport() {
|
|
1220
|
+
}
|
|
1221
|
+
ServerTransport.prototype.send = function (options, payload) {
|
|
1222
|
+
var _this = this;
|
|
1223
|
+
var protocol = new url.URL(options.endpoint).protocol;
|
|
1224
|
+
var transport = (protocol === 'http:' ? http__default["default"] : https__default["default"]);
|
|
1225
|
+
return new Promise(function (resolve, reject) {
|
|
1226
|
+
var promise;
|
|
1227
|
+
// this should not be here. it should be done before reaching the transport layer
|
|
1228
|
+
// it could be inside a beforeNotifyHandler, but is not possible at the moment because those handlers are synchronous
|
|
1229
|
+
if (_this.isNoticePayload(payload)) {
|
|
1230
|
+
promise = _this.appendMetadata(payload);
|
|
1231
|
+
}
|
|
1232
|
+
else {
|
|
1233
|
+
promise = Promise.resolve();
|
|
1234
|
+
}
|
|
1235
|
+
promise.then(function () {
|
|
1236
|
+
var httpOptions = {
|
|
1237
|
+
method: options.method,
|
|
1238
|
+
headers: options.headers,
|
|
1239
|
+
};
|
|
1240
|
+
var data = undefined;
|
|
1241
|
+
if (payload) {
|
|
1242
|
+
data = Buffer.from(JSON.stringify(sanitize(payload, options.maxObjectDepth)), 'utf8');
|
|
1243
|
+
httpOptions.headers['Content-Length'] = data.length;
|
|
1244
|
+
}
|
|
1245
|
+
var req = transport.request(options.endpoint, httpOptions, function (res) {
|
|
1246
|
+
options.logger.debug("statusCode: ".concat(res.statusCode));
|
|
1247
|
+
var body = '';
|
|
1248
|
+
res.on('data', function (chunk) {
|
|
1249
|
+
body += chunk;
|
|
1250
|
+
});
|
|
1251
|
+
res.on('end', function () { return resolve({ statusCode: res.statusCode, body: body }); });
|
|
1252
|
+
});
|
|
1253
|
+
req.on('error', function (err) { return reject(err); });
|
|
1254
|
+
if (data) {
|
|
1255
|
+
req.write(data);
|
|
1256
|
+
}
|
|
1257
|
+
req.end();
|
|
1258
|
+
});
|
|
1259
|
+
});
|
|
1260
|
+
};
|
|
1261
|
+
ServerTransport.prototype.isNoticePayload = function (payload) {
|
|
1262
|
+
return payload && payload.error !== undefined;
|
|
1263
|
+
};
|
|
1264
|
+
ServerTransport.prototype.appendMetadata = function (payload) {
|
|
1265
|
+
payload.server.pid = process.pid;
|
|
1266
|
+
return getStats()
|
|
1267
|
+
.then(function (stats) {
|
|
1268
|
+
payload.server.stats = stats;
|
|
1269
|
+
});
|
|
1270
|
+
};
|
|
1271
|
+
return ServerTransport;
|
|
1272
|
+
}());
|
|
1273
|
+
|
|
1274
|
+
var kHoneybadgerStore = Symbol.for('kHoneybadgerStore');
|
|
1100
1275
|
var Honeybadger = /** @class */ (function (_super) {
|
|
1101
1276
|
__extends(Honeybadger, _super);
|
|
1102
1277
|
function Honeybadger(opts) {
|
|
1103
1278
|
if (opts === void 0) { opts = {}; }
|
|
1104
|
-
var
|
|
1279
|
+
var _a;
|
|
1280
|
+
var _this = _super.call(this, __assign({ afterUncaught: fatallyLogAndExit, projectRoot: process.cwd(), hostname: os__default["default"].hostname() }, opts), new ServerTransport()) || this;
|
|
1105
1281
|
/** @internal */
|
|
1106
1282
|
_this.__beforeNotifyHandlers = [
|
|
1107
1283
|
function (notice) {
|
|
@@ -1114,6 +1290,10 @@ var Honeybadger = /** @class */ (function (_super) {
|
|
|
1114
1290
|
});
|
|
1115
1291
|
}
|
|
1116
1292
|
];
|
|
1293
|
+
// serverless defaults
|
|
1294
|
+
var config = _this.config;
|
|
1295
|
+
config.reportTimeoutWarning = (_a = config.reportTimeoutWarning) !== null && _a !== void 0 ? _a : true;
|
|
1296
|
+
config.timeoutWarningThresholdMs = config.timeoutWarningThresholdMs || 50;
|
|
1117
1297
|
_this.__getSourceFileHandler = getSourceFile.bind(_this);
|
|
1118
1298
|
_this.errorHandler = errorHandler.bind(_this);
|
|
1119
1299
|
_this.requestHandler = requestHandler.bind(_this);
|
|
@@ -1121,51 +1301,27 @@ var Honeybadger = /** @class */ (function (_super) {
|
|
|
1121
1301
|
return _this;
|
|
1122
1302
|
}
|
|
1123
1303
|
Honeybadger.prototype.factory = function (opts) {
|
|
1304
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1124
1305
|
return new Honeybadger(opts);
|
|
1125
1306
|
};
|
|
1126
|
-
|
|
1127
|
-
|
|
1307
|
+
Honeybadger.prototype.configure = function (opts) {
|
|
1308
|
+
if (opts === void 0) { opts = {}; }
|
|
1309
|
+
return _super.prototype.configure.call(this, opts);
|
|
1310
|
+
};
|
|
1311
|
+
Honeybadger.prototype.checkIn = function (id) {
|
|
1128
1312
|
var _this = this;
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
'X-API-Key': _this.config.apiKey
|
|
1142
|
-
}
|
|
1143
|
-
};
|
|
1144
|
-
var req = transport.request(endpoint(_this.config, '/v1/notices/js'), options, function (res) {
|
|
1145
|
-
_this.logger.debug("statusCode: ".concat(res.statusCode));
|
|
1146
|
-
var body = '';
|
|
1147
|
-
res.on('data', function (chunk) {
|
|
1148
|
-
body += chunk;
|
|
1149
|
-
});
|
|
1150
|
-
res.on('end', function () {
|
|
1151
|
-
if (res.statusCode !== 201) {
|
|
1152
|
-
runAfterNotifyHandlers(notice, _this.__afterNotifyHandlers, new Error("Bad HTTP response: ".concat(res.statusCode)));
|
|
1153
|
-
_this.logger.warn("Error report failed: unknown response from server. code=".concat(res.statusCode));
|
|
1154
|
-
return;
|
|
1155
|
-
}
|
|
1156
|
-
var uuid = JSON.parse(body).id;
|
|
1157
|
-
runAfterNotifyHandlers(merge(notice, {
|
|
1158
|
-
id: uuid
|
|
1159
|
-
}), _this.__afterNotifyHandlers);
|
|
1160
|
-
_this.logger.info("Error report sent \u26A1 https://app.honeybadger.io/notice/".concat(uuid));
|
|
1161
|
-
});
|
|
1162
|
-
});
|
|
1163
|
-
req.on('error', function (err) {
|
|
1164
|
-
_this.logger.error('Error report failed: an unknown error occurred.', "message=".concat(err.message));
|
|
1165
|
-
runAfterNotifyHandlers(notice, _this.__afterNotifyHandlers, err);
|
|
1166
|
-
});
|
|
1167
|
-
req.write(data);
|
|
1168
|
-
req.end();
|
|
1313
|
+
return this.__transport
|
|
1314
|
+
.send({
|
|
1315
|
+
method: 'GET',
|
|
1316
|
+
endpoint: endpoint(this.config.endpoint, "v1/check_in/".concat(id)),
|
|
1317
|
+
logger: this.logger,
|
|
1318
|
+
})
|
|
1319
|
+
.then(function () {
|
|
1320
|
+
_this.logger.info('CheckIn sent');
|
|
1321
|
+
return Promise.resolve();
|
|
1322
|
+
})
|
|
1323
|
+
.catch(function (err) {
|
|
1324
|
+
_this.logger.error('CheckIn failed: an unknown error occurred.', "message=".concat(err.message));
|
|
1169
1325
|
});
|
|
1170
1326
|
};
|
|
1171
1327
|
// This method is intended for web frameworks.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Transport, TransportOptions, NoticeTransportPayload } from '../core/types';
|
|
2
|
+
export declare class BrowserTransport implements Transport {
|
|
3
|
+
send(options: TransportOptions, payload?: NoticeTransportPayload | undefined): Promise<{
|
|
4
|
+
statusCode: number;
|
|
5
|
+
body: string;
|
|
6
|
+
}>;
|
|
7
|
+
}
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import Client from './core/client';
|
|
2
|
-
import {
|
|
3
|
-
interface BrowserConfig extends Config {
|
|
4
|
-
async: boolean;
|
|
5
|
-
maxErrors: number;
|
|
6
|
-
}
|
|
2
|
+
import { BrowserConfig } from './core/types';
|
|
7
3
|
declare class Honeybadger extends Client {
|
|
8
4
|
config: BrowserConfig;
|
|
9
5
|
constructor(opts?: Partial<BrowserConfig>);
|
|
10
|
-
configure(opts?: Partial<BrowserConfig>):
|
|
6
|
+
configure(opts?: Partial<BrowserConfig>): this;
|
|
11
7
|
resetMaxErrors(): number;
|
|
12
|
-
factory(opts?: Partial<BrowserConfig>):
|
|
8
|
+
factory(opts?: Partial<BrowserConfig>): this;
|
|
9
|
+
checkIn(_id: string): Promise<void>;
|
|
13
10
|
}
|
|
14
11
|
declare const _default: Honeybadger;
|
|
15
12
|
export default _default;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Config, Logger, BeforeNotifyHandler, AfterNotifyHandler, Notice, Noticeable, HoneybadgerStore, BreadcrumbRecord } from './types';
|
|
2
|
-
export default class Client {
|
|
1
|
+
import { Config, Logger, BeforeNotifyHandler, AfterNotifyHandler, Notice, Noticeable, HoneybadgerStore, BreadcrumbRecord, Transport, NoticeTransportPayload } from './types';
|
|
2
|
+
export default abstract class Client {
|
|
3
3
|
protected __pluginsExecuted: boolean;
|
|
4
4
|
protected __store: HoneybadgerStore<{
|
|
5
5
|
context: Record<string, unknown>;
|
|
@@ -7,13 +7,15 @@ export default class Client {
|
|
|
7
7
|
}>;
|
|
8
8
|
protected __beforeNotifyHandlers: BeforeNotifyHandler[];
|
|
9
9
|
protected __afterNotifyHandlers: AfterNotifyHandler[];
|
|
10
|
-
protected __getSourceFileHandler: (path: string
|
|
10
|
+
protected __getSourceFileHandler: (path: string) => Promise<string>;
|
|
11
|
+
protected readonly __transport: Transport;
|
|
11
12
|
config: Config;
|
|
12
13
|
logger: Logger;
|
|
13
|
-
constructor(opts
|
|
14
|
-
factory(
|
|
14
|
+
protected constructor(opts: Partial<Config>, transport: Transport);
|
|
15
|
+
protected abstract factory(opts: Partial<Config>): this;
|
|
16
|
+
protected abstract checkIn(id: string): Promise<void>;
|
|
15
17
|
getVersion(): string;
|
|
16
|
-
configure(opts?: Partial<Config>):
|
|
18
|
+
configure(opts?: Partial<Config>): this;
|
|
17
19
|
beforeNotify(handler: BeforeNotifyHandler): Client;
|
|
18
20
|
afterNotify(handler: AfterNotifyHandler): Client;
|
|
19
21
|
setContext(context: Record<string, unknown>): Client;
|
|
@@ -30,7 +32,6 @@ export default class Client {
|
|
|
30
32
|
protected makeNotice(noticeable: Noticeable, name?: string | Partial<Notice>, extra?: Partial<Notice>): Notice | null;
|
|
31
33
|
addBreadcrumb(message: string, opts?: Record<string, unknown>): Client;
|
|
32
34
|
protected __developmentMode(): boolean;
|
|
33
|
-
protected
|
|
34
|
-
protected __buildPayload(notice: Notice): Record<string, Record<string, unknown>>;
|
|
35
|
+
protected __buildPayload(notice: Notice): NoticeTransportPayload;
|
|
35
36
|
protected __constructTags(tags: unknown): Array<string>;
|
|
36
37
|
}
|