rollbar 2.26.3 → 2.26.5
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 +33 -11
- package/.lgtm.yml +7 -7
- package/.prettierignore +18 -0
- package/.vscode/settings.json +39 -0
- package/CHANGELOG.md +121 -35
- package/CLAUDE.md +28 -0
- package/Gruntfile.js +48 -38
- package/README.md +2 -4
- package/SECURITY.md +5 -0
- package/bower.json +1 -3
- package/defaults.js +17 -5
- package/dist/plugins/jquery.min.js +1 -1
- package/dist/rollbar.js +6107 -5461
- 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 +6107 -5466
- package/dist/rollbar.named-amd.js.map +1 -1
- package/dist/rollbar.named-amd.min.js +2 -1
- package/dist/rollbar.named-amd.min.js.map +1 -1
- package/dist/rollbar.noconflict.umd.js +6128 -5488
- package/dist/rollbar.noconflict.umd.js.map +1 -1
- package/dist/rollbar.noconflict.umd.min.js +2 -1
- package/dist/rollbar.noconflict.umd.min.js.map +1 -1
- package/dist/rollbar.snippet.js +1 -1
- package/dist/rollbar.umd.js +6107 -5467
- package/dist/rollbar.umd.js.map +1 -1
- package/dist/rollbar.umd.min.js +2 -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 +15 -15
- package/package.json +10 -12
- 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 +570 -358
- 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 +91 -32
- 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 +93 -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 +45 -38
- 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 +279 -222
- package/webpack.config.js +46 -42
- package/.gitmodules +0 -3
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,283 +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
|
-
}, this.replacements, 'network');
|
|
204
|
-
|
|
205
|
-
replace(xhrp, 'setRequestHeader', function(orig) {
|
|
206
|
-
return function(header, value) {
|
|
207
|
-
// If xhr.open is async, __rollbar_xhr may not be initialized yet.
|
|
208
|
-
if (!this.__rollbar_xhr) {
|
|
209
|
-
this.__rollbar_xhr = {};
|
|
210
|
-
}
|
|
211
|
-
if (_.isType(header, 'string') && _.isType(value, 'string')) {
|
|
212
|
-
if (self.autoInstrument.networkRequestHeaders) {
|
|
213
|
-
if (!this.__rollbar_xhr.request_headers) {
|
|
214
|
-
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
|
+
};
|
|
215
224
|
}
|
|
216
|
-
this.__rollbar_xhr.request_headers[header] = value;
|
|
217
225
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
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 = {};
|
|
221
241
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
replace(xhrp, 'send', function(orig) {
|
|
228
|
-
/* eslint-disable no-unused-vars */
|
|
229
|
-
return function(data) {
|
|
230
|
-
/* eslint-enable no-unused-vars */
|
|
231
|
-
var xhr = this;
|
|
232
|
-
|
|
233
|
-
function onreadystatechangeHandler() {
|
|
234
|
-
if (xhr.__rollbar_xhr) {
|
|
235
|
-
if (xhr.__rollbar_xhr.status_code === null) {
|
|
236
|
-
xhr.__rollbar_xhr.status_code = 0;
|
|
237
|
-
if (self.autoInstrument.networkRequestBody) {
|
|
238
|
-
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 = {};
|
|
239
246
|
}
|
|
240
|
-
|
|
247
|
+
this.__rollbar_xhr.request_headers[header] = value;
|
|
241
248
|
}
|
|
242
|
-
if
|
|
243
|
-
|
|
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;
|
|
244
252
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
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);
|
|
265
314
|
}
|
|
266
315
|
}
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
headers[header] = xhr.getResponseHeader(header);
|
|
271
|
-
}
|
|
316
|
+
} catch (e) {
|
|
317
|
+
/* we ignore the errors here that could come from different
|
|
318
|
+
* browser issues with the xhr methods */
|
|
272
319
|
}
|
|
273
|
-
} catch (e) {
|
|
274
|
-
/* we ignore the errors here that could come from different
|
|
275
|
-
* browser issues with the xhr methods */
|
|
276
320
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
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
|
+
}
|
|
284
328
|
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
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;
|
|
294
345
|
}
|
|
295
346
|
}
|
|
296
|
-
if (
|
|
297
|
-
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 */
|
|
298
359
|
}
|
|
299
|
-
}
|
|
300
|
-
if (response) {
|
|
301
|
-
xhr.__rollbar_xhr.response = response;
|
|
302
|
-
}
|
|
303
|
-
try {
|
|
304
|
-
var code = xhr.status;
|
|
305
|
-
code = code === 1223 ? 204 : code;
|
|
306
|
-
xhr.__rollbar_xhr.status_code = code;
|
|
307
|
-
xhr.__rollbar_event.level = self.telemeter.levelFromStatus(code);
|
|
308
|
-
self.errorOnHttpStatus(xhr.__rollbar_xhr);
|
|
309
|
-
} catch (e) {
|
|
310
|
-
/* ignore possible exception from xhr.status */
|
|
311
360
|
}
|
|
312
361
|
}
|
|
313
362
|
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
wrapProp('onload', xhr);
|
|
317
|
-
wrapProp('onerror', xhr);
|
|
318
|
-
wrapProp('onprogress', xhr);
|
|
319
363
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
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
|
+
);
|
|
333
391
|
}
|
|
334
392
|
|
|
335
393
|
if ('fetch' in this._window) {
|
|
336
|
-
replace(
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
var url;
|
|
347
|
-
var isUrlObject = _isUrlObject(input)
|
|
348
|
-
if (_.isType(input, 'string') || isUrlObject) {
|
|
349
|
-
url = isUrlObject ? input.toString() : input;
|
|
350
|
-
} else if (input) {
|
|
351
|
-
url = input.url;
|
|
352
|
-
if (input.method) {
|
|
353
|
-
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];
|
|
354
404
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
if (args[1] && args[1].headers) {
|
|
367
|
-
// Argument may be a Headers object, or plain object. Ensure here that
|
|
368
|
-
// we are working with a Headers object with case-insensitive keys.
|
|
369
|
-
var reqHeaders = headers(args[1].headers);
|
|
370
|
-
|
|
371
|
-
metadata.request_content_type = reqHeaders.get('Content-Type');
|
|
372
|
-
|
|
373
|
-
if (self.autoInstrument.networkRequestHeaders) {
|
|
374
|
-
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
|
+
}
|
|
375
416
|
}
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
if (self.autoInstrument.networkRequestBody) {
|
|
379
|
-
if (args[1] && args[1].body) {
|
|
380
|
-
metadata.request = args[1].body;
|
|
381
|
-
} else if (args[0] && !_.isType(args[0], 'string') && args[0].body) {
|
|
382
|
-
metadata.request = args[0].body;
|
|
417
|
+
if (args[1] && args[1].method) {
|
|
418
|
+
method = args[1].method;
|
|
383
419
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
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
|
+
}
|
|
399
440
|
}
|
|
400
|
-
|
|
401
|
-
if (self.autoInstrument.
|
|
402
|
-
if (
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
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;
|
|
406
451
|
}
|
|
407
452
|
}
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
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
|
|
422
478
|
}
|
|
423
479
|
}
|
|
424
|
-
if (headers) {
|
|
425
|
-
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
|
+
}
|
|
426
502
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
|
|
503
|
+
self.errorOnHttpStatus(metadata);
|
|
504
|
+
return resp;
|
|
505
|
+
});
|
|
506
|
+
};
|
|
507
|
+
},
|
|
508
|
+
this.replacements,
|
|
509
|
+
'network',
|
|
510
|
+
);
|
|
433
511
|
}
|
|
434
512
|
};
|
|
435
513
|
|
|
436
|
-
Instrumenter.prototype.captureNetwork = function(
|
|
437
|
-
|
|
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
|
+
) {
|
|
438
523
|
metadata.request = this.scrubJson(metadata.request);
|
|
439
524
|
}
|
|
440
525
|
return this.telemeter.captureNetwork(metadata, subtype, rollbarUUID);
|
|
441
526
|
};
|
|
442
527
|
|
|
443
|
-
Instrumenter.prototype.isJsonContentType = function(contentType) {
|
|
444
|
-
return
|
|
445
|
-
|
|
528
|
+
Instrumenter.prototype.isJsonContentType = function (contentType) {
|
|
529
|
+
return contentType &&
|
|
530
|
+
_.isType(contentType, 'string') &&
|
|
531
|
+
contentType.toLowerCase().includes('json')
|
|
532
|
+
? true
|
|
533
|
+
: false;
|
|
534
|
+
};
|
|
446
535
|
|
|
447
|
-
Instrumenter.prototype.scrubJson = function(json) {
|
|
536
|
+
Instrumenter.prototype.scrubJson = function (json) {
|
|
448
537
|
return JSON.stringify(scrub(JSON.parse(json), this.options.scrubFields));
|
|
449
|
-
}
|
|
538
|
+
};
|
|
450
539
|
|
|
451
|
-
Instrumenter.prototype.fetchHeaders = function(inHeaders, headersConfig) {
|
|
540
|
+
Instrumenter.prototype.fetchHeaders = function (inHeaders, headersConfig) {
|
|
452
541
|
var outHeaders = {};
|
|
453
542
|
try {
|
|
454
543
|
var i;
|
|
455
544
|
if (headersConfig === true) {
|
|
456
|
-
if (typeof inHeaders.entries === 'function') {
|
|
545
|
+
if (typeof inHeaders.entries === 'function') {
|
|
546
|
+
// Headers.entries() is not implemented in IE
|
|
457
547
|
var allHeaders = inHeaders.entries();
|
|
458
548
|
var currentHeader = allHeaders.next();
|
|
459
549
|
while (!currentHeader.done) {
|
|
@@ -462,7 +552,7 @@ Instrumenter.prototype.fetchHeaders = function(inHeaders, headersConfig) {
|
|
|
462
552
|
}
|
|
463
553
|
}
|
|
464
554
|
} else {
|
|
465
|
-
for (i=0; i < headersConfig.length; i++) {
|
|
555
|
+
for (i = 0; i < headersConfig.length; i++) {
|
|
466
556
|
var header = headersConfig[i];
|
|
467
557
|
outHeaders[header] = inHeaders.get(header);
|
|
468
558
|
}
|
|
@@ -471,27 +561,31 @@ Instrumenter.prototype.fetchHeaders = function(inHeaders, headersConfig) {
|
|
|
471
561
|
/* ignore probable IE errors */
|
|
472
562
|
}
|
|
473
563
|
return outHeaders;
|
|
474
|
-
}
|
|
564
|
+
};
|
|
475
565
|
|
|
476
|
-
Instrumenter.prototype.trackHttpErrors = function() {
|
|
477
|
-
return
|
|
566
|
+
Instrumenter.prototype.trackHttpErrors = function () {
|
|
567
|
+
return (
|
|
568
|
+
this.autoInstrument.networkErrorOnHttp5xx ||
|
|
478
569
|
this.autoInstrument.networkErrorOnHttp4xx ||
|
|
479
|
-
this.autoInstrument.networkErrorOnHttp0
|
|
480
|
-
|
|
570
|
+
this.autoInstrument.networkErrorOnHttp0
|
|
571
|
+
);
|
|
572
|
+
};
|
|
481
573
|
|
|
482
|
-
Instrumenter.prototype.errorOnHttpStatus = function(metadata) {
|
|
574
|
+
Instrumenter.prototype.errorOnHttpStatus = function (metadata) {
|
|
483
575
|
var status = metadata.status_code;
|
|
484
576
|
|
|
485
|
-
if (
|
|
577
|
+
if (
|
|
578
|
+
(status >= 500 && this.autoInstrument.networkErrorOnHttp5xx) ||
|
|
486
579
|
(status >= 400 && this.autoInstrument.networkErrorOnHttp4xx) ||
|
|
487
|
-
(status === 0 && this.autoInstrument.networkErrorOnHttp0)
|
|
580
|
+
(status === 0 && this.autoInstrument.networkErrorOnHttp0)
|
|
581
|
+
) {
|
|
488
582
|
var error = new Error('HTTP request failed with Status ' + status);
|
|
489
583
|
error.stack = metadata.stack;
|
|
490
584
|
this.rollbar.error(error, { skipFrames: 1 });
|
|
491
585
|
}
|
|
492
|
-
}
|
|
586
|
+
};
|
|
493
587
|
|
|
494
|
-
Instrumenter.prototype.deinstrumentConsole = function() {
|
|
588
|
+
Instrumenter.prototype.deinstrumentConsole = function () {
|
|
495
589
|
if (!('console' in this._window && this._window.console.log)) {
|
|
496
590
|
return;
|
|
497
591
|
}
|
|
@@ -502,7 +596,7 @@ Instrumenter.prototype.deinstrumentConsole = function() {
|
|
|
502
596
|
}
|
|
503
597
|
};
|
|
504
598
|
|
|
505
|
-
Instrumenter.prototype.instrumentConsole = function() {
|
|
599
|
+
Instrumenter.prototype.instrumentConsole = function () {
|
|
506
600
|
if (!('console' in this._window && this._window.console.log)) {
|
|
507
601
|
return;
|
|
508
602
|
}
|
|
@@ -516,7 +610,7 @@ Instrumenter.prototype.instrumentConsole = function() {
|
|
|
516
610
|
var orig = c[method];
|
|
517
611
|
var origConsole = c;
|
|
518
612
|
var level = method === 'warn' ? 'warning' : method;
|
|
519
|
-
c[method] = function() {
|
|
613
|
+
c[method] = function () {
|
|
520
614
|
var args = Array.prototype.slice.call(arguments);
|
|
521
615
|
var message = _.formatArgsAsString(args);
|
|
522
616
|
self.telemeter.captureLog(message, level);
|
|
@@ -526,9 +620,9 @@ Instrumenter.prototype.instrumentConsole = function() {
|
|
|
526
620
|
};
|
|
527
621
|
self.replacements['log'].push([method, orig]);
|
|
528
622
|
}
|
|
529
|
-
var methods = ['debug','info','warn','error','log'];
|
|
623
|
+
var methods = ['debug', 'info', 'warn', 'error', 'log'];
|
|
530
624
|
try {
|
|
531
|
-
for (var i=0, len=methods.length; i < len; i++) {
|
|
625
|
+
for (var i = 0, len = methods.length; i < len; i++) {
|
|
532
626
|
wrapConsole(methods[i]);
|
|
533
627
|
}
|
|
534
628
|
} catch (e) {
|
|
@@ -536,30 +630,43 @@ Instrumenter.prototype.instrumentConsole = function() {
|
|
|
536
630
|
}
|
|
537
631
|
};
|
|
538
632
|
|
|
539
|
-
Instrumenter.prototype.deinstrumentDom = function() {
|
|
633
|
+
Instrumenter.prototype.deinstrumentDom = function () {
|
|
540
634
|
if (!('addEventListener' in this._window || 'attachEvent' in this._window)) {
|
|
541
635
|
return;
|
|
542
636
|
}
|
|
543
637
|
this.removeListeners('dom');
|
|
544
638
|
};
|
|
545
639
|
|
|
546
|
-
Instrumenter.prototype.instrumentDom = function() {
|
|
640
|
+
Instrumenter.prototype.instrumentDom = function () {
|
|
547
641
|
if (!('addEventListener' in this._window || 'attachEvent' in this._window)) {
|
|
548
642
|
return;
|
|
549
643
|
}
|
|
550
644
|
var clickHandler = this.handleClick.bind(this);
|
|
551
645
|
var blurHandler = this.handleBlur.bind(this);
|
|
552
646
|
this.addListener('dom', this._window, 'click', 'onclick', clickHandler, true);
|
|
553
|
-
this.addListener(
|
|
647
|
+
this.addListener(
|
|
648
|
+
'dom',
|
|
649
|
+
this._window,
|
|
650
|
+
'blur',
|
|
651
|
+
'onfocusout',
|
|
652
|
+
blurHandler,
|
|
653
|
+
true,
|
|
654
|
+
);
|
|
554
655
|
};
|
|
555
656
|
|
|
556
|
-
Instrumenter.prototype.handleClick = function(evt) {
|
|
657
|
+
Instrumenter.prototype.handleClick = function (evt) {
|
|
557
658
|
try {
|
|
558
659
|
var e = domUtil.getElementFromEvent(evt, this._document);
|
|
559
660
|
var hasTag = e && e.tagName;
|
|
560
|
-
var anchorOrButton =
|
|
561
|
-
|
|
562
|
-
|
|
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);
|
|
563
670
|
} else if (domUtil.isDescribedElement(e, 'input', ['checkbox', 'radio'])) {
|
|
564
671
|
this.captureDomEvent('input', e, e.value, e.checked);
|
|
565
672
|
}
|
|
@@ -568,15 +675,28 @@ Instrumenter.prototype.handleClick = function(evt) {
|
|
|
568
675
|
}
|
|
569
676
|
};
|
|
570
677
|
|
|
571
|
-
Instrumenter.prototype.handleBlur = function(evt) {
|
|
678
|
+
Instrumenter.prototype.handleBlur = function (evt) {
|
|
572
679
|
try {
|
|
573
680
|
var e = domUtil.getElementFromEvent(evt, this._document);
|
|
574
681
|
if (e && e.tagName) {
|
|
575
682
|
if (domUtil.isDescribedElement(e, 'textarea')) {
|
|
576
683
|
this.captureDomEvent('input', e, e.value);
|
|
577
|
-
} else if (
|
|
684
|
+
} else if (
|
|
685
|
+
domUtil.isDescribedElement(e, 'select') &&
|
|
686
|
+
e.options &&
|
|
687
|
+
e.options.length
|
|
688
|
+
) {
|
|
578
689
|
this.handleSelectInputChanged(e);
|
|
579
|
-
} 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
|
+
) {
|
|
580
700
|
this.captureDomEvent('input', e, e.value);
|
|
581
701
|
}
|
|
582
702
|
}
|
|
@@ -585,7 +705,7 @@ Instrumenter.prototype.handleBlur = function(evt) {
|
|
|
585
705
|
}
|
|
586
706
|
};
|
|
587
707
|
|
|
588
|
-
Instrumenter.prototype.handleSelectInputChanged = function(elem) {
|
|
708
|
+
Instrumenter.prototype.handleSelectInputChanged = function (elem) {
|
|
589
709
|
if (elem.multiple) {
|
|
590
710
|
for (var i = 0; i < elem.options.length; i++) {
|
|
591
711
|
if (elem.options[i].selected) {
|
|
@@ -597,9 +717,17 @@ Instrumenter.prototype.handleSelectInputChanged = function(elem) {
|
|
|
597
717
|
}
|
|
598
718
|
};
|
|
599
719
|
|
|
600
|
-
Instrumenter.prototype.captureDomEvent = function(
|
|
720
|
+
Instrumenter.prototype.captureDomEvent = function (
|
|
721
|
+
subtype,
|
|
722
|
+
element,
|
|
723
|
+
value,
|
|
724
|
+
isChecked,
|
|
725
|
+
) {
|
|
601
726
|
if (value !== undefined) {
|
|
602
|
-
if (
|
|
727
|
+
if (
|
|
728
|
+
this.scrubTelemetryInputs ||
|
|
729
|
+
domUtil.getElementType(element) === 'password'
|
|
730
|
+
) {
|
|
603
731
|
value = '[scrubbed]';
|
|
604
732
|
} else {
|
|
605
733
|
var description = domUtil.describeElement(element);
|
|
@@ -612,66 +740,92 @@ Instrumenter.prototype.captureDomEvent = function(subtype, element, value, isChe
|
|
|
612
740
|
}
|
|
613
741
|
}
|
|
614
742
|
}
|
|
615
|
-
var elementString = domUtil.elementArrayToString(
|
|
743
|
+
var elementString = domUtil.elementArrayToString(
|
|
744
|
+
domUtil.treeToArray(element),
|
|
745
|
+
);
|
|
616
746
|
this.telemeter.captureDom(subtype, elementString, value, isChecked);
|
|
617
747
|
};
|
|
618
748
|
|
|
619
|
-
Instrumenter.prototype.deinstrumentNavigation = function() {
|
|
749
|
+
Instrumenter.prototype.deinstrumentNavigation = function () {
|
|
620
750
|
var chrome = this._window.chrome;
|
|
621
751
|
var chromePackagedApp = chrome && chrome.app && chrome.app.runtime;
|
|
622
752
|
// See https://github.com/angular/angular.js/pull/13945/files
|
|
623
|
-
var hasPushState =
|
|
753
|
+
var hasPushState =
|
|
754
|
+
!chromePackagedApp &&
|
|
755
|
+
this._window.history &&
|
|
756
|
+
this._window.history.pushState;
|
|
624
757
|
if (!hasPushState) {
|
|
625
758
|
return;
|
|
626
759
|
}
|
|
627
760
|
restore(this.replacements, 'navigation');
|
|
628
761
|
};
|
|
629
762
|
|
|
630
|
-
Instrumenter.prototype.instrumentNavigation = function() {
|
|
763
|
+
Instrumenter.prototype.instrumentNavigation = function () {
|
|
631
764
|
var chrome = this._window.chrome;
|
|
632
765
|
var chromePackagedApp = chrome && chrome.app && chrome.app.runtime;
|
|
633
766
|
// See https://github.com/angular/angular.js/pull/13945/files
|
|
634
|
-
var hasPushState =
|
|
767
|
+
var hasPushState =
|
|
768
|
+
!chromePackagedApp &&
|
|
769
|
+
this._window.history &&
|
|
770
|
+
this._window.history.pushState;
|
|
635
771
|
if (!hasPushState) {
|
|
636
772
|
return;
|
|
637
773
|
}
|
|
638
774
|
var self = this;
|
|
639
|
-
replace(
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
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
|
+
);
|
|
658
806
|
};
|
|
659
807
|
|
|
660
|
-
Instrumenter.prototype.handleUrlChange = function(from, to) {
|
|
808
|
+
Instrumenter.prototype.handleUrlChange = function (from, to) {
|
|
661
809
|
var parsedHref = urlparser.parse(this._location.href);
|
|
662
810
|
var parsedTo = urlparser.parse(to);
|
|
663
811
|
var parsedFrom = urlparser.parse(from);
|
|
664
812
|
this._lastHref = to;
|
|
665
|
-
if (
|
|
813
|
+
if (
|
|
814
|
+
parsedHref.protocol === parsedTo.protocol &&
|
|
815
|
+
parsedHref.host === parsedTo.host
|
|
816
|
+
) {
|
|
666
817
|
to = parsedTo.path + (parsedTo.hash || '');
|
|
667
818
|
}
|
|
668
|
-
if (
|
|
819
|
+
if (
|
|
820
|
+
parsedHref.protocol === parsedFrom.protocol &&
|
|
821
|
+
parsedHref.host === parsedFrom.host
|
|
822
|
+
) {
|
|
669
823
|
from = parsedFrom.path + (parsedFrom.hash || '');
|
|
670
824
|
}
|
|
671
825
|
this.telemeter.captureNavigation(from, to);
|
|
672
826
|
};
|
|
673
827
|
|
|
674
|
-
Instrumenter.prototype.deinstrumentConnectivity = function() {
|
|
828
|
+
Instrumenter.prototype.deinstrumentConnectivity = function () {
|
|
675
829
|
if (!('addEventListener' in this._window || 'body' in this._document)) {
|
|
676
830
|
return;
|
|
677
831
|
}
|
|
@@ -682,90 +836,148 @@ Instrumenter.prototype.deinstrumentConnectivity = function() {
|
|
|
682
836
|
}
|
|
683
837
|
};
|
|
684
838
|
|
|
685
|
-
Instrumenter.prototype.instrumentConnectivity = function() {
|
|
839
|
+
Instrumenter.prototype.instrumentConnectivity = function () {
|
|
686
840
|
if (!('addEventListener' in this._window || 'body' in this._document)) {
|
|
687
841
|
return;
|
|
688
842
|
}
|
|
689
843
|
if (this._window.addEventListener) {
|
|
690
|
-
this.addListener(
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
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
|
+
);
|
|
696
864
|
} else {
|
|
697
865
|
var self = this;
|
|
698
|
-
replace(
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
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
|
+
);
|
|
714
894
|
}
|
|
715
895
|
};
|
|
716
896
|
|
|
717
|
-
Instrumenter.prototype.handleCspEvent = function(cspEvent) {
|
|
718
|
-
var message =
|
|
719
|
-
'
|
|
720
|
-
'
|
|
721
|
-
|
|
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
|
+
', ';
|
|
722
909
|
|
|
723
910
|
if (cspEvent.sourceFile) {
|
|
724
|
-
message +=
|
|
725
|
-
'
|
|
726
|
-
|
|
911
|
+
message +=
|
|
912
|
+
'location: ' +
|
|
913
|
+
cspEvent.sourceFile +
|
|
914
|
+
', ' +
|
|
915
|
+
'line: ' +
|
|
916
|
+
cspEvent.lineNumber +
|
|
917
|
+
', ' +
|
|
918
|
+
'col: ' +
|
|
919
|
+
cspEvent.columnNumber +
|
|
920
|
+
', ';
|
|
727
921
|
}
|
|
728
922
|
|
|
729
923
|
message += 'originalPolicy: ' + cspEvent.originalPolicy;
|
|
730
924
|
|
|
731
925
|
this.telemeter.captureLog(message, 'error');
|
|
732
926
|
this.handleCspError(message);
|
|
733
|
-
}
|
|
927
|
+
};
|
|
734
928
|
|
|
735
|
-
Instrumenter.prototype.handleCspError = function(message) {
|
|
929
|
+
Instrumenter.prototype.handleCspError = function (message) {
|
|
736
930
|
if (this.autoInstrument.errorOnContentSecurityPolicy) {
|
|
737
931
|
this.rollbar.error(message);
|
|
738
932
|
}
|
|
739
|
-
}
|
|
933
|
+
};
|
|
740
934
|
|
|
741
|
-
Instrumenter.prototype.deinstrumentContentSecurityPolicy = function() {
|
|
742
|
-
if (!('addEventListener' in this._document)) {
|
|
935
|
+
Instrumenter.prototype.deinstrumentContentSecurityPolicy = function () {
|
|
936
|
+
if (!('addEventListener' in this._document)) {
|
|
937
|
+
return;
|
|
938
|
+
}
|
|
743
939
|
|
|
744
940
|
this.removeListeners('contentsecuritypolicy');
|
|
745
941
|
};
|
|
746
942
|
|
|
747
|
-
Instrumenter.prototype.instrumentContentSecurityPolicy = function() {
|
|
748
|
-
if (!('addEventListener' in this._document)) {
|
|
943
|
+
Instrumenter.prototype.instrumentContentSecurityPolicy = function () {
|
|
944
|
+
if (!('addEventListener' in this._document)) {
|
|
945
|
+
return;
|
|
946
|
+
}
|
|
749
947
|
|
|
750
948
|
var cspHandler = this.handleCspEvent.bind(this);
|
|
751
|
-
this.addListener(
|
|
949
|
+
this.addListener(
|
|
950
|
+
'contentsecuritypolicy',
|
|
951
|
+
this._document,
|
|
952
|
+
'securitypolicyviolation',
|
|
953
|
+
null,
|
|
954
|
+
cspHandler,
|
|
955
|
+
false,
|
|
956
|
+
);
|
|
752
957
|
};
|
|
753
958
|
|
|
754
|
-
Instrumenter.prototype.addListener = function(
|
|
959
|
+
Instrumenter.prototype.addListener = function (
|
|
960
|
+
section,
|
|
961
|
+
obj,
|
|
962
|
+
type,
|
|
963
|
+
altType,
|
|
964
|
+
handler,
|
|
965
|
+
capture,
|
|
966
|
+
) {
|
|
755
967
|
if (obj.addEventListener) {
|
|
756
968
|
obj.addEventListener(type, handler, capture);
|
|
757
|
-
this.eventRemovers[section].push(function() {
|
|
969
|
+
this.eventRemovers[section].push(function () {
|
|
758
970
|
obj.removeEventListener(type, handler, capture);
|
|
759
971
|
});
|
|
760
972
|
} else if (altType) {
|
|
761
973
|
obj.attachEvent(altType, handler);
|
|
762
|
-
this.eventRemovers[section].push(function() {
|
|
974
|
+
this.eventRemovers[section].push(function () {
|
|
763
975
|
obj.detachEvent(altType, handler);
|
|
764
976
|
});
|
|
765
977
|
}
|
|
766
978
|
};
|
|
767
979
|
|
|
768
|
-
Instrumenter.prototype.removeListeners = function(section) {
|
|
980
|
+
Instrumenter.prototype.removeListeners = function (section) {
|
|
769
981
|
var r;
|
|
770
982
|
while (this.eventRemovers[section].length) {
|
|
771
983
|
r = this.eventRemovers[section].shift();
|
|
@@ -774,7 +986,7 @@ Instrumenter.prototype.removeListeners = function(section) {
|
|
|
774
986
|
};
|
|
775
987
|
|
|
776
988
|
function _isUrlObject(input) {
|
|
777
|
-
return typeof URL !== 'undefined' && input instanceof URL
|
|
989
|
+
return typeof URL !== 'undefined' && input instanceof URL;
|
|
778
990
|
}
|
|
779
991
|
|
|
780
992
|
module.exports = Instrumenter;
|