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/browser/telemetry.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
var _ = require('../utility');
|
|
2
2
|
var headers = require('../utility/headers');
|
|
3
|
+
var replace = require('../utility/replace');
|
|
3
4
|
var scrub = require('../scrub');
|
|
4
5
|
var urlparser = require('./url');
|
|
5
6
|
var domUtil = require('./domUtility');
|
|
@@ -18,17 +19,9 @@ var defaults = {
|
|
|
18
19
|
navigation: true,
|
|
19
20
|
connectivity: true,
|
|
20
21
|
contentSecurityPolicy: true,
|
|
21
|
-
errorOnContentSecurityPolicy: false
|
|
22
|
+
errorOnContentSecurityPolicy: false,
|
|
22
23
|
};
|
|
23
24
|
|
|
24
|
-
function replace(obj, name, replacement, replacements, type) {
|
|
25
|
-
var orig = obj[name];
|
|
26
|
-
obj[name] = replacement(orig);
|
|
27
|
-
if (replacements) {
|
|
28
|
-
replacements[type].push([obj, name, orig]);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
25
|
function restore(replacements, type) {
|
|
33
26
|
var b;
|
|
34
27
|
while (replacements[type].length) {
|
|
@@ -38,7 +31,9 @@ function restore(replacements, type) {
|
|
|
38
31
|
}
|
|
39
32
|
|
|
40
33
|
function nameFromDescription(description) {
|
|
41
|
-
if (!description || !description.attributes) {
|
|
34
|
+
if (!description || !description.attributes) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
42
37
|
var attrs = description.attributes;
|
|
43
38
|
for (var a = 0; a < attrs.length; ++a) {
|
|
44
39
|
if (attrs[a].key === 'name') {
|
|
@@ -53,9 +48,11 @@ function defaultValueScrubber(scrubFields) {
|
|
|
53
48
|
for (var i = 0; i < scrubFields.length; ++i) {
|
|
54
49
|
patterns.push(new RegExp(scrubFields[i], 'i'));
|
|
55
50
|
}
|
|
56
|
-
return function(description) {
|
|
51
|
+
return function (description) {
|
|
57
52
|
var name = nameFromDescription(description);
|
|
58
|
-
if (!name) {
|
|
53
|
+
if (!name) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
59
56
|
for (var i = 0; i < patterns.length; ++i) {
|
|
60
57
|
if (patterns[i].test(name)) {
|
|
61
58
|
return true;
|
|
@@ -88,19 +85,19 @@ function Instrumenter(options, telemeter, rollbar, _window, _document) {
|
|
|
88
85
|
network: [],
|
|
89
86
|
log: [],
|
|
90
87
|
navigation: [],
|
|
91
|
-
connectivity: []
|
|
88
|
+
connectivity: [],
|
|
92
89
|
};
|
|
93
90
|
this.eventRemovers = {
|
|
94
91
|
dom: [],
|
|
95
92
|
connectivity: [],
|
|
96
|
-
contentsecuritypolicy: []
|
|
93
|
+
contentsecuritypolicy: [],
|
|
97
94
|
};
|
|
98
95
|
|
|
99
96
|
this._location = this._window.location;
|
|
100
97
|
this._lastHref = this._location && this._location.href;
|
|
101
98
|
}
|
|
102
99
|
|
|
103
|
-
Instrumenter.prototype.configure = function(options) {
|
|
100
|
+
Instrumenter.prototype.configure = function (options) {
|
|
104
101
|
this.options = _.merge(this.options, options);
|
|
105
102
|
var autoInstrument = options.autoInstrument;
|
|
106
103
|
var oldSettings = _.merge(this.autoInstrument);
|
|
@@ -122,10 +119,14 @@ Instrumenter.prototype.configure = function(options) {
|
|
|
122
119
|
};
|
|
123
120
|
|
|
124
121
|
// eslint-disable-next-line complexity
|
|
125
|
-
Instrumenter.prototype.instrument = function(oldSettings) {
|
|
122
|
+
Instrumenter.prototype.instrument = function (oldSettings) {
|
|
126
123
|
if (this.autoInstrument.network && !(oldSettings && oldSettings.network)) {
|
|
127
124
|
this.instrumentNetwork();
|
|
128
|
-
} else if (
|
|
125
|
+
} else if (
|
|
126
|
+
!this.autoInstrument.network &&
|
|
127
|
+
oldSettings &&
|
|
128
|
+
oldSettings.network
|
|
129
|
+
) {
|
|
129
130
|
this.deinstrumentNetwork();
|
|
130
131
|
}
|
|
131
132
|
|
|
@@ -141,35 +142,56 @@ Instrumenter.prototype.instrument = function(oldSettings) {
|
|
|
141
142
|
this.deinstrumentDom();
|
|
142
143
|
}
|
|
143
144
|
|
|
144
|
-
if (
|
|
145
|
+
if (
|
|
146
|
+
this.autoInstrument.navigation &&
|
|
147
|
+
!(oldSettings && oldSettings.navigation)
|
|
148
|
+
) {
|
|
145
149
|
this.instrumentNavigation();
|
|
146
|
-
} else if (
|
|
150
|
+
} else if (
|
|
151
|
+
!this.autoInstrument.navigation &&
|
|
152
|
+
oldSettings &&
|
|
153
|
+
oldSettings.navigation
|
|
154
|
+
) {
|
|
147
155
|
this.deinstrumentNavigation();
|
|
148
156
|
}
|
|
149
157
|
|
|
150
|
-
if (
|
|
158
|
+
if (
|
|
159
|
+
this.autoInstrument.connectivity &&
|
|
160
|
+
!(oldSettings && oldSettings.connectivity)
|
|
161
|
+
) {
|
|
151
162
|
this.instrumentConnectivity();
|
|
152
|
-
} else if (
|
|
163
|
+
} else if (
|
|
164
|
+
!this.autoInstrument.connectivity &&
|
|
165
|
+
oldSettings &&
|
|
166
|
+
oldSettings.connectivity
|
|
167
|
+
) {
|
|
153
168
|
this.deinstrumentConnectivity();
|
|
154
169
|
}
|
|
155
170
|
|
|
156
|
-
if (
|
|
171
|
+
if (
|
|
172
|
+
this.autoInstrument.contentSecurityPolicy &&
|
|
173
|
+
!(oldSettings && oldSettings.contentSecurityPolicy)
|
|
174
|
+
) {
|
|
157
175
|
this.instrumentContentSecurityPolicy();
|
|
158
|
-
} else if (
|
|
176
|
+
} else if (
|
|
177
|
+
!this.autoInstrument.contentSecurityPolicy &&
|
|
178
|
+
oldSettings &&
|
|
179
|
+
oldSettings.contentSecurityPolicy
|
|
180
|
+
) {
|
|
159
181
|
this.deinstrumentContentSecurityPolicy();
|
|
160
182
|
}
|
|
161
183
|
};
|
|
162
184
|
|
|
163
|
-
Instrumenter.prototype.deinstrumentNetwork = function() {
|
|
185
|
+
Instrumenter.prototype.deinstrumentNetwork = function () {
|
|
164
186
|
restore(this.replacements, 'network');
|
|
165
187
|
};
|
|
166
188
|
|
|
167
|
-
Instrumenter.prototype.instrumentNetwork = function() {
|
|
189
|
+
Instrumenter.prototype.instrumentNetwork = function () {
|
|
168
190
|
var self = this;
|
|
169
191
|
|
|
170
192
|
function wrapProp(prop, xhr) {
|
|
171
193
|
if (prop in xhr && _.isFunction(xhr[prop])) {
|
|
172
|
-
replace(xhr, prop, function(orig) {
|
|
194
|
+
replace(xhr, prop, function (orig) {
|
|
173
195
|
return self.rollbar.wrap(orig);
|
|
174
196
|
});
|
|
175
197
|
}
|
|
@@ -177,280 +199,351 @@ Instrumenter.prototype.instrumentNetwork = function() {
|
|
|
177
199
|
|
|
178
200
|
if ('XMLHttpRequest' in this._window) {
|
|
179
201
|
var xhrp = this._window.XMLHttpRequest.prototype;
|
|
180
|
-
replace(
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
this.__rollbar_xhr
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
replace(xhrp, 'setRequestHeader', function(orig) {
|
|
204
|
-
return function(header, value) {
|
|
205
|
-
// If xhr.open is async, __rollbar_xhr may not be initialized yet.
|
|
206
|
-
if (!this.__rollbar_xhr) {
|
|
207
|
-
this.__rollbar_xhr = {};
|
|
208
|
-
}
|
|
209
|
-
if (_.isType(header, 'string') && _.isType(value, 'string')) {
|
|
210
|
-
if (self.autoInstrument.networkRequestHeaders) {
|
|
211
|
-
if (!this.__rollbar_xhr.request_headers) {
|
|
212
|
-
this.__rollbar_xhr.request_headers = {};
|
|
202
|
+
replace(
|
|
203
|
+
xhrp,
|
|
204
|
+
'open',
|
|
205
|
+
function (orig) {
|
|
206
|
+
return function (method, url) {
|
|
207
|
+
var isUrlObject = _isUrlObject(url);
|
|
208
|
+
if (_.isType(url, 'string') || isUrlObject) {
|
|
209
|
+
url = isUrlObject ? url.toString() : url;
|
|
210
|
+
if (this.__rollbar_xhr) {
|
|
211
|
+
this.__rollbar_xhr.method = method;
|
|
212
|
+
this.__rollbar_xhr.url = url;
|
|
213
|
+
this.__rollbar_xhr.status_code = null;
|
|
214
|
+
this.__rollbar_xhr.start_time_ms = _.now();
|
|
215
|
+
this.__rollbar_xhr.end_time_ms = null;
|
|
216
|
+
} else {
|
|
217
|
+
this.__rollbar_xhr = {
|
|
218
|
+
method: method,
|
|
219
|
+
url: url,
|
|
220
|
+
status_code: null,
|
|
221
|
+
start_time_ms: _.now(),
|
|
222
|
+
end_time_ms: null,
|
|
223
|
+
};
|
|
213
224
|
}
|
|
214
|
-
this.__rollbar_xhr.request_headers[header] = value;
|
|
215
225
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
226
|
+
return orig.apply(this, arguments);
|
|
227
|
+
};
|
|
228
|
+
},
|
|
229
|
+
this.replacements,
|
|
230
|
+
'network',
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
replace(
|
|
234
|
+
xhrp,
|
|
235
|
+
'setRequestHeader',
|
|
236
|
+
function (orig) {
|
|
237
|
+
return function (header, value) {
|
|
238
|
+
// If xhr.open is async, __rollbar_xhr may not be initialized yet.
|
|
239
|
+
if (!this.__rollbar_xhr) {
|
|
240
|
+
this.__rollbar_xhr = {};
|
|
219
241
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
replace(xhrp, 'send', function(orig) {
|
|
226
|
-
/* eslint-disable no-unused-vars */
|
|
227
|
-
return function(data) {
|
|
228
|
-
/* eslint-enable no-unused-vars */
|
|
229
|
-
var xhr = this;
|
|
230
|
-
|
|
231
|
-
function onreadystatechangeHandler() {
|
|
232
|
-
if (xhr.__rollbar_xhr) {
|
|
233
|
-
if (xhr.__rollbar_xhr.status_code === null) {
|
|
234
|
-
xhr.__rollbar_xhr.status_code = 0;
|
|
235
|
-
if (self.autoInstrument.networkRequestBody) {
|
|
236
|
-
xhr.__rollbar_xhr.request = data;
|
|
242
|
+
if (_.isType(header, 'string') && _.isType(value, 'string')) {
|
|
243
|
+
if (self.autoInstrument.networkRequestHeaders) {
|
|
244
|
+
if (!this.__rollbar_xhr.request_headers) {
|
|
245
|
+
this.__rollbar_xhr.request_headers = {};
|
|
237
246
|
}
|
|
238
|
-
|
|
247
|
+
this.__rollbar_xhr.request_headers[header] = value;
|
|
239
248
|
}
|
|
240
|
-
if
|
|
241
|
-
|
|
249
|
+
// We want the content type even if request header telemetry is off.
|
|
250
|
+
if (header.toLowerCase() === 'content-type') {
|
|
251
|
+
this.__rollbar_xhr.request_content_type = value;
|
|
242
252
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
253
|
+
}
|
|
254
|
+
return orig.apply(this, arguments);
|
|
255
|
+
};
|
|
256
|
+
},
|
|
257
|
+
this.replacements,
|
|
258
|
+
'network',
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
replace(
|
|
262
|
+
xhrp,
|
|
263
|
+
'send',
|
|
264
|
+
function (orig) {
|
|
265
|
+
/* eslint-disable no-unused-vars */
|
|
266
|
+
return function (data) {
|
|
267
|
+
/* eslint-enable no-unused-vars */
|
|
268
|
+
var xhr = this;
|
|
269
|
+
|
|
270
|
+
function onreadystatechangeHandler() {
|
|
271
|
+
if (xhr.__rollbar_xhr) {
|
|
272
|
+
if (xhr.__rollbar_xhr.status_code === null) {
|
|
273
|
+
xhr.__rollbar_xhr.status_code = 0;
|
|
274
|
+
if (self.autoInstrument.networkRequestBody) {
|
|
275
|
+
xhr.__rollbar_xhr.request = data;
|
|
276
|
+
}
|
|
277
|
+
xhr.__rollbar_event = self.captureNetwork(
|
|
278
|
+
xhr.__rollbar_xhr,
|
|
279
|
+
'xhr',
|
|
280
|
+
undefined,
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
if (xhr.readyState < 2) {
|
|
284
|
+
xhr.__rollbar_xhr.start_time_ms = _.now();
|
|
285
|
+
}
|
|
286
|
+
if (xhr.readyState > 3) {
|
|
287
|
+
xhr.__rollbar_xhr.end_time_ms = _.now();
|
|
288
|
+
|
|
289
|
+
var headers = null;
|
|
290
|
+
xhr.__rollbar_xhr.response_content_type =
|
|
291
|
+
xhr.getResponseHeader('Content-Type');
|
|
292
|
+
if (self.autoInstrument.networkResponseHeaders) {
|
|
293
|
+
var headersConfig =
|
|
294
|
+
self.autoInstrument.networkResponseHeaders;
|
|
295
|
+
headers = {};
|
|
296
|
+
try {
|
|
297
|
+
var header, i;
|
|
298
|
+
if (headersConfig === true) {
|
|
299
|
+
var allHeaders = xhr.getAllResponseHeaders();
|
|
300
|
+
if (allHeaders) {
|
|
301
|
+
var arr = allHeaders.trim().split(/[\r\n]+/);
|
|
302
|
+
var parts, value;
|
|
303
|
+
for (i = 0; i < arr.length; i++) {
|
|
304
|
+
parts = arr[i].split(': ');
|
|
305
|
+
header = parts.shift();
|
|
306
|
+
value = parts.join(': ');
|
|
307
|
+
headers[header] = value;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
} else {
|
|
311
|
+
for (i = 0; i < headersConfig.length; i++) {
|
|
312
|
+
header = headersConfig[i];
|
|
313
|
+
headers[header] = xhr.getResponseHeader(header);
|
|
263
314
|
}
|
|
264
315
|
}
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
headers[header] = xhr.getResponseHeader(header);
|
|
269
|
-
}
|
|
316
|
+
} catch (e) {
|
|
317
|
+
/* we ignore the errors here that could come from different
|
|
318
|
+
* browser issues with the xhr methods */
|
|
270
319
|
}
|
|
271
|
-
} catch (e) {
|
|
272
|
-
/* we ignore the errors here that could come from different
|
|
273
|
-
* browser issues with the xhr methods */
|
|
274
320
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
321
|
+
var body = null;
|
|
322
|
+
if (self.autoInstrument.networkResponseBody) {
|
|
323
|
+
try {
|
|
324
|
+
body = xhr.responseText;
|
|
325
|
+
} catch (e) {
|
|
326
|
+
/* ignore errors from reading responseText */
|
|
327
|
+
}
|
|
282
328
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
329
|
+
var response = null;
|
|
330
|
+
if (body || headers) {
|
|
331
|
+
response = {};
|
|
332
|
+
if (body) {
|
|
333
|
+
if (
|
|
334
|
+
self.isJsonContentType(
|
|
335
|
+
xhr.__rollbar_xhr.response_content_type,
|
|
336
|
+
)
|
|
337
|
+
) {
|
|
338
|
+
response.body = self.scrubJson(body);
|
|
339
|
+
} else {
|
|
340
|
+
response.body = body;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
if (headers) {
|
|
344
|
+
response.headers = headers;
|
|
292
345
|
}
|
|
293
346
|
}
|
|
294
|
-
if (
|
|
295
|
-
response
|
|
347
|
+
if (response) {
|
|
348
|
+
xhr.__rollbar_xhr.response = response;
|
|
349
|
+
}
|
|
350
|
+
try {
|
|
351
|
+
var code = xhr.status;
|
|
352
|
+
code = code === 1223 ? 204 : code;
|
|
353
|
+
xhr.__rollbar_xhr.status_code = code;
|
|
354
|
+
xhr.__rollbar_event.level =
|
|
355
|
+
self.telemeter.levelFromStatus(code);
|
|
356
|
+
self.errorOnHttpStatus(xhr.__rollbar_xhr);
|
|
357
|
+
} catch (e) {
|
|
358
|
+
/* ignore possible exception from xhr.status */
|
|
296
359
|
}
|
|
297
|
-
}
|
|
298
|
-
if (response) {
|
|
299
|
-
xhr.__rollbar_xhr.response = response;
|
|
300
|
-
}
|
|
301
|
-
try {
|
|
302
|
-
var code = xhr.status;
|
|
303
|
-
code = code === 1223 ? 204 : code;
|
|
304
|
-
xhr.__rollbar_xhr.status_code = code;
|
|
305
|
-
xhr.__rollbar_event.level = self.telemeter.levelFromStatus(code);
|
|
306
|
-
self.errorOnHttpStatus(xhr.__rollbar_xhr);
|
|
307
|
-
} catch (e) {
|
|
308
|
-
/* ignore possible exception from xhr.status */
|
|
309
360
|
}
|
|
310
361
|
}
|
|
311
362
|
}
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
wrapProp('onload', xhr);
|
|
315
|
-
wrapProp('onerror', xhr);
|
|
316
|
-
wrapProp('onprogress', xhr);
|
|
317
363
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
364
|
+
wrapProp('onload', xhr);
|
|
365
|
+
wrapProp('onerror', xhr);
|
|
366
|
+
wrapProp('onprogress', xhr);
|
|
367
|
+
|
|
368
|
+
if (
|
|
369
|
+
'onreadystatechange' in xhr &&
|
|
370
|
+
_.isFunction(xhr.onreadystatechange)
|
|
371
|
+
) {
|
|
372
|
+
replace(xhr, 'onreadystatechange', function (orig) {
|
|
373
|
+
return self.rollbar.wrap(
|
|
374
|
+
orig,
|
|
375
|
+
undefined,
|
|
376
|
+
onreadystatechangeHandler,
|
|
377
|
+
);
|
|
378
|
+
});
|
|
379
|
+
} else {
|
|
380
|
+
xhr.onreadystatechange = onreadystatechangeHandler;
|
|
381
|
+
}
|
|
382
|
+
if (xhr.__rollbar_xhr && self.trackHttpErrors()) {
|
|
383
|
+
xhr.__rollbar_xhr.stack = new Error().stack;
|
|
384
|
+
}
|
|
385
|
+
return orig.apply(this, arguments);
|
|
386
|
+
};
|
|
387
|
+
},
|
|
388
|
+
this.replacements,
|
|
389
|
+
'network',
|
|
390
|
+
);
|
|
331
391
|
}
|
|
332
392
|
|
|
333
393
|
if ('fetch' in this._window) {
|
|
334
|
-
replace(
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
var url;
|
|
345
|
-
if (_.isType(input, 'string')) {
|
|
346
|
-
url = input;
|
|
347
|
-
} else if (input) {
|
|
348
|
-
url = input.url;
|
|
349
|
-
if (input.method) {
|
|
350
|
-
method = input.method;
|
|
394
|
+
replace(
|
|
395
|
+
this._window,
|
|
396
|
+
'fetch',
|
|
397
|
+
function (orig) {
|
|
398
|
+
/* eslint-disable no-unused-vars */
|
|
399
|
+
return function (fn, t) {
|
|
400
|
+
/* eslint-enable no-unused-vars */
|
|
401
|
+
var args = new Array(arguments.length);
|
|
402
|
+
for (var i = 0, len = args.length; i < len; i++) {
|
|
403
|
+
args[i] = arguments[i];
|
|
351
404
|
}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
if (args[1] && args[1].headers) {
|
|
364
|
-
// Argument may be a Headers object, or plain object. Ensure here that
|
|
365
|
-
// we are working with a Headers object with case-insensitive keys.
|
|
366
|
-
var reqHeaders = headers(args[1].headers);
|
|
367
|
-
|
|
368
|
-
metadata.request_content_type = reqHeaders.get('Content-Type');
|
|
369
|
-
|
|
370
|
-
if (self.autoInstrument.networkRequestHeaders) {
|
|
371
|
-
metadata.request_headers = self.fetchHeaders(reqHeaders, self.autoInstrument.networkRequestHeaders)
|
|
405
|
+
var input = args[0];
|
|
406
|
+
var method = 'GET';
|
|
407
|
+
var url;
|
|
408
|
+
var isUrlObject = _isUrlObject(input);
|
|
409
|
+
if (_.isType(input, 'string') || isUrlObject) {
|
|
410
|
+
url = isUrlObject ? input.toString() : input;
|
|
411
|
+
} else if (input) {
|
|
412
|
+
url = input.url;
|
|
413
|
+
if (input.method) {
|
|
414
|
+
method = input.method;
|
|
415
|
+
}
|
|
372
416
|
}
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
if (self.autoInstrument.networkRequestBody) {
|
|
376
|
-
if (args[1] && args[1].body) {
|
|
377
|
-
metadata.request = args[1].body;
|
|
378
|
-
} else if (args[0] && !_.isType(args[0], 'string') && args[0].body) {
|
|
379
|
-
metadata.request = args[0].body;
|
|
417
|
+
if (args[1] && args[1].method) {
|
|
418
|
+
method = args[1].method;
|
|
380
419
|
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
420
|
+
var metadata = {
|
|
421
|
+
method: method,
|
|
422
|
+
url: url,
|
|
423
|
+
status_code: null,
|
|
424
|
+
start_time_ms: _.now(),
|
|
425
|
+
end_time_ms: null,
|
|
426
|
+
};
|
|
427
|
+
if (args[1] && args[1].headers) {
|
|
428
|
+
// Argument may be a Headers object, or plain object. Ensure here that
|
|
429
|
+
// we are working with a Headers object with case-insensitive keys.
|
|
430
|
+
var reqHeaders = headers(args[1].headers);
|
|
431
|
+
|
|
432
|
+
metadata.request_content_type = reqHeaders.get('Content-Type');
|
|
433
|
+
|
|
434
|
+
if (self.autoInstrument.networkRequestHeaders) {
|
|
435
|
+
metadata.request_headers = self.fetchHeaders(
|
|
436
|
+
reqHeaders,
|
|
437
|
+
self.autoInstrument.networkRequestHeaders,
|
|
438
|
+
);
|
|
439
|
+
}
|
|
396
440
|
}
|
|
397
|
-
|
|
398
|
-
if (self.autoInstrument.
|
|
399
|
-
if (
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
441
|
+
|
|
442
|
+
if (self.autoInstrument.networkRequestBody) {
|
|
443
|
+
if (args[1] && args[1].body) {
|
|
444
|
+
metadata.request = args[1].body;
|
|
445
|
+
} else if (
|
|
446
|
+
args[0] &&
|
|
447
|
+
!_.isType(args[0], 'string') &&
|
|
448
|
+
args[0].body
|
|
449
|
+
) {
|
|
450
|
+
metadata.request = args[0].body;
|
|
403
451
|
}
|
|
404
452
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
453
|
+
self.captureNetwork(metadata, 'fetch', undefined);
|
|
454
|
+
if (self.trackHttpErrors()) {
|
|
455
|
+
metadata.stack = new Error().stack;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// Start our handler before returning the promise. This allows resp.clone()
|
|
459
|
+
// to execute before other handlers touch the response.
|
|
460
|
+
return orig.apply(this, args).then(function (resp) {
|
|
461
|
+
metadata.end_time_ms = _.now();
|
|
462
|
+
metadata.status_code = resp.status;
|
|
463
|
+
metadata.response_content_type = resp.headers.get('Content-Type');
|
|
464
|
+
var headers = null;
|
|
465
|
+
if (self.autoInstrument.networkResponseHeaders) {
|
|
466
|
+
headers = self.fetchHeaders(
|
|
467
|
+
resp.headers,
|
|
468
|
+
self.autoInstrument.networkResponseHeaders,
|
|
469
|
+
);
|
|
470
|
+
}
|
|
471
|
+
var body = null;
|
|
472
|
+
if (self.autoInstrument.networkResponseBody) {
|
|
473
|
+
if (typeof resp.text === 'function') {
|
|
474
|
+
// Response.text() is not implemented on some platforms
|
|
475
|
+
// The response must be cloned to prevent reading (and locking) the original stream.
|
|
476
|
+
// This must be done before other handlers touch the response.
|
|
477
|
+
body = resp.clone().text(); //returns a Promise
|
|
419
478
|
}
|
|
420
479
|
}
|
|
421
|
-
if (headers) {
|
|
422
|
-
metadata.response
|
|
480
|
+
if (headers || body) {
|
|
481
|
+
metadata.response = {};
|
|
482
|
+
if (body) {
|
|
483
|
+
// Test to ensure body is a Promise, which it should always be.
|
|
484
|
+
if (typeof body.then === 'function') {
|
|
485
|
+
body.then(function (text) {
|
|
486
|
+
if (
|
|
487
|
+
text &&
|
|
488
|
+
self.isJsonContentType(metadata.response_content_type)
|
|
489
|
+
) {
|
|
490
|
+
metadata.response.body = self.scrubJson(text);
|
|
491
|
+
} else {
|
|
492
|
+
metadata.response.body = text;
|
|
493
|
+
}
|
|
494
|
+
});
|
|
495
|
+
} else {
|
|
496
|
+
metadata.response.body = body;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
if (headers) {
|
|
500
|
+
metadata.response.headers = headers;
|
|
501
|
+
}
|
|
423
502
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
|
|
503
|
+
self.errorOnHttpStatus(metadata);
|
|
504
|
+
return resp;
|
|
505
|
+
});
|
|
506
|
+
};
|
|
507
|
+
},
|
|
508
|
+
this.replacements,
|
|
509
|
+
'network',
|
|
510
|
+
);
|
|
430
511
|
}
|
|
431
512
|
};
|
|
432
513
|
|
|
433
|
-
Instrumenter.prototype.captureNetwork = function(
|
|
434
|
-
|
|
514
|
+
Instrumenter.prototype.captureNetwork = function (
|
|
515
|
+
metadata,
|
|
516
|
+
subtype,
|
|
517
|
+
rollbarUUID,
|
|
518
|
+
) {
|
|
519
|
+
if (
|
|
520
|
+
metadata.request &&
|
|
521
|
+
this.isJsonContentType(metadata.request_content_type)
|
|
522
|
+
) {
|
|
435
523
|
metadata.request = this.scrubJson(metadata.request);
|
|
436
524
|
}
|
|
437
525
|
return this.telemeter.captureNetwork(metadata, subtype, rollbarUUID);
|
|
438
526
|
};
|
|
439
527
|
|
|
440
|
-
Instrumenter.prototype.isJsonContentType = function(contentType) {
|
|
441
|
-
return
|
|
442
|
-
|
|
528
|
+
Instrumenter.prototype.isJsonContentType = function (contentType) {
|
|
529
|
+
return contentType &&
|
|
530
|
+
_.isType(contentType, 'string') &&
|
|
531
|
+
contentType.toLowerCase().includes('json')
|
|
532
|
+
? true
|
|
533
|
+
: false;
|
|
534
|
+
};
|
|
443
535
|
|
|
444
|
-
Instrumenter.prototype.scrubJson = function(json) {
|
|
536
|
+
Instrumenter.prototype.scrubJson = function (json) {
|
|
445
537
|
return JSON.stringify(scrub(JSON.parse(json), this.options.scrubFields));
|
|
446
|
-
}
|
|
538
|
+
};
|
|
447
539
|
|
|
448
|
-
Instrumenter.prototype.fetchHeaders = function(inHeaders, headersConfig) {
|
|
540
|
+
Instrumenter.prototype.fetchHeaders = function (inHeaders, headersConfig) {
|
|
449
541
|
var outHeaders = {};
|
|
450
542
|
try {
|
|
451
543
|
var i;
|
|
452
544
|
if (headersConfig === true) {
|
|
453
|
-
if (typeof inHeaders.entries === 'function') {
|
|
545
|
+
if (typeof inHeaders.entries === 'function') {
|
|
546
|
+
// Headers.entries() is not implemented in IE
|
|
454
547
|
var allHeaders = inHeaders.entries();
|
|
455
548
|
var currentHeader = allHeaders.next();
|
|
456
549
|
while (!currentHeader.done) {
|
|
@@ -459,7 +552,7 @@ Instrumenter.prototype.fetchHeaders = function(inHeaders, headersConfig) {
|
|
|
459
552
|
}
|
|
460
553
|
}
|
|
461
554
|
} else {
|
|
462
|
-
for (i=0; i < headersConfig.length; i++) {
|
|
555
|
+
for (i = 0; i < headersConfig.length; i++) {
|
|
463
556
|
var header = headersConfig[i];
|
|
464
557
|
outHeaders[header] = inHeaders.get(header);
|
|
465
558
|
}
|
|
@@ -468,27 +561,31 @@ Instrumenter.prototype.fetchHeaders = function(inHeaders, headersConfig) {
|
|
|
468
561
|
/* ignore probable IE errors */
|
|
469
562
|
}
|
|
470
563
|
return outHeaders;
|
|
471
|
-
}
|
|
564
|
+
};
|
|
472
565
|
|
|
473
|
-
Instrumenter.prototype.trackHttpErrors = function() {
|
|
474
|
-
return
|
|
566
|
+
Instrumenter.prototype.trackHttpErrors = function () {
|
|
567
|
+
return (
|
|
568
|
+
this.autoInstrument.networkErrorOnHttp5xx ||
|
|
475
569
|
this.autoInstrument.networkErrorOnHttp4xx ||
|
|
476
|
-
this.autoInstrument.networkErrorOnHttp0
|
|
477
|
-
|
|
570
|
+
this.autoInstrument.networkErrorOnHttp0
|
|
571
|
+
);
|
|
572
|
+
};
|
|
478
573
|
|
|
479
|
-
Instrumenter.prototype.errorOnHttpStatus = function(metadata) {
|
|
574
|
+
Instrumenter.prototype.errorOnHttpStatus = function (metadata) {
|
|
480
575
|
var status = metadata.status_code;
|
|
481
576
|
|
|
482
|
-
if (
|
|
577
|
+
if (
|
|
578
|
+
(status >= 500 && this.autoInstrument.networkErrorOnHttp5xx) ||
|
|
483
579
|
(status >= 400 && this.autoInstrument.networkErrorOnHttp4xx) ||
|
|
484
|
-
(status === 0 && this.autoInstrument.networkErrorOnHttp0)
|
|
580
|
+
(status === 0 && this.autoInstrument.networkErrorOnHttp0)
|
|
581
|
+
) {
|
|
485
582
|
var error = new Error('HTTP request failed with Status ' + status);
|
|
486
583
|
error.stack = metadata.stack;
|
|
487
584
|
this.rollbar.error(error, { skipFrames: 1 });
|
|
488
585
|
}
|
|
489
|
-
}
|
|
586
|
+
};
|
|
490
587
|
|
|
491
|
-
Instrumenter.prototype.deinstrumentConsole = function() {
|
|
588
|
+
Instrumenter.prototype.deinstrumentConsole = function () {
|
|
492
589
|
if (!('console' in this._window && this._window.console.log)) {
|
|
493
590
|
return;
|
|
494
591
|
}
|
|
@@ -499,7 +596,7 @@ Instrumenter.prototype.deinstrumentConsole = function() {
|
|
|
499
596
|
}
|
|
500
597
|
};
|
|
501
598
|
|
|
502
|
-
Instrumenter.prototype.instrumentConsole = function() {
|
|
599
|
+
Instrumenter.prototype.instrumentConsole = function () {
|
|
503
600
|
if (!('console' in this._window && this._window.console.log)) {
|
|
504
601
|
return;
|
|
505
602
|
}
|
|
@@ -513,7 +610,7 @@ Instrumenter.prototype.instrumentConsole = function() {
|
|
|
513
610
|
var orig = c[method];
|
|
514
611
|
var origConsole = c;
|
|
515
612
|
var level = method === 'warn' ? 'warning' : method;
|
|
516
|
-
c[method] = function() {
|
|
613
|
+
c[method] = function () {
|
|
517
614
|
var args = Array.prototype.slice.call(arguments);
|
|
518
615
|
var message = _.formatArgsAsString(args);
|
|
519
616
|
self.telemeter.captureLog(message, level);
|
|
@@ -523,9 +620,9 @@ Instrumenter.prototype.instrumentConsole = function() {
|
|
|
523
620
|
};
|
|
524
621
|
self.replacements['log'].push([method, orig]);
|
|
525
622
|
}
|
|
526
|
-
var methods = ['debug','info','warn','error','log'];
|
|
623
|
+
var methods = ['debug', 'info', 'warn', 'error', 'log'];
|
|
527
624
|
try {
|
|
528
|
-
for (var i=0, len=methods.length; i < len; i++) {
|
|
625
|
+
for (var i = 0, len = methods.length; i < len; i++) {
|
|
529
626
|
wrapConsole(methods[i]);
|
|
530
627
|
}
|
|
531
628
|
} catch (e) {
|
|
@@ -533,30 +630,43 @@ Instrumenter.prototype.instrumentConsole = function() {
|
|
|
533
630
|
}
|
|
534
631
|
};
|
|
535
632
|
|
|
536
|
-
Instrumenter.prototype.deinstrumentDom = function() {
|
|
633
|
+
Instrumenter.prototype.deinstrumentDom = function () {
|
|
537
634
|
if (!('addEventListener' in this._window || 'attachEvent' in this._window)) {
|
|
538
635
|
return;
|
|
539
636
|
}
|
|
540
637
|
this.removeListeners('dom');
|
|
541
638
|
};
|
|
542
639
|
|
|
543
|
-
Instrumenter.prototype.instrumentDom = function() {
|
|
640
|
+
Instrumenter.prototype.instrumentDom = function () {
|
|
544
641
|
if (!('addEventListener' in this._window || 'attachEvent' in this._window)) {
|
|
545
642
|
return;
|
|
546
643
|
}
|
|
547
644
|
var clickHandler = this.handleClick.bind(this);
|
|
548
645
|
var blurHandler = this.handleBlur.bind(this);
|
|
549
646
|
this.addListener('dom', this._window, 'click', 'onclick', clickHandler, true);
|
|
550
|
-
this.addListener(
|
|
647
|
+
this.addListener(
|
|
648
|
+
'dom',
|
|
649
|
+
this._window,
|
|
650
|
+
'blur',
|
|
651
|
+
'onfocusout',
|
|
652
|
+
blurHandler,
|
|
653
|
+
true,
|
|
654
|
+
);
|
|
551
655
|
};
|
|
552
656
|
|
|
553
|
-
Instrumenter.prototype.handleClick = function(evt) {
|
|
657
|
+
Instrumenter.prototype.handleClick = function (evt) {
|
|
554
658
|
try {
|
|
555
659
|
var e = domUtil.getElementFromEvent(evt, this._document);
|
|
556
660
|
var hasTag = e && e.tagName;
|
|
557
|
-
var anchorOrButton =
|
|
558
|
-
|
|
559
|
-
|
|
661
|
+
var anchorOrButton =
|
|
662
|
+
domUtil.isDescribedElement(e, 'a') ||
|
|
663
|
+
domUtil.isDescribedElement(e, 'button');
|
|
664
|
+
if (
|
|
665
|
+
hasTag &&
|
|
666
|
+
(anchorOrButton ||
|
|
667
|
+
domUtil.isDescribedElement(e, 'input', ['button', 'submit']))
|
|
668
|
+
) {
|
|
669
|
+
this.captureDomEvent('click', e);
|
|
560
670
|
} else if (domUtil.isDescribedElement(e, 'input', ['checkbox', 'radio'])) {
|
|
561
671
|
this.captureDomEvent('input', e, e.value, e.checked);
|
|
562
672
|
}
|
|
@@ -565,15 +675,28 @@ Instrumenter.prototype.handleClick = function(evt) {
|
|
|
565
675
|
}
|
|
566
676
|
};
|
|
567
677
|
|
|
568
|
-
Instrumenter.prototype.handleBlur = function(evt) {
|
|
678
|
+
Instrumenter.prototype.handleBlur = function (evt) {
|
|
569
679
|
try {
|
|
570
680
|
var e = domUtil.getElementFromEvent(evt, this._document);
|
|
571
681
|
if (e && e.tagName) {
|
|
572
682
|
if (domUtil.isDescribedElement(e, 'textarea')) {
|
|
573
683
|
this.captureDomEvent('input', e, e.value);
|
|
574
|
-
} else if (
|
|
684
|
+
} else if (
|
|
685
|
+
domUtil.isDescribedElement(e, 'select') &&
|
|
686
|
+
e.options &&
|
|
687
|
+
e.options.length
|
|
688
|
+
) {
|
|
575
689
|
this.handleSelectInputChanged(e);
|
|
576
|
-
} else if (
|
|
690
|
+
} else if (
|
|
691
|
+
domUtil.isDescribedElement(e, 'input') &&
|
|
692
|
+
!domUtil.isDescribedElement(e, 'input', [
|
|
693
|
+
'button',
|
|
694
|
+
'submit',
|
|
695
|
+
'hidden',
|
|
696
|
+
'checkbox',
|
|
697
|
+
'radio',
|
|
698
|
+
])
|
|
699
|
+
) {
|
|
577
700
|
this.captureDomEvent('input', e, e.value);
|
|
578
701
|
}
|
|
579
702
|
}
|
|
@@ -582,7 +705,7 @@ Instrumenter.prototype.handleBlur = function(evt) {
|
|
|
582
705
|
}
|
|
583
706
|
};
|
|
584
707
|
|
|
585
|
-
Instrumenter.prototype.handleSelectInputChanged = function(elem) {
|
|
708
|
+
Instrumenter.prototype.handleSelectInputChanged = function (elem) {
|
|
586
709
|
if (elem.multiple) {
|
|
587
710
|
for (var i = 0; i < elem.options.length; i++) {
|
|
588
711
|
if (elem.options[i].selected) {
|
|
@@ -594,9 +717,17 @@ Instrumenter.prototype.handleSelectInputChanged = function(elem) {
|
|
|
594
717
|
}
|
|
595
718
|
};
|
|
596
719
|
|
|
597
|
-
Instrumenter.prototype.captureDomEvent = function(
|
|
720
|
+
Instrumenter.prototype.captureDomEvent = function (
|
|
721
|
+
subtype,
|
|
722
|
+
element,
|
|
723
|
+
value,
|
|
724
|
+
isChecked,
|
|
725
|
+
) {
|
|
598
726
|
if (value !== undefined) {
|
|
599
|
-
if (
|
|
727
|
+
if (
|
|
728
|
+
this.scrubTelemetryInputs ||
|
|
729
|
+
domUtil.getElementType(element) === 'password'
|
|
730
|
+
) {
|
|
600
731
|
value = '[scrubbed]';
|
|
601
732
|
} else {
|
|
602
733
|
var description = domUtil.describeElement(element);
|
|
@@ -609,66 +740,92 @@ Instrumenter.prototype.captureDomEvent = function(subtype, element, value, isChe
|
|
|
609
740
|
}
|
|
610
741
|
}
|
|
611
742
|
}
|
|
612
|
-
var elementString = domUtil.elementArrayToString(
|
|
743
|
+
var elementString = domUtil.elementArrayToString(
|
|
744
|
+
domUtil.treeToArray(element),
|
|
745
|
+
);
|
|
613
746
|
this.telemeter.captureDom(subtype, elementString, value, isChecked);
|
|
614
747
|
};
|
|
615
748
|
|
|
616
|
-
Instrumenter.prototype.deinstrumentNavigation = function() {
|
|
749
|
+
Instrumenter.prototype.deinstrumentNavigation = function () {
|
|
617
750
|
var chrome = this._window.chrome;
|
|
618
751
|
var chromePackagedApp = chrome && chrome.app && chrome.app.runtime;
|
|
619
752
|
// See https://github.com/angular/angular.js/pull/13945/files
|
|
620
|
-
var hasPushState =
|
|
753
|
+
var hasPushState =
|
|
754
|
+
!chromePackagedApp &&
|
|
755
|
+
this._window.history &&
|
|
756
|
+
this._window.history.pushState;
|
|
621
757
|
if (!hasPushState) {
|
|
622
758
|
return;
|
|
623
759
|
}
|
|
624
760
|
restore(this.replacements, 'navigation');
|
|
625
761
|
};
|
|
626
762
|
|
|
627
|
-
Instrumenter.prototype.instrumentNavigation = function() {
|
|
763
|
+
Instrumenter.prototype.instrumentNavigation = function () {
|
|
628
764
|
var chrome = this._window.chrome;
|
|
629
765
|
var chromePackagedApp = chrome && chrome.app && chrome.app.runtime;
|
|
630
766
|
// See https://github.com/angular/angular.js/pull/13945/files
|
|
631
|
-
var hasPushState =
|
|
767
|
+
var hasPushState =
|
|
768
|
+
!chromePackagedApp &&
|
|
769
|
+
this._window.history &&
|
|
770
|
+
this._window.history.pushState;
|
|
632
771
|
if (!hasPushState) {
|
|
633
772
|
return;
|
|
634
773
|
}
|
|
635
774
|
var self = this;
|
|
636
|
-
replace(
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
775
|
+
replace(
|
|
776
|
+
this._window,
|
|
777
|
+
'onpopstate',
|
|
778
|
+
function (orig) {
|
|
779
|
+
return function () {
|
|
780
|
+
var current = self._location.href;
|
|
781
|
+
self.handleUrlChange(self._lastHref, current);
|
|
782
|
+
if (orig) {
|
|
783
|
+
orig.apply(this, arguments);
|
|
784
|
+
}
|
|
785
|
+
};
|
|
786
|
+
},
|
|
787
|
+
this.replacements,
|
|
788
|
+
'navigation',
|
|
789
|
+
);
|
|
790
|
+
|
|
791
|
+
replace(
|
|
792
|
+
this._window.history,
|
|
793
|
+
'pushState',
|
|
794
|
+
function (orig) {
|
|
795
|
+
return function () {
|
|
796
|
+
var url = arguments.length > 2 ? arguments[2] : undefined;
|
|
797
|
+
if (url) {
|
|
798
|
+
self.handleUrlChange(self._lastHref, url + '');
|
|
799
|
+
}
|
|
800
|
+
return orig.apply(this, arguments);
|
|
801
|
+
};
|
|
802
|
+
},
|
|
803
|
+
this.replacements,
|
|
804
|
+
'navigation',
|
|
805
|
+
);
|
|
655
806
|
};
|
|
656
807
|
|
|
657
|
-
Instrumenter.prototype.handleUrlChange = function(from, to) {
|
|
808
|
+
Instrumenter.prototype.handleUrlChange = function (from, to) {
|
|
658
809
|
var parsedHref = urlparser.parse(this._location.href);
|
|
659
810
|
var parsedTo = urlparser.parse(to);
|
|
660
811
|
var parsedFrom = urlparser.parse(from);
|
|
661
812
|
this._lastHref = to;
|
|
662
|
-
if (
|
|
813
|
+
if (
|
|
814
|
+
parsedHref.protocol === parsedTo.protocol &&
|
|
815
|
+
parsedHref.host === parsedTo.host
|
|
816
|
+
) {
|
|
663
817
|
to = parsedTo.path + (parsedTo.hash || '');
|
|
664
818
|
}
|
|
665
|
-
if (
|
|
819
|
+
if (
|
|
820
|
+
parsedHref.protocol === parsedFrom.protocol &&
|
|
821
|
+
parsedHref.host === parsedFrom.host
|
|
822
|
+
) {
|
|
666
823
|
from = parsedFrom.path + (parsedFrom.hash || '');
|
|
667
824
|
}
|
|
668
825
|
this.telemeter.captureNavigation(from, to);
|
|
669
826
|
};
|
|
670
827
|
|
|
671
|
-
Instrumenter.prototype.deinstrumentConnectivity = function() {
|
|
828
|
+
Instrumenter.prototype.deinstrumentConnectivity = function () {
|
|
672
829
|
if (!('addEventListener' in this._window || 'body' in this._document)) {
|
|
673
830
|
return;
|
|
674
831
|
}
|
|
@@ -679,90 +836,148 @@ Instrumenter.prototype.deinstrumentConnectivity = function() {
|
|
|
679
836
|
}
|
|
680
837
|
};
|
|
681
838
|
|
|
682
|
-
Instrumenter.prototype.instrumentConnectivity = function() {
|
|
839
|
+
Instrumenter.prototype.instrumentConnectivity = function () {
|
|
683
840
|
if (!('addEventListener' in this._window || 'body' in this._document)) {
|
|
684
841
|
return;
|
|
685
842
|
}
|
|
686
843
|
if (this._window.addEventListener) {
|
|
687
|
-
this.addListener(
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
844
|
+
this.addListener(
|
|
845
|
+
'connectivity',
|
|
846
|
+
this._window,
|
|
847
|
+
'online',
|
|
848
|
+
undefined,
|
|
849
|
+
function () {
|
|
850
|
+
this.telemeter.captureConnectivityChange('online');
|
|
851
|
+
}.bind(this),
|
|
852
|
+
true,
|
|
853
|
+
);
|
|
854
|
+
this.addListener(
|
|
855
|
+
'connectivity',
|
|
856
|
+
this._window,
|
|
857
|
+
'offline',
|
|
858
|
+
undefined,
|
|
859
|
+
function () {
|
|
860
|
+
this.telemeter.captureConnectivityChange('offline');
|
|
861
|
+
}.bind(this),
|
|
862
|
+
true,
|
|
863
|
+
);
|
|
693
864
|
} else {
|
|
694
865
|
var self = this;
|
|
695
|
-
replace(
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
866
|
+
replace(
|
|
867
|
+
this._document.body,
|
|
868
|
+
'ononline',
|
|
869
|
+
function (orig) {
|
|
870
|
+
return function () {
|
|
871
|
+
self.telemeter.captureConnectivityChange('online');
|
|
872
|
+
if (orig) {
|
|
873
|
+
orig.apply(this, arguments);
|
|
874
|
+
}
|
|
875
|
+
};
|
|
876
|
+
},
|
|
877
|
+
this.replacements,
|
|
878
|
+
'connectivity',
|
|
879
|
+
);
|
|
880
|
+
replace(
|
|
881
|
+
this._document.body,
|
|
882
|
+
'onoffline',
|
|
883
|
+
function (orig) {
|
|
884
|
+
return function () {
|
|
885
|
+
self.telemeter.captureConnectivityChange('offline');
|
|
886
|
+
if (orig) {
|
|
887
|
+
orig.apply(this, arguments);
|
|
888
|
+
}
|
|
889
|
+
};
|
|
890
|
+
},
|
|
891
|
+
this.replacements,
|
|
892
|
+
'connectivity',
|
|
893
|
+
);
|
|
711
894
|
}
|
|
712
895
|
};
|
|
713
896
|
|
|
714
|
-
Instrumenter.prototype.handleCspEvent = function(cspEvent) {
|
|
715
|
-
var message =
|
|
716
|
-
'
|
|
717
|
-
'
|
|
718
|
-
|
|
897
|
+
Instrumenter.prototype.handleCspEvent = function (cspEvent) {
|
|
898
|
+
var message =
|
|
899
|
+
'Security Policy Violation: ' +
|
|
900
|
+
'blockedURI: ' +
|
|
901
|
+
cspEvent.blockedURI +
|
|
902
|
+
', ' +
|
|
903
|
+
'violatedDirective: ' +
|
|
904
|
+
cspEvent.violatedDirective +
|
|
905
|
+
', ' +
|
|
906
|
+
'effectiveDirective: ' +
|
|
907
|
+
cspEvent.effectiveDirective +
|
|
908
|
+
', ';
|
|
719
909
|
|
|
720
910
|
if (cspEvent.sourceFile) {
|
|
721
|
-
message +=
|
|
722
|
-
'
|
|
723
|
-
|
|
911
|
+
message +=
|
|
912
|
+
'location: ' +
|
|
913
|
+
cspEvent.sourceFile +
|
|
914
|
+
', ' +
|
|
915
|
+
'line: ' +
|
|
916
|
+
cspEvent.lineNumber +
|
|
917
|
+
', ' +
|
|
918
|
+
'col: ' +
|
|
919
|
+
cspEvent.columnNumber +
|
|
920
|
+
', ';
|
|
724
921
|
}
|
|
725
922
|
|
|
726
923
|
message += 'originalPolicy: ' + cspEvent.originalPolicy;
|
|
727
924
|
|
|
728
925
|
this.telemeter.captureLog(message, 'error');
|
|
729
926
|
this.handleCspError(message);
|
|
730
|
-
}
|
|
927
|
+
};
|
|
731
928
|
|
|
732
|
-
Instrumenter.prototype.handleCspError = function(message) {
|
|
929
|
+
Instrumenter.prototype.handleCspError = function (message) {
|
|
733
930
|
if (this.autoInstrument.errorOnContentSecurityPolicy) {
|
|
734
931
|
this.rollbar.error(message);
|
|
735
932
|
}
|
|
736
|
-
}
|
|
933
|
+
};
|
|
737
934
|
|
|
738
|
-
Instrumenter.prototype.deinstrumentContentSecurityPolicy = function() {
|
|
739
|
-
if (!('addEventListener' in this._document)) {
|
|
935
|
+
Instrumenter.prototype.deinstrumentContentSecurityPolicy = function () {
|
|
936
|
+
if (!('addEventListener' in this._document)) {
|
|
937
|
+
return;
|
|
938
|
+
}
|
|
740
939
|
|
|
741
940
|
this.removeListeners('contentsecuritypolicy');
|
|
742
941
|
};
|
|
743
942
|
|
|
744
|
-
Instrumenter.prototype.instrumentContentSecurityPolicy = function() {
|
|
745
|
-
if (!('addEventListener' in this._document)) {
|
|
943
|
+
Instrumenter.prototype.instrumentContentSecurityPolicy = function () {
|
|
944
|
+
if (!('addEventListener' in this._document)) {
|
|
945
|
+
return;
|
|
946
|
+
}
|
|
746
947
|
|
|
747
948
|
var cspHandler = this.handleCspEvent.bind(this);
|
|
748
|
-
this.addListener(
|
|
949
|
+
this.addListener(
|
|
950
|
+
'contentsecuritypolicy',
|
|
951
|
+
this._document,
|
|
952
|
+
'securitypolicyviolation',
|
|
953
|
+
null,
|
|
954
|
+
cspHandler,
|
|
955
|
+
false,
|
|
956
|
+
);
|
|
749
957
|
};
|
|
750
958
|
|
|
751
|
-
Instrumenter.prototype.addListener = function(
|
|
959
|
+
Instrumenter.prototype.addListener = function (
|
|
960
|
+
section,
|
|
961
|
+
obj,
|
|
962
|
+
type,
|
|
963
|
+
altType,
|
|
964
|
+
handler,
|
|
965
|
+
capture,
|
|
966
|
+
) {
|
|
752
967
|
if (obj.addEventListener) {
|
|
753
968
|
obj.addEventListener(type, handler, capture);
|
|
754
|
-
this.eventRemovers[section].push(function() {
|
|
969
|
+
this.eventRemovers[section].push(function () {
|
|
755
970
|
obj.removeEventListener(type, handler, capture);
|
|
756
971
|
});
|
|
757
972
|
} else if (altType) {
|
|
758
973
|
obj.attachEvent(altType, handler);
|
|
759
|
-
this.eventRemovers[section].push(function() {
|
|
974
|
+
this.eventRemovers[section].push(function () {
|
|
760
975
|
obj.detachEvent(altType, handler);
|
|
761
976
|
});
|
|
762
977
|
}
|
|
763
978
|
};
|
|
764
979
|
|
|
765
|
-
Instrumenter.prototype.removeListeners = function(section) {
|
|
980
|
+
Instrumenter.prototype.removeListeners = function (section) {
|
|
766
981
|
var r;
|
|
767
982
|
while (this.eventRemovers[section].length) {
|
|
768
983
|
r = this.eventRemovers[section].shift();
|
|
@@ -770,4 +985,8 @@ Instrumenter.prototype.removeListeners = function(section) {
|
|
|
770
985
|
}
|
|
771
986
|
};
|
|
772
987
|
|
|
988
|
+
function _isUrlObject(input) {
|
|
989
|
+
return typeof URL !== 'undefined' && input instanceof URL;
|
|
990
|
+
}
|
|
991
|
+
|
|
773
992
|
module.exports = Instrumenter;
|