rollbar 2.26.2 → 2.26.4
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/.github/workflows/ci.yml +32 -10
- package/.lgtm.yml +7 -7
- package/.prettierignore +18 -0
- package/.vscode/settings.json +39 -0
- package/CHANGELOG.md +121 -35
- package/Gruntfile.js +51 -71
- package/README.md +2 -4
- package/bower.json +1 -3
- package/defaults.js +17 -5
- package/dist/plugins/jquery.min.js +1 -1
- package/dist/rollbar.js +5699 -5052
- package/dist/rollbar.js.map +1 -1
- package/dist/rollbar.min.js +1 -1
- package/dist/rollbar.min.js.map +1 -1
- package/dist/rollbar.named-amd.js +5704 -5062
- package/dist/rollbar.named-amd.js.map +1 -1
- package/dist/rollbar.named-amd.min.js +1 -1
- package/dist/rollbar.named-amd.min.js.map +1 -1
- package/dist/rollbar.noconflict.umd.js +5693 -5052
- package/dist/rollbar.noconflict.umd.js.map +1 -1
- package/dist/rollbar.noconflict.umd.min.js +1 -1
- package/dist/rollbar.noconflict.umd.min.js.map +1 -1
- package/dist/rollbar.snippet.js +1 -1
- package/dist/rollbar.umd.js +5704 -5063
- package/dist/rollbar.umd.js.map +1 -1
- package/dist/rollbar.umd.min.js +1 -1
- package/dist/rollbar.umd.min.js.map +1 -1
- package/docs/extension-exceptions.md +35 -30
- package/docs/migration_v0_to_v1.md +41 -38
- package/index.d.ts +270 -231
- package/karma.conf.js +16 -34
- package/package.json +21 -17
- package/prettier.config.js +7 -0
- package/src/api.js +21 -10
- package/src/apiUtility.js +12 -8
- package/src/browser/core.js +103 -65
- package/src/browser/defaults/scrubFields.js +3 -3
- package/src/browser/detection.js +7 -8
- package/src/browser/domUtility.js +18 -8
- package/src/browser/globalSetup.js +12 -6
- package/src/browser/logger.js +1 -1
- package/src/browser/plugins/jquery.js +35 -35
- package/src/browser/predicates.js +1 -1
- package/src/browser/rollbar.js +1 -1
- package/src/browser/rollbarWrapper.js +8 -5
- package/src/browser/shim.js +43 -19
- package/src/browser/snippet_callback.js +6 -4
- package/src/browser/telemetry.js +573 -354
- package/src/browser/transforms.js +46 -27
- package/src/browser/transport/fetch.js +16 -14
- package/src/browser/transport/xhr.js +29 -13
- package/src/browser/transport.js +82 -25
- package/src/browser/url.js +16 -8
- package/src/browser/wrapGlobals.js +27 -8
- package/src/defaults.js +3 -3
- package/src/errorParser.js +14 -11
- package/src/merge.js +32 -23
- package/src/notifier.js +16 -13
- package/src/predicates.js +43 -23
- package/src/queue.js +71 -39
- package/src/rateLimiter.js +59 -18
- package/src/react-native/logger.js +1 -1
- package/src/react-native/rollbar.js +59 -55
- package/src/react-native/transforms.js +13 -9
- package/src/react-native/transport.js +44 -34
- package/src/rollbar.js +22 -13
- package/src/scrub.js +0 -1
- package/src/server/locals.js +69 -39
- package/src/server/logger.js +4 -4
- package/src/server/parser.js +72 -47
- package/src/server/rollbar.js +133 -55
- package/src/server/sourceMap/stackTrace.js +33 -18
- package/src/server/telemetry/urlHelpers.js +9 -11
- package/src/server/telemetry.js +68 -45
- package/src/server/transforms.js +37 -21
- package/src/server/transport.js +62 -32
- package/src/telemetry.js +92 -28
- package/src/transforms.js +33 -21
- package/src/truncation.js +8 -5
- package/src/utility/headers.js +43 -43
- package/src/utility/replace.js +9 -0
- package/src/utility/traverse.js +1 -1
- package/src/utility.js +89 -52
- package/test/api.test.js +31 -29
- package/test/apiUtility.test.js +43 -44
- package/test/browser.core.test.js +141 -131
- package/test/browser.domUtility.test.js +52 -35
- package/test/browser.predicates.test.js +13 -13
- package/test/browser.rollbar.test.js +597 -503
- package/test/browser.telemetry.test.js +76 -0
- package/test/browser.transforms.test.js +146 -128
- package/test/browser.transport.test.js +54 -46
- package/test/browser.url.test.js +12 -11
- package/test/fixtures/locals.fixtures.js +245 -126
- package/test/notifier.test.js +90 -78
- package/test/predicates.test.js +260 -214
- package/test/queue.test.js +230 -214
- package/test/rateLimiter.test.js +50 -42
- package/test/react-native.rollbar.test.js +149 -115
- package/test/react-native.transforms.test.js +21 -23
- package/test/react-native.transport.test.js +23 -11
- package/test/server.lambda.test.js +70 -53
- package/test/server.locals.test.js +437 -210
- package/test/server.parser.test.js +32 -26
- package/test/server.predicates.test.js +45 -43
- package/test/server.rollbar.test.js +311 -259
- package/test/server.telemetry.test.js +208 -83
- package/test/server.transforms.test.js +455 -361
- package/test/server.transport.test.js +144 -76
- package/test/telemetry.test.js +46 -37
- package/test/transforms.test.js +68 -66
- package/test/truncation.test.js +55 -53
- package/test/utility.test.js +266 -222
- package/webpack.config.js +46 -43
- package/.gitmodules +0 -3
- package/browserstack.browsers.js +0 -153
- package/browserstack.browsers.json +0 -4384
package/src/errorParser.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
var ErrorStackParser = require('error-stack-parser');
|
|
2
2
|
|
|
3
3
|
var UNKNOWN_FUNCTION = '?';
|
|
4
|
-
var ERR_CLASS_REGEXP = new RegExp(
|
|
4
|
+
var ERR_CLASS_REGEXP = new RegExp(
|
|
5
|
+
'^(([a-zA-Z0-9-_$ ]*): *)?(Uncaught )?([a-zA-Z0-9-_$ ]*): ',
|
|
6
|
+
);
|
|
5
7
|
|
|
6
8
|
function guessFunctionName() {
|
|
7
9
|
return UNKNOWN_FUNCTION;
|
|
8
10
|
}
|
|
9
11
|
|
|
10
|
-
|
|
11
12
|
function gatherContext() {
|
|
12
13
|
return null;
|
|
13
14
|
}
|
|
14
15
|
|
|
15
|
-
|
|
16
16
|
function Frame(stackFrame) {
|
|
17
17
|
var data = {};
|
|
18
18
|
|
|
@@ -29,7 +29,6 @@ function Frame(stackFrame) {
|
|
|
29
29
|
return data;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
|
|
33
32
|
function Stack(exception, skip) {
|
|
34
33
|
function getStack() {
|
|
35
34
|
var parserStack = [];
|
|
@@ -38,7 +37,7 @@ function Stack(exception, skip) {
|
|
|
38
37
|
|
|
39
38
|
try {
|
|
40
39
|
parserStack = ErrorStackParser.parse(exception);
|
|
41
|
-
} catch(e) {
|
|
40
|
+
} catch (e) {
|
|
42
41
|
parserStack = [];
|
|
43
42
|
}
|
|
44
43
|
|
|
@@ -56,11 +55,10 @@ function Stack(exception, skip) {
|
|
|
56
55
|
message: exception.message,
|
|
57
56
|
name: _mostSpecificErrorName(exception),
|
|
58
57
|
rawStack: exception.stack,
|
|
59
|
-
rawException: exception
|
|
58
|
+
rawException: exception,
|
|
60
59
|
};
|
|
61
60
|
}
|
|
62
61
|
|
|
63
|
-
|
|
64
62
|
function parse(e, skip) {
|
|
65
63
|
var err = e;
|
|
66
64
|
|
|
@@ -81,7 +79,6 @@ function parse(e, skip) {
|
|
|
81
79
|
}
|
|
82
80
|
}
|
|
83
81
|
|
|
84
|
-
|
|
85
82
|
function guessErrorClass(errMsg) {
|
|
86
83
|
if (!errMsg || !errMsg.match) {
|
|
87
84
|
return ['Unknown error. There was no error message to display.', ''];
|
|
@@ -91,7 +88,10 @@ function guessErrorClass(errMsg) {
|
|
|
91
88
|
|
|
92
89
|
if (errClassMatch) {
|
|
93
90
|
errClass = errClassMatch[errClassMatch.length - 1];
|
|
94
|
-
errMsg = errMsg.replace(
|
|
91
|
+
errMsg = errMsg.replace(
|
|
92
|
+
(errClassMatch[errClassMatch.length - 2] || '') + errClass + ':',
|
|
93
|
+
'',
|
|
94
|
+
);
|
|
95
95
|
errMsg = errMsg.replace(/(^[\s]+|[\s]+$)/g, '');
|
|
96
96
|
}
|
|
97
97
|
return [errClass, errMsg];
|
|
@@ -102,7 +102,10 @@ function guessErrorClass(errMsg) {
|
|
|
102
102
|
// * Prefers name over constructor.name when both are more specific than 'Error'
|
|
103
103
|
function _mostSpecificErrorName(error) {
|
|
104
104
|
var name = error.name && error.name.length && error.name;
|
|
105
|
-
var constructorName =
|
|
105
|
+
var constructorName =
|
|
106
|
+
error.constructor.name &&
|
|
107
|
+
error.constructor.name.length &&
|
|
108
|
+
error.constructor.name;
|
|
106
109
|
|
|
107
110
|
if (!name || !constructorName) {
|
|
108
111
|
return name || constructorName;
|
|
@@ -120,5 +123,5 @@ module.exports = {
|
|
|
120
123
|
gatherContext: gatherContext,
|
|
121
124
|
parse: parse,
|
|
122
125
|
Stack: Stack,
|
|
123
|
-
Frame: Frame
|
|
126
|
+
Frame: Frame,
|
|
124
127
|
};
|
package/src/merge.js
CHANGED
|
@@ -4,32 +4,41 @@ var hasOwn = Object.prototype.hasOwnProperty;
|
|
|
4
4
|
var toStr = Object.prototype.toString;
|
|
5
5
|
|
|
6
6
|
var isPlainObject = function isPlainObject(obj) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
7
|
+
if (!obj || toStr.call(obj) !== '[object Object]') {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
var hasOwnConstructor = hasOwn.call(obj, 'constructor');
|
|
12
|
+
var hasIsPrototypeOf =
|
|
13
|
+
obj.constructor &&
|
|
14
|
+
obj.constructor.prototype &&
|
|
15
|
+
hasOwn.call(obj.constructor.prototype, 'isPrototypeOf');
|
|
16
|
+
// Not own constructor property must be Object
|
|
17
|
+
if (obj.constructor && !hasOwnConstructor && !hasIsPrototypeOf) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Own properties are enumerated firstly, so to speed up,
|
|
22
|
+
// if last one is own, then all properties are own.
|
|
23
|
+
var key;
|
|
24
|
+
for (key in obj) {
|
|
25
|
+
/**/
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return typeof key === 'undefined' || hasOwn.call(obj, key);
|
|
24
29
|
};
|
|
25
30
|
|
|
26
31
|
function merge() {
|
|
27
|
-
var i,
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
var i,
|
|
33
|
+
src,
|
|
34
|
+
copy,
|
|
35
|
+
clone,
|
|
36
|
+
name,
|
|
37
|
+
result = {},
|
|
38
|
+
current = null,
|
|
39
|
+
length = arguments.length;
|
|
40
|
+
|
|
41
|
+
for (i = 0; i < length; i++) {
|
|
33
42
|
current = arguments[i];
|
|
34
43
|
if (current == null) {
|
|
35
44
|
continue;
|
package/src/notifier.js
CHANGED
|
@@ -22,7 +22,7 @@ function Notifier(queue, options) {
|
|
|
22
22
|
* @param options - an object which gets merged with the current options set on this notifier
|
|
23
23
|
* @returns this
|
|
24
24
|
*/
|
|
25
|
-
Notifier.prototype.configure = function(options) {
|
|
25
|
+
Notifier.prototype.configure = function (options) {
|
|
26
26
|
this.queue && this.queue.configure(options);
|
|
27
27
|
var oldOptions = this.options;
|
|
28
28
|
this.options = _.merge(oldOptions, options);
|
|
@@ -40,7 +40,7 @@ Notifier.prototype.configure = function(options) {
|
|
|
40
40
|
* with an error to terminate the processing. The item should be the updated item after this
|
|
41
41
|
* transform is finished modifying it.
|
|
42
42
|
*/
|
|
43
|
-
Notifier.prototype.addTransform = function(transform) {
|
|
43
|
+
Notifier.prototype.addTransform = function (transform) {
|
|
44
44
|
if (_.isFunction(transform)) {
|
|
45
45
|
this.transforms.push(transform);
|
|
46
46
|
}
|
|
@@ -60,9 +60,9 @@ Notifier.prototype.addTransform = function(transform) {
|
|
|
60
60
|
* transform stage if an error occurs inside a transform, or in response to the communication with
|
|
61
61
|
* the backend. The second argument will be the response from the backend in case of success.
|
|
62
62
|
*/
|
|
63
|
-
Notifier.prototype.log = function(item, callback) {
|
|
63
|
+
Notifier.prototype.log = function (item, callback) {
|
|
64
64
|
if (!callback || !_.isFunction(callback)) {
|
|
65
|
-
callback = function() {};
|
|
65
|
+
callback = function () {};
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
if (!this.options.enabled) {
|
|
@@ -71,13 +71,16 @@ Notifier.prototype.log = function(item, callback) {
|
|
|
71
71
|
|
|
72
72
|
this.queue.addPendingItem(item);
|
|
73
73
|
var originalError = item.err;
|
|
74
|
-
this._applyTransforms(
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
74
|
+
this._applyTransforms(
|
|
75
|
+
item,
|
|
76
|
+
function (err, i) {
|
|
77
|
+
if (err) {
|
|
78
|
+
this.queue.removePendingItem(item);
|
|
79
|
+
return callback(err, null);
|
|
80
|
+
}
|
|
81
|
+
this.queue.addItem(i, callback, originalError, item);
|
|
82
|
+
}.bind(this),
|
|
83
|
+
);
|
|
81
84
|
};
|
|
82
85
|
|
|
83
86
|
/* Internal */
|
|
@@ -91,13 +94,13 @@ Notifier.prototype.log = function(item, callback) {
|
|
|
91
94
|
* error and a null item in the case of a transform failure, or a null error and non-null item after
|
|
92
95
|
* all transforms have been applied.
|
|
93
96
|
*/
|
|
94
|
-
Notifier.prototype._applyTransforms = function(item, callback) {
|
|
97
|
+
Notifier.prototype._applyTransforms = function (item, callback) {
|
|
95
98
|
var transformIndex = -1;
|
|
96
99
|
var transformsLength = this.transforms.length;
|
|
97
100
|
var transforms = this.transforms;
|
|
98
101
|
var options = this.options;
|
|
99
102
|
|
|
100
|
-
var cb = function(err, i) {
|
|
103
|
+
var cb = function (err, i) {
|
|
101
104
|
if (err) {
|
|
102
105
|
callback(err, null);
|
|
103
106
|
return;
|
package/src/predicates.js
CHANGED
|
@@ -13,7 +13,7 @@ function checkLevel(item, settings) {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
function userCheckIgnore(logger) {
|
|
16
|
-
return function(item, settings) {
|
|
16
|
+
return function (item, settings) {
|
|
17
17
|
var isUncaught = !!item._isUncaught;
|
|
18
18
|
delete item._isUncaught;
|
|
19
19
|
var args = item._originalArgs;
|
|
@@ -27,7 +27,10 @@ function userCheckIgnore(logger) {
|
|
|
27
27
|
logger.error('Error while calling onSendCallback, removing', e);
|
|
28
28
|
}
|
|
29
29
|
try {
|
|
30
|
-
if (
|
|
30
|
+
if (
|
|
31
|
+
_.isFunction(settings.checkIgnore) &&
|
|
32
|
+
settings.checkIgnore(isUncaught, args, item)
|
|
33
|
+
) {
|
|
31
34
|
return false;
|
|
32
35
|
}
|
|
33
36
|
} catch (e) {
|
|
@@ -35,27 +38,31 @@ function userCheckIgnore(logger) {
|
|
|
35
38
|
logger.error('Error while calling custom checkIgnore(), removing', e);
|
|
36
39
|
}
|
|
37
40
|
return true;
|
|
38
|
-
}
|
|
41
|
+
};
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
function urlIsNotBlockListed(logger) {
|
|
42
|
-
return function(item, settings) {
|
|
45
|
+
return function (item, settings) {
|
|
43
46
|
return !urlIsOnAList(item, settings, 'blocklist', logger);
|
|
44
|
-
}
|
|
47
|
+
};
|
|
45
48
|
}
|
|
46
49
|
|
|
47
50
|
function urlIsSafeListed(logger) {
|
|
48
|
-
return function(item, settings) {
|
|
51
|
+
return function (item, settings) {
|
|
49
52
|
return urlIsOnAList(item, settings, 'safelist', logger);
|
|
50
|
-
}
|
|
53
|
+
};
|
|
51
54
|
}
|
|
52
55
|
|
|
53
56
|
function matchFrames(trace, list, block) {
|
|
54
|
-
if (!trace) {
|
|
57
|
+
if (!trace) {
|
|
58
|
+
return !block;
|
|
59
|
+
}
|
|
55
60
|
|
|
56
61
|
var frames = trace.frames;
|
|
57
62
|
|
|
58
|
-
if (!frames || frames.length === 0) {
|
|
63
|
+
if (!frames || frames.length === 0) {
|
|
64
|
+
return !block;
|
|
65
|
+
}
|
|
59
66
|
|
|
60
67
|
var frame, filename, url, urlRegex;
|
|
61
68
|
var listLength = list.length;
|
|
@@ -64,7 +71,9 @@ function matchFrames(trace, list, block) {
|
|
|
64
71
|
frame = frames[i];
|
|
65
72
|
filename = frame.filename;
|
|
66
73
|
|
|
67
|
-
if (!_.isType(filename, 'string')) {
|
|
74
|
+
if (!_.isType(filename, 'string')) {
|
|
75
|
+
return !block;
|
|
76
|
+
}
|
|
68
77
|
|
|
69
78
|
for (var j = 0; j < listLength; j++) {
|
|
70
79
|
url = list[j];
|
|
@@ -101,27 +110,35 @@ function urlIsOnAList(item, settings, safeOrBlock, logger) {
|
|
|
101
110
|
|
|
102
111
|
var tracesLength = traces.length;
|
|
103
112
|
for (var i = 0; i < tracesLength; i++) {
|
|
104
|
-
if(matchFrames(traces[i], list, block)) {
|
|
113
|
+
if (matchFrames(traces[i], list, block)) {
|
|
105
114
|
return true;
|
|
106
115
|
}
|
|
107
116
|
}
|
|
108
|
-
} catch (
|
|
109
|
-
|
|
110
|
-
|
|
117
|
+
} catch (
|
|
118
|
+
e
|
|
119
|
+
/* istanbul ignore next */
|
|
120
|
+
) {
|
|
111
121
|
if (block) {
|
|
112
122
|
settings.hostBlockList = null;
|
|
113
123
|
} else {
|
|
114
124
|
settings.hostSafeList = null;
|
|
115
125
|
}
|
|
116
126
|
var listName = block ? 'hostBlockList' : 'hostSafeList';
|
|
117
|
-
logger.error(
|
|
127
|
+
logger.error(
|
|
128
|
+
"Error while reading your configuration's " +
|
|
129
|
+
listName +
|
|
130
|
+
' option. Removing custom ' +
|
|
131
|
+
listName +
|
|
132
|
+
'.',
|
|
133
|
+
e,
|
|
134
|
+
);
|
|
118
135
|
return !block;
|
|
119
136
|
}
|
|
120
137
|
return false;
|
|
121
138
|
}
|
|
122
139
|
|
|
123
140
|
function messageIsIgnored(logger) {
|
|
124
|
-
return function(item, settings) {
|
|
141
|
+
return function (item, settings) {
|
|
125
142
|
var i, j, ignoredMessages, len, messageIsIgnored, rIgnoredMessage, messages;
|
|
126
143
|
|
|
127
144
|
try {
|
|
@@ -134,7 +151,7 @@ function messageIsIgnored(logger) {
|
|
|
134
151
|
|
|
135
152
|
messages = messagesFromItem(item);
|
|
136
153
|
|
|
137
|
-
if (messages.length === 0){
|
|
154
|
+
if (messages.length === 0) {
|
|
138
155
|
return true;
|
|
139
156
|
}
|
|
140
157
|
|
|
@@ -150,15 +167,18 @@ function messageIsIgnored(logger) {
|
|
|
150
167
|
}
|
|
151
168
|
}
|
|
152
169
|
}
|
|
153
|
-
} catch(
|
|
154
|
-
|
|
155
|
-
|
|
170
|
+
} catch (
|
|
171
|
+
e
|
|
172
|
+
/* istanbul ignore next */
|
|
173
|
+
) {
|
|
156
174
|
settings.ignoredMessages = null;
|
|
157
|
-
logger.error(
|
|
175
|
+
logger.error(
|
|
176
|
+
"Error while reading your configuration's ignoredMessages option. Removing custom ignoredMessages.",
|
|
177
|
+
);
|
|
158
178
|
}
|
|
159
179
|
|
|
160
180
|
return true;
|
|
161
|
-
}
|
|
181
|
+
};
|
|
162
182
|
}
|
|
163
183
|
|
|
164
184
|
function messagesFromItem(item) {
|
|
@@ -189,5 +209,5 @@ module.exports = {
|
|
|
189
209
|
userCheckIgnore: userCheckIgnore,
|
|
190
210
|
urlIsNotBlockListed: urlIsNotBlockListed,
|
|
191
211
|
urlIsSafeListed: urlIsSafeListed,
|
|
192
|
-
messageIsIgnored: messageIsIgnored
|
|
212
|
+
messageIsIgnored: messageIsIgnored,
|
|
193
213
|
};
|
package/src/queue.js
CHANGED
|
@@ -32,7 +32,7 @@ function Queue(rateLimiter, api, logger, options) {
|
|
|
32
32
|
*
|
|
33
33
|
* @param options
|
|
34
34
|
*/
|
|
35
|
-
Queue.prototype.configure = function(options) {
|
|
35
|
+
Queue.prototype.configure = function (options) {
|
|
36
36
|
this.api && this.api.configure(options);
|
|
37
37
|
var oldOptions = this.options;
|
|
38
38
|
this.options = _.merge(oldOptions, options);
|
|
@@ -48,18 +48,18 @@ Queue.prototype.configure = function(options) {
|
|
|
48
48
|
* Returning {err: Error} means do not add the item to the queue, and the given error explains why
|
|
49
49
|
* Returning {err: undefined} is equivalent to returning true but don't do that
|
|
50
50
|
*/
|
|
51
|
-
Queue.prototype.addPredicate = function(predicate) {
|
|
51
|
+
Queue.prototype.addPredicate = function (predicate) {
|
|
52
52
|
if (_.isFunction(predicate)) {
|
|
53
53
|
this.predicates.push(predicate);
|
|
54
54
|
}
|
|
55
55
|
return this;
|
|
56
56
|
};
|
|
57
57
|
|
|
58
|
-
Queue.prototype.addPendingItem = function(item) {
|
|
58
|
+
Queue.prototype.addPendingItem = function (item) {
|
|
59
59
|
this.pendingItems.push(item);
|
|
60
60
|
};
|
|
61
61
|
|
|
62
|
-
Queue.prototype.removePendingItem = function(item) {
|
|
62
|
+
Queue.prototype.removePendingItem = function (item) {
|
|
63
63
|
var idx = this.pendingItems.indexOf(item);
|
|
64
64
|
if (idx !== -1) {
|
|
65
65
|
this.pendingItems.splice(idx, 1);
|
|
@@ -76,9 +76,16 @@ Queue.prototype.removePendingItem = function(item) {
|
|
|
76
76
|
* to be an error condition, but nonetheless did not send the item to the API.
|
|
77
77
|
* @param originalError - The original error before any transformations that is to be logged if any
|
|
78
78
|
*/
|
|
79
|
-
Queue.prototype.addItem = function(
|
|
79
|
+
Queue.prototype.addItem = function (
|
|
80
|
+
item,
|
|
81
|
+
callback,
|
|
82
|
+
originalError,
|
|
83
|
+
originalItem,
|
|
84
|
+
) {
|
|
80
85
|
if (!callback || !_.isFunction(callback)) {
|
|
81
|
-
callback = function() {
|
|
86
|
+
callback = function () {
|
|
87
|
+
return;
|
|
88
|
+
};
|
|
82
89
|
}
|
|
83
90
|
var predicateResult = this._applyPredicates(item);
|
|
84
91
|
if (predicateResult.stop) {
|
|
@@ -94,10 +101,13 @@ Queue.prototype.addItem = function(item, callback, originalError, originalItem)
|
|
|
94
101
|
}
|
|
95
102
|
this.pendingRequests.push(item);
|
|
96
103
|
try {
|
|
97
|
-
this._makeApiRequest(
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
104
|
+
this._makeApiRequest(
|
|
105
|
+
item,
|
|
106
|
+
function (err, resp) {
|
|
107
|
+
this._dequeuePendingRequest(item);
|
|
108
|
+
callback(err, resp);
|
|
109
|
+
}.bind(this),
|
|
110
|
+
);
|
|
101
111
|
} catch (e) {
|
|
102
112
|
this._dequeuePendingRequest(item);
|
|
103
113
|
callback(e);
|
|
@@ -110,7 +120,7 @@ Queue.prototype.addItem = function(item, callback, originalError, originalItem)
|
|
|
110
120
|
*
|
|
111
121
|
* @param callback - function() called when all pending items have been sent
|
|
112
122
|
*/
|
|
113
|
-
Queue.prototype.wait = function(callback) {
|
|
123
|
+
Queue.prototype.wait = function (callback) {
|
|
114
124
|
if (!_.isFunction(callback)) {
|
|
115
125
|
return;
|
|
116
126
|
}
|
|
@@ -121,9 +131,12 @@ Queue.prototype.wait = function(callback) {
|
|
|
121
131
|
if (this.waitIntervalID) {
|
|
122
132
|
this.waitIntervalID = clearInterval(this.waitIntervalID);
|
|
123
133
|
}
|
|
124
|
-
this.waitIntervalID = setInterval(
|
|
125
|
-
|
|
126
|
-
|
|
134
|
+
this.waitIntervalID = setInterval(
|
|
135
|
+
function () {
|
|
136
|
+
this._maybeCallWait();
|
|
137
|
+
}.bind(this),
|
|
138
|
+
500,
|
|
139
|
+
);
|
|
127
140
|
};
|
|
128
141
|
|
|
129
142
|
/* _applyPredicates - Sequentially applies the predicates that have been added to the queue to the
|
|
@@ -133,15 +146,15 @@ Queue.prototype.wait = function(callback) {
|
|
|
133
146
|
* @returns {stop: bool, err: (Error|null)} - stop being true means do not add item to the queue,
|
|
134
147
|
* the error value should be passed up to a callbak if we are stopping.
|
|
135
148
|
*/
|
|
136
|
-
Queue.prototype._applyPredicates = function(item) {
|
|
149
|
+
Queue.prototype._applyPredicates = function (item) {
|
|
137
150
|
var p = null;
|
|
138
151
|
for (var i = 0, len = this.predicates.length; i < len; i++) {
|
|
139
152
|
p = this.predicates[i](item, this.options);
|
|
140
153
|
if (!p || p.err !== undefined) {
|
|
141
|
-
return {stop: true, err: p.err};
|
|
154
|
+
return { stop: true, err: p.err };
|
|
142
155
|
}
|
|
143
156
|
}
|
|
144
|
-
return {stop: false, err: null};
|
|
157
|
+
return { stop: false, err: null };
|
|
145
158
|
};
|
|
146
159
|
|
|
147
160
|
/*
|
|
@@ -151,16 +164,19 @@ Queue.prototype._applyPredicates = function(item) {
|
|
|
151
164
|
* @param item - an item ready to send to the backend
|
|
152
165
|
* @param callback - function(err, response)
|
|
153
166
|
*/
|
|
154
|
-
Queue.prototype._makeApiRequest = function(item, callback) {
|
|
167
|
+
Queue.prototype._makeApiRequest = function (item, callback) {
|
|
155
168
|
var rateLimitResponse = this.rateLimiter.shouldSend(item);
|
|
156
169
|
if (rateLimitResponse.shouldSend) {
|
|
157
|
-
this.api.postItem(
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
170
|
+
this.api.postItem(
|
|
171
|
+
item,
|
|
172
|
+
function (err, resp) {
|
|
173
|
+
if (err) {
|
|
174
|
+
this._maybeRetry(err, item, callback);
|
|
175
|
+
} else {
|
|
176
|
+
callback(err, resp);
|
|
177
|
+
}
|
|
178
|
+
}.bind(this),
|
|
179
|
+
);
|
|
164
180
|
} else if (rateLimitResponse.error) {
|
|
165
181
|
callback(rateLimitResponse.error);
|
|
166
182
|
} else {
|
|
@@ -169,7 +185,16 @@ Queue.prototype._makeApiRequest = function(item, callback) {
|
|
|
169
185
|
};
|
|
170
186
|
|
|
171
187
|
// These are errors basically mean there is no internet connection
|
|
172
|
-
var RETRIABLE_ERRORS = [
|
|
188
|
+
var RETRIABLE_ERRORS = [
|
|
189
|
+
'ECONNRESET',
|
|
190
|
+
'ENOTFOUND',
|
|
191
|
+
'ESOCKETTIMEDOUT',
|
|
192
|
+
'ETIMEDOUT',
|
|
193
|
+
'ECONNREFUSED',
|
|
194
|
+
'EHOSTUNREACH',
|
|
195
|
+
'EPIPE',
|
|
196
|
+
'EAI_AGAIN',
|
|
197
|
+
];
|
|
173
198
|
|
|
174
199
|
/*
|
|
175
200
|
* _maybeRetry - Given the error returned by the API, decide if we should retry or just callback
|
|
@@ -179,7 +204,7 @@ var RETRIABLE_ERRORS = ['ECONNRESET', 'ENOTFOUND', 'ESOCKETTIMEDOUT', 'ETIMEDOUT
|
|
|
179
204
|
* @param item - the item that was trying to be sent when this error occured
|
|
180
205
|
* @param callback - function(err, response)
|
|
181
206
|
*/
|
|
182
|
-
Queue.prototype._maybeRetry = function(err, item, callback) {
|
|
207
|
+
Queue.prototype._maybeRetry = function (err, item, callback) {
|
|
183
208
|
var shouldRetry = false;
|
|
184
209
|
if (this.options.retryInterval) {
|
|
185
210
|
for (var i = 0, len = RETRIABLE_ERRORS.length; i < len; i++) {
|
|
@@ -209,16 +234,19 @@ Queue.prototype._maybeRetry = function(err, item, callback) {
|
|
|
209
234
|
* @param item - an item that failed to send due to an error we deem retriable
|
|
210
235
|
* @param callback - function(err, response)
|
|
211
236
|
*/
|
|
212
|
-
Queue.prototype._retryApiRequest = function(item, callback) {
|
|
213
|
-
this.retryQueue.push({item: item, callback: callback});
|
|
237
|
+
Queue.prototype._retryApiRequest = function (item, callback) {
|
|
238
|
+
this.retryQueue.push({ item: item, callback: callback });
|
|
214
239
|
|
|
215
240
|
if (!this.retryHandle) {
|
|
216
|
-
this.retryHandle = setInterval(
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
241
|
+
this.retryHandle = setInterval(
|
|
242
|
+
function () {
|
|
243
|
+
while (this.retryQueue.length) {
|
|
244
|
+
var retryObject = this.retryQueue.shift();
|
|
245
|
+
this._makeApiRequest(retryObject.item, retryObject.callback);
|
|
246
|
+
}
|
|
247
|
+
}.bind(this),
|
|
248
|
+
this.options.retryInterval,
|
|
249
|
+
);
|
|
222
250
|
}
|
|
223
251
|
};
|
|
224
252
|
|
|
@@ -230,7 +258,7 @@ Queue.prototype._retryApiRequest = function(item, callback) {
|
|
|
230
258
|
*
|
|
231
259
|
* @param item - the item previously added to the pending request queue
|
|
232
260
|
*/
|
|
233
|
-
Queue.prototype._dequeuePendingRequest = function(item) {
|
|
261
|
+
Queue.prototype._dequeuePendingRequest = function (item) {
|
|
234
262
|
var idx = this.pendingRequests.indexOf(item);
|
|
235
263
|
if (idx !== -1) {
|
|
236
264
|
this.pendingRequests.splice(idx, 1);
|
|
@@ -238,7 +266,7 @@ Queue.prototype._dequeuePendingRequest = function(item) {
|
|
|
238
266
|
}
|
|
239
267
|
};
|
|
240
268
|
|
|
241
|
-
Queue.prototype._maybeLog = function(data, originalError) {
|
|
269
|
+
Queue.prototype._maybeLog = function (data, originalError) {
|
|
242
270
|
if (this.logger && this.options.verbose) {
|
|
243
271
|
var message = originalError;
|
|
244
272
|
message = message || _.get(data, 'body.trace.exception.message');
|
|
@@ -254,8 +282,12 @@ Queue.prototype._maybeLog = function(data, originalError) {
|
|
|
254
282
|
}
|
|
255
283
|
};
|
|
256
284
|
|
|
257
|
-
Queue.prototype._maybeCallWait = function() {
|
|
258
|
-
if (
|
|
285
|
+
Queue.prototype._maybeCallWait = function () {
|
|
286
|
+
if (
|
|
287
|
+
_.isFunction(this.waitCallback) &&
|
|
288
|
+
this.pendingItems.length === 0 &&
|
|
289
|
+
this.pendingRequests.length === 0
|
|
290
|
+
) {
|
|
259
291
|
if (this.waitIntervalID) {
|
|
260
292
|
this.waitIntervalID = clearInterval(this.waitIntervalID);
|
|
261
293
|
}
|