rollbar 2.17.0 → 2.19.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/README.md +1 -1
- package/defaults.js +0 -1
- package/dist/rollbar.js +3810 -3556
- 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 +3807 -3553
- 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 +3807 -3553
- 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 +3807 -3553
- 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/index.d.ts +2 -0
- package/package.json +1 -62
- package/src/api.js +13 -7
- package/src/browser/core.js +561 -0
- package/src/browser/defaults/scrubFields.js +59 -0
- package/src/browser/globalSetup.js +1 -41
- package/src/browser/rollbar.js +16 -544
- package/src/browser/shim.js +2 -1
- package/src/browser/telemetry.js +33 -17
- package/src/browser/transforms.js +28 -5
- package/src/browser/transport.js +13 -10
- package/src/browser/wrapGlobals.js +41 -0
- package/src/defaults.js +9 -0
- package/src/predicates.js +1 -0
- package/src/react-native/rollbar.js +9 -3
- package/src/react-native/transforms.js +7 -1
- package/src/react-native/transport.js +16 -10
- package/src/rollbar.js +9 -10
- package/src/scrub.js +93 -0
- package/src/server/rollbar.js +6 -2
- package/src/server/sourceMap/stackTrace.js +1 -2
- package/src/server/transforms.js +18 -4
- package/src/transforms.js +0 -1
- package/src/truncation.js +3 -2
- package/src/utility/traverse.js +38 -0
- package/src/utility.js +25 -107
- package/test/api.test.js +2 -0
- package/test/apiUtility.test.js +2 -1
- package/test/browser.core.test.js +555 -0
- package/test/browser.rollbar.test.js +116 -13
- package/test/browser.transforms.test.js +22 -2
- package/test/browser.transport.test.js +5 -2
- package/test/react-native.transport.test.js +5 -1
- package/test/server.transforms.test.js +70 -0
- package/test/truncation.test.js +2 -0
- package/test/utility.test.js +44 -13
package/src/browser/telemetry.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
var _ = require('../utility');
|
|
2
|
+
var scrub = require('../scrub');
|
|
2
3
|
var urlparser = require('./url');
|
|
3
4
|
var domUtil = require('./domUtility');
|
|
4
5
|
|
|
@@ -168,15 +169,20 @@ Instrumenter.prototype.instrumentNetwork = function() {
|
|
|
168
169
|
replace(xhrp, 'open', function(orig) {
|
|
169
170
|
return function(method, url) {
|
|
170
171
|
if (_.isType(url, 'string')) {
|
|
171
|
-
this.__rollbar_xhr
|
|
172
|
-
method
|
|
173
|
-
url
|
|
174
|
-
status_code
|
|
175
|
-
start_time_ms
|
|
176
|
-
end_time_ms
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
|
|
172
|
+
if (this.__rollbar_xhr) {
|
|
173
|
+
this.__rollbar_xhr.method = method;
|
|
174
|
+
this.__rollbar_xhr.url = url;
|
|
175
|
+
this.__rollbar_xhr.status_code = null;
|
|
176
|
+
this.__rollbar_xhr.start_time_ms = _.now();
|
|
177
|
+
this.__rollbar_xhr.end_time_ms = null;
|
|
178
|
+
} else {
|
|
179
|
+
this.__rollbar_xhr = {
|
|
180
|
+
method: method,
|
|
181
|
+
url: url,
|
|
182
|
+
status_code: null,
|
|
183
|
+
start_time_ms: _.now(),
|
|
184
|
+
end_time_ms: null
|
|
185
|
+
};
|
|
180
186
|
}
|
|
181
187
|
}
|
|
182
188
|
return orig.apply(this, arguments);
|
|
@@ -185,12 +191,21 @@ Instrumenter.prototype.instrumentNetwork = function() {
|
|
|
185
191
|
|
|
186
192
|
replace(xhrp, 'setRequestHeader', function(orig) {
|
|
187
193
|
return function(header, value) {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
this.__rollbar_xhr
|
|
194
|
+
// If xhr.open is async, __rollbar_xhr may not be initialized yet.
|
|
195
|
+
if (!this.__rollbar_xhr) {
|
|
196
|
+
this.__rollbar_xhr = {};
|
|
191
197
|
}
|
|
192
|
-
if (
|
|
193
|
-
|
|
198
|
+
if (_.isType(header, 'string') && _.isType(value, 'string')) {
|
|
199
|
+
if (self.autoInstrument.networkRequestHeaders) {
|
|
200
|
+
if (!this.__rollbar_xhr.request_headers) {
|
|
201
|
+
this.__rollbar_xhr.request_headers = {};
|
|
202
|
+
}
|
|
203
|
+
this.__rollbar_xhr.request_headers[header] = value;
|
|
204
|
+
}
|
|
205
|
+
// We want the content type even if request header telemetry is off.
|
|
206
|
+
if (header.toLowerCase() === 'content-type') {
|
|
207
|
+
this.__rollbar_xhr.request_content_type = value;
|
|
208
|
+
}
|
|
194
209
|
}
|
|
195
210
|
return orig.apply(this, arguments);
|
|
196
211
|
};
|
|
@@ -367,8 +382,9 @@ Instrumenter.prototype.instrumentNetwork = function() {
|
|
|
367
382
|
}
|
|
368
383
|
var body = null;
|
|
369
384
|
if (self.autoInstrument.networkResponseBody) {
|
|
370
|
-
if (typeof resp.text === 'function') { // Response.text() is not implemented on
|
|
371
|
-
|
|
385
|
+
if (typeof resp.text === 'function') { // Response.text() is not implemented on some platforms
|
|
386
|
+
// The response must be cloned to prevent reading (and locking) the original stream.
|
|
387
|
+
body = resp.clone().text(); //returns a Promise
|
|
372
388
|
}
|
|
373
389
|
}
|
|
374
390
|
if (headers || body) {
|
|
@@ -409,7 +425,7 @@ Instrumenter.prototype.isJsonContentType = function(contentType) {
|
|
|
409
425
|
}
|
|
410
426
|
|
|
411
427
|
Instrumenter.prototype.scrubJson = function(json) {
|
|
412
|
-
return JSON.stringify(
|
|
428
|
+
return JSON.stringify(scrub(JSON.parse(json), this.options.scrubFields));
|
|
413
429
|
}
|
|
414
430
|
|
|
415
431
|
Instrumenter.prototype.fetchHeaders = function(inHeaders, headersConfig) {
|
|
@@ -19,6 +19,10 @@ function handleItemWithError(item, options, callback) {
|
|
|
19
19
|
if (item.err) {
|
|
20
20
|
try {
|
|
21
21
|
item.stackInfo = item.err._savedStackTrace || errorParser.parse(item.err, item.skipFrames);
|
|
22
|
+
|
|
23
|
+
if (options.addErrorContext) {
|
|
24
|
+
addErrorContext(item);
|
|
25
|
+
}
|
|
22
26
|
} catch (e) {
|
|
23
27
|
logger.error('Error while parsing the error object.', e);
|
|
24
28
|
try {
|
|
@@ -32,6 +36,20 @@ function handleItemWithError(item, options, callback) {
|
|
|
32
36
|
callback(null, item);
|
|
33
37
|
}
|
|
34
38
|
|
|
39
|
+
function addErrorContext(item) {
|
|
40
|
+
var chain = [];
|
|
41
|
+
var err = item.err;
|
|
42
|
+
|
|
43
|
+
chain.push(err);
|
|
44
|
+
|
|
45
|
+
while (err.nested) {
|
|
46
|
+
err = err.nested;
|
|
47
|
+
chain.push(err);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
_.addErrorContext(item, chain);
|
|
51
|
+
}
|
|
52
|
+
|
|
35
53
|
function ensureItemHasSomethingToSay(item, options, callback) {
|
|
36
54
|
if (!item.message && !item.stackInfo && !item.custom) {
|
|
37
55
|
callback(new Error('No message, stack info, or custom data'), null);
|
|
@@ -291,10 +309,15 @@ function errorClass(stackInfo, guess, options) {
|
|
|
291
309
|
}
|
|
292
310
|
}
|
|
293
311
|
|
|
294
|
-
function
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
312
|
+
function addScrubber(scrubFn) {
|
|
313
|
+
return function (item, options, callback) {
|
|
314
|
+
if (scrubFn) {
|
|
315
|
+
var scrubFields = options.scrubFields || [];
|
|
316
|
+
var scrubPaths = options.scrubPaths || [];
|
|
317
|
+
item.data = scrubFn(item.data, scrubFields, scrubPaths);
|
|
318
|
+
}
|
|
319
|
+
callback(null, item);
|
|
320
|
+
}
|
|
298
321
|
}
|
|
299
322
|
|
|
300
323
|
module.exports = {
|
|
@@ -306,5 +329,5 @@ module.exports = {
|
|
|
306
329
|
addClientInfo: addClientInfo,
|
|
307
330
|
addPluginInfo: addPluginInfo,
|
|
308
331
|
addBody: addBody,
|
|
309
|
-
|
|
332
|
+
addScrubber: addScrubber
|
|
310
333
|
};
|
package/src/browser/transport.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/*global XDomainRequest*/
|
|
2
2
|
|
|
3
3
|
var _ = require('../utility');
|
|
4
|
-
var truncation = require('../truncation');
|
|
5
4
|
var logger = require('./logger');
|
|
6
5
|
|
|
7
6
|
/*
|
|
@@ -21,8 +20,11 @@ var logger = require('./logger');
|
|
|
21
20
|
*
|
|
22
21
|
* payload is an unserialized object
|
|
23
22
|
*/
|
|
23
|
+
function Transport(truncation) {
|
|
24
|
+
this.truncation = truncation;
|
|
25
|
+
}
|
|
24
26
|
|
|
25
|
-
function
|
|
27
|
+
Transport.prototype.get = function(accessToken, options, params, callback, requestFactory) {
|
|
26
28
|
if (!callback || !_.isFunction(callback)) {
|
|
27
29
|
callback = function() {};
|
|
28
30
|
}
|
|
@@ -33,7 +35,7 @@ function get(accessToken, options, params, callback, requestFactory) {
|
|
|
33
35
|
_makeZoneRequest(accessToken, url, method, null, callback, requestFactory);
|
|
34
36
|
}
|
|
35
37
|
|
|
36
|
-
function
|
|
38
|
+
Transport.prototype.post = function(accessToken, options, payload, callback, requestFactory) {
|
|
37
39
|
if (!callback || !_.isFunction(callback)) {
|
|
38
40
|
callback = function() {};
|
|
39
41
|
}
|
|
@@ -42,7 +44,12 @@ function post(accessToken, options, payload, callback, requestFactory) {
|
|
|
42
44
|
return callback(new Error('Cannot send empty request'));
|
|
43
45
|
}
|
|
44
46
|
|
|
45
|
-
var stringifyResult
|
|
47
|
+
var stringifyResult;
|
|
48
|
+
if (this.truncation) {
|
|
49
|
+
stringifyResult = this.truncation.truncate(payload);
|
|
50
|
+
} else {
|
|
51
|
+
stringifyResult = _.stringify(payload)
|
|
52
|
+
}
|
|
46
53
|
if (stringifyResult.error) {
|
|
47
54
|
return callback(stringifyResult.error);
|
|
48
55
|
}
|
|
@@ -53,7 +60,7 @@ function post(accessToken, options, payload, callback, requestFactory) {
|
|
|
53
60
|
_makeZoneRequest(accessToken, url, method, writeData, callback, requestFactory);
|
|
54
61
|
}
|
|
55
62
|
|
|
56
|
-
function
|
|
63
|
+
Transport.prototype.postJsonPayload = function (accessToken, options, jsonPayload, callback, requestFactory) {
|
|
57
64
|
if (!callback || !_.isFunction(callback)) {
|
|
58
65
|
callback = function() {};
|
|
59
66
|
}
|
|
@@ -245,8 +252,4 @@ function _newRetriableError(message, code) {
|
|
|
245
252
|
return err;
|
|
246
253
|
}
|
|
247
254
|
|
|
248
|
-
module.exports =
|
|
249
|
-
get: get,
|
|
250
|
-
post: post,
|
|
251
|
-
postJsonPayload: postJsonPayload
|
|
252
|
-
};
|
|
255
|
+
module.exports = Transport;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
function wrapGlobals(window, handler, shim) {
|
|
2
|
+
if (!window) { return; }
|
|
3
|
+
// Adapted from https://github.com/bugsnag/bugsnag-js
|
|
4
|
+
var globals = 'EventTarget,Window,Node,ApplicationCache,AudioTrackList,ChannelMergerNode,CryptoOperation,EventSource,FileReader,HTMLUnknownElement,IDBDatabase,IDBRequest,IDBTransaction,KeyOperation,MediaController,MessagePort,ModalWindow,Notification,SVGElementInstance,Screen,TextTrack,TextTrackCue,TextTrackList,WebSocket,WebSocketWorker,Worker,XMLHttpRequest,XMLHttpRequestEventTarget,XMLHttpRequestUpload'.split(',');
|
|
5
|
+
var i, global;
|
|
6
|
+
for (i = 0; i < globals.length; ++i) {
|
|
7
|
+
global = globals[i];
|
|
8
|
+
|
|
9
|
+
if (window[global] && window[global].prototype) {
|
|
10
|
+
_extendListenerPrototype(handler, window[global].prototype, shim);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function _extendListenerPrototype(handler, prototype, shim) {
|
|
16
|
+
if (prototype.hasOwnProperty && prototype.hasOwnProperty('addEventListener')) {
|
|
17
|
+
var oldAddEventListener = prototype.addEventListener;
|
|
18
|
+
while (oldAddEventListener._rollbarOldAdd && oldAddEventListener.belongsToShim) {
|
|
19
|
+
oldAddEventListener = oldAddEventListener._rollbarOldAdd;
|
|
20
|
+
}
|
|
21
|
+
var addFn = function(event, callback, bubble) {
|
|
22
|
+
oldAddEventListener.call(this, event, handler.wrap(callback), bubble);
|
|
23
|
+
};
|
|
24
|
+
addFn._rollbarOldAdd = oldAddEventListener;
|
|
25
|
+
addFn.belongsToShim = shim;
|
|
26
|
+
prototype.addEventListener = addFn;
|
|
27
|
+
|
|
28
|
+
var oldRemoveEventListener = prototype.removeEventListener;
|
|
29
|
+
while (oldRemoveEventListener._rollbarOldRemove && oldRemoveEventListener.belongsToShim) {
|
|
30
|
+
oldRemoveEventListener = oldRemoveEventListener._rollbarOldRemove;
|
|
31
|
+
}
|
|
32
|
+
var removeFn = function(event, callback, bubble) {
|
|
33
|
+
oldRemoveEventListener.call(this, event, callback && callback._rollbar_wrapped || callback, bubble);
|
|
34
|
+
};
|
|
35
|
+
removeFn._rollbarOldRemove = oldRemoveEventListener;
|
|
36
|
+
removeFn.belongsToShim = shim;
|
|
37
|
+
prototype.removeEventListener = removeFn;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports = wrapGlobals;
|
package/src/defaults.js
ADDED
package/src/predicates.js
CHANGED
|
@@ -4,12 +4,14 @@ var _ = require('../utility');
|
|
|
4
4
|
var API = require('../api');
|
|
5
5
|
var logger = require('./logger');
|
|
6
6
|
|
|
7
|
-
var
|
|
7
|
+
var Transport = require('./transport');
|
|
8
8
|
var urllib = require('../browser/url');
|
|
9
9
|
|
|
10
|
+
var Telemeter = require('../telemetry');
|
|
10
11
|
var transforms = require('./transforms');
|
|
11
12
|
var sharedTransforms = require('../transforms');
|
|
12
13
|
var sharedPredicates = require('../predicates');
|
|
14
|
+
var truncation = require('../truncation');
|
|
13
15
|
|
|
14
16
|
function Rollbar(options, client) {
|
|
15
17
|
if (_.isType(options, 'string')) {
|
|
@@ -22,10 +24,14 @@ function Rollbar(options, client) {
|
|
|
22
24
|
// This makes no sense in a long running app
|
|
23
25
|
delete this.options.maxItems;
|
|
24
26
|
this.options.environment = this.options.environment || 'unspecified';
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
|
|
28
|
+
var transport = new Transport(truncation);
|
|
29
|
+
var api = new API(this.options, transport, urllib, truncation);
|
|
30
|
+
var telemeter = new Telemeter(this.options)
|
|
31
|
+
this.client = client || new Client(this.options, api, logger, telemeter, 'react-native');
|
|
27
32
|
addTransformsToNotifier(this.client.notifier);
|
|
28
33
|
addPredicatesToQueue(this.client.queue);
|
|
34
|
+
_.setupJSON();
|
|
29
35
|
}
|
|
30
36
|
|
|
31
37
|
var _instance = null;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
var _ = require('../utility');
|
|
2
|
+
var scrub = require('../scrub');
|
|
2
3
|
var errorParser = require('../errorParser');
|
|
3
4
|
|
|
4
5
|
function baseData(item, options, callback) {
|
|
@@ -64,6 +65,10 @@ function handleItemWithError(item, options, callback) {
|
|
|
64
65
|
return callback(null, item);
|
|
65
66
|
}
|
|
66
67
|
|
|
68
|
+
if (options.addErrorContext) {
|
|
69
|
+
_.addErrorContext(item, [item.err]);
|
|
70
|
+
}
|
|
71
|
+
|
|
67
72
|
var err = item.err;
|
|
68
73
|
var parsedError = errorParser.parse(err);
|
|
69
74
|
var guess = errorParser.guessErrorClass(parsedError.message);
|
|
@@ -85,8 +90,9 @@ function handleItemWithError(item, options, callback) {
|
|
|
85
90
|
function scrubPayload(item, options, callback) {
|
|
86
91
|
var scrubHeaders = options.scrubHeaders || [];
|
|
87
92
|
var scrubFields = options.scrubFields || [];
|
|
93
|
+
var scrubPaths = options.scrubPaths || [];
|
|
88
94
|
scrubFields = scrubHeaders.concat(scrubFields);
|
|
89
|
-
item.data =
|
|
95
|
+
item.data = scrub(item.data, scrubFields, scrubPaths);
|
|
90
96
|
callback(null, item);
|
|
91
97
|
}
|
|
92
98
|
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
var _ = require('../utility');
|
|
2
|
-
var truncation = require('../truncation');
|
|
3
2
|
var logger = require('./logger');
|
|
4
3
|
|
|
5
4
|
var Buffer = require('buffer/').Buffer;
|
|
6
5
|
|
|
7
|
-
function
|
|
6
|
+
function Transport(truncation) {
|
|
7
|
+
this.rateLimitExpires = 0;
|
|
8
|
+
this.truncation = truncation;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
Transport.prototype.get = function(accessToken, options, params, callback) {
|
|
8
12
|
if (!callback || !_.isFunction(callback)) {
|
|
9
13
|
callback = function() {};
|
|
10
14
|
}
|
|
@@ -23,7 +27,7 @@ function get(accessToken, options, params, callback) {
|
|
|
23
27
|
});
|
|
24
28
|
}
|
|
25
29
|
|
|
26
|
-
function
|
|
30
|
+
Transport.prototype.post = function(accessToken, options, payload, callback) {
|
|
27
31
|
if (!callback || !_.isFunction(callback)) {
|
|
28
32
|
callback = function() {};
|
|
29
33
|
}
|
|
@@ -31,7 +35,13 @@ function post(accessToken, options, payload, callback) {
|
|
|
31
35
|
if (!payload) {
|
|
32
36
|
return callback(new Error('Cannot send empty request'));
|
|
33
37
|
}
|
|
34
|
-
|
|
38
|
+
|
|
39
|
+
var stringifyResult;
|
|
40
|
+
if (this.truncation) {
|
|
41
|
+
stringifyResult = this.truncation.truncate(payload);
|
|
42
|
+
} else {
|
|
43
|
+
stringifyResult = _.stringify(payload)
|
|
44
|
+
}
|
|
35
45
|
if (stringifyResult.error) {
|
|
36
46
|
logger.error('Problem stringifying payload. Giving up');
|
|
37
47
|
return callback(stringifyResult.error);
|
|
@@ -42,7 +52,7 @@ function post(accessToken, options, payload, callback) {
|
|
|
42
52
|
_makeRequest(headers, options, writeData, callback);
|
|
43
53
|
}
|
|
44
54
|
|
|
45
|
-
function
|
|
55
|
+
Transport.prototype.postJsonPayload = function(accessToken, options, jsonPayload, callback) {
|
|
46
56
|
if (!callback || !_.isFunction(callback)) {
|
|
47
57
|
callback = function() {};
|
|
48
58
|
}
|
|
@@ -114,8 +124,4 @@ function _wrapPostCallback(callback) {
|
|
|
114
124
|
}
|
|
115
125
|
}
|
|
116
126
|
|
|
117
|
-
module.exports =
|
|
118
|
-
get: get,
|
|
119
|
-
post: post,
|
|
120
|
-
postJsonPayload: postJsonPayload
|
|
121
|
-
};
|
|
127
|
+
module.exports = Transport;
|
package/src/rollbar.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
var RateLimiter = require('./rateLimiter');
|
|
2
2
|
var Queue = require('./queue');
|
|
3
3
|
var Notifier = require('./notifier');
|
|
4
|
-
var Telemeter = require('./telemetry');
|
|
5
4
|
var _ = require('./utility');
|
|
6
5
|
|
|
7
6
|
/*
|
|
@@ -11,7 +10,7 @@ var _ = require('./utility');
|
|
|
11
10
|
* @param api
|
|
12
11
|
* @param logger
|
|
13
12
|
*/
|
|
14
|
-
function Rollbar(options, api, logger, platform) {
|
|
13
|
+
function Rollbar(options, api, logger, telemeter, platform) {
|
|
15
14
|
this.options = _.merge(options);
|
|
16
15
|
this.logger = logger;
|
|
17
16
|
Rollbar.rateLimiter.configureGlobal(this.options);
|
|
@@ -31,7 +30,7 @@ function Rollbar(options, api, logger, platform) {
|
|
|
31
30
|
}
|
|
32
31
|
|
|
33
32
|
this.notifier = new Notifier(this.queue, this.options);
|
|
34
|
-
this.telemeter =
|
|
33
|
+
this.telemeter = telemeter;
|
|
35
34
|
setStackTraceLimit(options);
|
|
36
35
|
this.lastError = null;
|
|
37
36
|
this.lastErrorHash = 'none';
|
|
@@ -115,15 +114,15 @@ Rollbar.prototype.wait = function (callback) {
|
|
|
115
114
|
};
|
|
116
115
|
|
|
117
116
|
Rollbar.prototype.captureEvent = function (type, metadata, level) {
|
|
118
|
-
return this.telemeter.captureEvent(type, metadata, level);
|
|
117
|
+
return this.telemeter && this.telemeter.captureEvent(type, metadata, level);
|
|
119
118
|
};
|
|
120
119
|
|
|
121
120
|
Rollbar.prototype.captureDomContentLoaded = function (ts) {
|
|
122
|
-
return this.telemeter.captureDomContentLoaded(ts);
|
|
121
|
+
return this.telemeter && this.telemeter.captureDomContentLoaded(ts);
|
|
123
122
|
};
|
|
124
123
|
|
|
125
124
|
Rollbar.prototype.captureLoad = function (ts) {
|
|
126
|
-
return this.telemeter.captureLoad(ts);
|
|
125
|
+
return this.telemeter && this.telemeter.captureLoad(ts);
|
|
127
126
|
};
|
|
128
127
|
|
|
129
128
|
Rollbar.prototype.buildJsonPayload = function (item) {
|
|
@@ -153,8 +152,8 @@ Rollbar.prototype._log = function (defaultLevel, item) {
|
|
|
153
152
|
try {
|
|
154
153
|
this._addTracingInfo(item);
|
|
155
154
|
item.level = item.level || defaultLevel;
|
|
156
|
-
this.telemeter._captureRollbarItem(item);
|
|
157
|
-
item.telemetryEvents = this.telemeter.copyEvents();
|
|
155
|
+
this.telemeter && this.telemeter._captureRollbarItem(item);
|
|
156
|
+
item.telemetryEvents = (this.telemeter && this.telemeter.copyEvents()) || [];
|
|
158
157
|
this.notifier.log(item, callback);
|
|
159
158
|
} catch (e) {
|
|
160
159
|
this.logger.error(e);
|
|
@@ -235,7 +234,7 @@ function validateTracer(tracer) {
|
|
|
235
234
|
return false;
|
|
236
235
|
}
|
|
237
236
|
|
|
238
|
-
|
|
237
|
+
var scope = tracer.scope();
|
|
239
238
|
|
|
240
239
|
if (!scope || !scope.active || typeof scope.active !== 'function') {
|
|
241
240
|
return false;
|
|
@@ -253,7 +252,7 @@ function validateSpan(span) {
|
|
|
253
252
|
return false;
|
|
254
253
|
}
|
|
255
254
|
|
|
256
|
-
|
|
255
|
+
var spanContext = span.context();
|
|
257
256
|
|
|
258
257
|
if (!spanContext
|
|
259
258
|
|| !spanContext.toSpanId
|
package/src/scrub.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
var _ = require('./utility');
|
|
2
|
+
var traverse = require('./utility/traverse');
|
|
3
|
+
|
|
4
|
+
function scrub(data, scrubFields, scrubPaths) {
|
|
5
|
+
scrubFields = scrubFields || [];
|
|
6
|
+
|
|
7
|
+
if (scrubPaths) {
|
|
8
|
+
for (var i = 0; i < scrubPaths.length; ++i) {
|
|
9
|
+
scrubPath(data, scrubPaths[i]);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
var paramRes = _getScrubFieldRegexs(scrubFields);
|
|
14
|
+
var queryRes = _getScrubQueryParamRegexs(scrubFields);
|
|
15
|
+
|
|
16
|
+
function redactQueryParam(dummy0, paramPart) {
|
|
17
|
+
return paramPart + _.redact();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function paramScrubber(v) {
|
|
21
|
+
var i;
|
|
22
|
+
if (_.isType(v, 'string')) {
|
|
23
|
+
for (i = 0; i < queryRes.length; ++i) {
|
|
24
|
+
v = v.replace(queryRes[i], redactQueryParam);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return v;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function valScrubber(k, v) {
|
|
31
|
+
var i;
|
|
32
|
+
for (i = 0; i < paramRes.length; ++i) {
|
|
33
|
+
if (paramRes[i].test(k)) {
|
|
34
|
+
v = _.redact();
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return v;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function scrubber(k, v, seen) {
|
|
42
|
+
var tmpV = valScrubber(k, v);
|
|
43
|
+
if (tmpV === v) {
|
|
44
|
+
if (_.isType(v, 'object') || _.isType(v, 'array')) {
|
|
45
|
+
return traverse(v, scrubber, seen);
|
|
46
|
+
}
|
|
47
|
+
return paramScrubber(tmpV);
|
|
48
|
+
} else {
|
|
49
|
+
return tmpV;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return traverse(data, scrubber, []);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function scrubPath(obj, path) {
|
|
57
|
+
var keys = path.split('.');
|
|
58
|
+
var last = keys.length - 1;
|
|
59
|
+
try {
|
|
60
|
+
for (var i = 0; i <= last; ++i) {
|
|
61
|
+
if (i < last) {
|
|
62
|
+
obj = obj[keys[i]];
|
|
63
|
+
} else {
|
|
64
|
+
obj[keys[i]] = _.redact();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
} catch (e) {
|
|
68
|
+
// Missing key is OK;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function _getScrubFieldRegexs(scrubFields) {
|
|
73
|
+
var ret = [];
|
|
74
|
+
var pat;
|
|
75
|
+
for (var i = 0; i < scrubFields.length; ++i) {
|
|
76
|
+
pat = '^\\[?(%5[bB])?' + scrubFields[i] + '\\[?(%5[bB])?\\]?(%5[dD])?$';
|
|
77
|
+
ret.push(new RegExp(pat, 'i'));
|
|
78
|
+
}
|
|
79
|
+
return ret;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
function _getScrubQueryParamRegexs(scrubFields) {
|
|
84
|
+
var ret = [];
|
|
85
|
+
var pat;
|
|
86
|
+
for (var i = 0; i < scrubFields.length; ++i) {
|
|
87
|
+
pat = '\\[?(%5[bB])?' + scrubFields[i] + '\\[?(%5[bB])?\\]?(%5[dD])?';
|
|
88
|
+
ret.push(new RegExp('(' + pat + '=)([^&\\n]+)', 'igm'));
|
|
89
|
+
}
|
|
90
|
+
return ret;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
module.exports = scrub;
|
package/src/server/rollbar.js
CHANGED
|
@@ -11,9 +11,11 @@ var Transport = require('./transport');
|
|
|
11
11
|
var urllib = require('url');
|
|
12
12
|
var jsonBackup = require('json-stringify-safe');
|
|
13
13
|
|
|
14
|
+
var Telemeter = require('../telemetry');
|
|
14
15
|
var transforms = require('./transforms');
|
|
15
16
|
var sharedTransforms = require('../transforms');
|
|
16
17
|
var sharedPredicates = require('../predicates');
|
|
18
|
+
var truncation = require('../truncation');
|
|
17
19
|
|
|
18
20
|
function Rollbar(options, client) {
|
|
19
21
|
if (_.isType(options, 'string')) {
|
|
@@ -34,11 +36,13 @@ function Rollbar(options, client) {
|
|
|
34
36
|
this.lambdaContext = null;
|
|
35
37
|
this.lambdaTimeoutHandle = null;
|
|
36
38
|
var transport = new Transport();
|
|
37
|
-
var api = new API(this.options, transport, urllib, jsonBackup);
|
|
38
|
-
|
|
39
|
+
var api = new API(this.options, transport, urllib, truncation, jsonBackup);
|
|
40
|
+
var telemeter = new Telemeter(this.options)
|
|
41
|
+
this.client = client || new Client(this.options, api, logger, telemeter, 'server');
|
|
39
42
|
addTransformsToNotifier(this.client.notifier);
|
|
40
43
|
addPredicatesToQueue(this.client.queue);
|
|
41
44
|
this.setupUnhandledCapture();
|
|
45
|
+
_.setupJSON();
|
|
42
46
|
}
|
|
43
47
|
|
|
44
48
|
var _instance = null;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
var SourceMapConsumer = require('source-map').SourceMapConsumer;
|
|
2
2
|
var path = require('path');
|
|
3
3
|
var fs = require('fs');
|
|
4
|
-
var bufferFrom = require('buffer-from');
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Uses Node source-map to map transpiled JS stack locations to original
|
|
@@ -94,7 +93,7 @@ function retrieveSourceMap(source) {
|
|
|
94
93
|
if (reSourceMap.test(sourceMappingURL)) {
|
|
95
94
|
// Support source map URL as a data url
|
|
96
95
|
var rawData = sourceMappingURL.slice(sourceMappingURL.indexOf(',') + 1);
|
|
97
|
-
sourceMapData =
|
|
96
|
+
sourceMapData = Buffer.from(rawData, 'base64').toString();
|
|
98
97
|
sourceMappingURL = source;
|
|
99
98
|
} else {
|
|
100
99
|
// Support source map URLs relative to the source URL
|
package/src/server/transforms.js
CHANGED
|
@@ -3,6 +3,7 @@ var parser = require('./parser');
|
|
|
3
3
|
var requestIp = require('request-ip');
|
|
4
4
|
var url = require('url');
|
|
5
5
|
var _ = require('../utility');
|
|
6
|
+
var scrub = require('../scrub');
|
|
6
7
|
|
|
7
8
|
function baseData(item, options, callback) {
|
|
8
9
|
var environment = (options.payload && options.payload.environment) || options.environment;
|
|
@@ -88,6 +89,10 @@ function handleItemWithError(item, options, callback) {
|
|
|
88
89
|
} while (err !== undefined);
|
|
89
90
|
item.stackInfo = chain;
|
|
90
91
|
|
|
92
|
+
if (options.addErrorContext) {
|
|
93
|
+
_.addErrorContext(item, errors);
|
|
94
|
+
}
|
|
95
|
+
|
|
91
96
|
var cb = function(e) {
|
|
92
97
|
if (e) {
|
|
93
98
|
item.message = item.err.message || item.err.description || item.message || String(item.err);
|
|
@@ -108,6 +113,8 @@ function addRequestData(item, options, callback) {
|
|
|
108
113
|
return;
|
|
109
114
|
}
|
|
110
115
|
|
|
116
|
+
var baseUrl = req.baseUrl || '';
|
|
117
|
+
|
|
111
118
|
if (options.addRequestData && _.isFunction(options.addRequestData)) {
|
|
112
119
|
options.addRequestData(item.data, req);
|
|
113
120
|
callback(null, item);
|
|
@@ -118,11 +125,15 @@ function addRequestData(item, options, callback) {
|
|
|
118
125
|
_.filterIp(requestData, options.captureIp);
|
|
119
126
|
item.data.request = requestData;
|
|
120
127
|
|
|
128
|
+
var routePath;
|
|
129
|
+
|
|
121
130
|
if (req.route) {
|
|
122
|
-
|
|
131
|
+
routePath = req.route.path;
|
|
132
|
+
item.data.context = baseUrl && baseUrl.length ? baseUrl + routePath : routePath;
|
|
123
133
|
} else {
|
|
124
134
|
try {
|
|
125
|
-
|
|
135
|
+
routePath = req.app._router.matchRequest(req).path;
|
|
136
|
+
item.data.context = baseUrl && baseUrl.length ? baseUrl + routePath : routePath;
|
|
126
137
|
} catch (ignore) {
|
|
127
138
|
// Ignored
|
|
128
139
|
}
|
|
@@ -184,10 +195,11 @@ function addLambdaData(item, options, callback) {
|
|
|
184
195
|
function scrubPayload(item, options, callback) {
|
|
185
196
|
var scrubHeaders = options.scrubHeaders || [];
|
|
186
197
|
var scrubFields = options.scrubFields || [];
|
|
198
|
+
var scrubPaths = options.scrubPaths || [];
|
|
187
199
|
scrubFields = scrubHeaders.concat(scrubFields);
|
|
188
200
|
|
|
189
201
|
parseRequestBody(item.data.request, options);
|
|
190
|
-
item.data =
|
|
202
|
+
item.data = scrub(item.data, scrubFields, scrubPaths);
|
|
191
203
|
serializeRequestBody(item.data.request, options);
|
|
192
204
|
|
|
193
205
|
callback(null, item);
|
|
@@ -258,8 +270,10 @@ function _buildRequestData(req) {
|
|
|
258
270
|
var host = headers.host || '<no host>';
|
|
259
271
|
var proto = req.protocol || ((req.socket && req.socket.encrypted) ? 'https' : 'http' );
|
|
260
272
|
var parsedUrl;
|
|
273
|
+
var baseUrl = req.baseUrl || '';
|
|
261
274
|
if (_.isType(req.url, 'string')) {
|
|
262
|
-
|
|
275
|
+
var fullUrl = baseUrl && baseUrl.length ? baseUrl + req.url : req.url
|
|
276
|
+
parsedUrl = url.parse(fullUrl, true);
|
|
263
277
|
} else {
|
|
264
278
|
parsedUrl = req.url || {};
|
|
265
279
|
}
|