Skip to content

Commit 848d5f0

Browse files
feat: Support URL object in fetch / XHR telemetry (#1118)
* feat: Support `URL` type in `XHR.open` telemetry * feat: Support `URL` object in `fetch` telemetry * test: XHR test * test: Fetch telemetry tests
1 parent 6f83da1 commit 848d5f0

File tree

2 files changed

+79
-3
lines changed

2 files changed

+79
-3
lines changed

src/browser/telemetry.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,9 @@ Instrumenter.prototype.instrumentNetwork = function() {
179179
var xhrp = this._window.XMLHttpRequest.prototype;
180180
replace(xhrp, 'open', function(orig) {
181181
return function(method, url) {
182-
if (_.isType(url, 'string')) {
182+
var isUrlObject = _isUrlObject(url)
183+
if (_.isType(url, 'string') || isUrlObject) {
184+
url = isUrlObject ? url.toString() : url;
183185
if (this.__rollbar_xhr) {
184186
this.__rollbar_xhr.method = method;
185187
this.__rollbar_xhr.url = url;
@@ -342,8 +344,9 @@ Instrumenter.prototype.instrumentNetwork = function() {
342344
var input = args[0];
343345
var method = 'GET';
344346
var url;
345-
if (_.isType(input, 'string')) {
346-
url = input;
347+
var isUrlObject = _isUrlObject(input)
348+
if (_.isType(input, 'string') || isUrlObject) {
349+
url = isUrlObject ? input.toString() : input;
347350
} else if (input) {
348351
url = input.url;
349352
if (input.method) {
@@ -770,4 +773,8 @@ Instrumenter.prototype.removeListeners = function(section) {
770773
}
771774
};
772775

776+
function _isUrlObject(input) {
777+
return typeof URL !== 'undefined' && input instanceof URL
778+
}
779+
773780
module.exports = Instrumenter;

test/browser.telemetry.test.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/* globals expect */
2+
/* globals describe */
3+
/* globals it */
4+
/* globals sinon */
5+
6+
var Instrumenter = require('../src/browser/telemetry');
7+
8+
describe('instrumentNetwork', function () {
9+
it('should capture XHR requests with string URL', function (done) {
10+
var callback = sinon.spy();
11+
var windowMock = {
12+
XMLHttpRequest: function () { }
13+
}
14+
15+
windowMock.XMLHttpRequest.prototype.open = function () { }
16+
windowMock.XMLHttpRequest.prototype.send = function () { }
17+
18+
var i = createInstrumenter(callback, windowMock)
19+
i.instrumentNetwork()
20+
21+
var xhr = new windowMock.XMLHttpRequest();
22+
xhr.open('GET', 'http://first.call')
23+
xhr.send()
24+
xhr.onreadystatechange()
25+
26+
expect(callback.callCount).to.eql(1)
27+
expect(callback.args[0][0].url).to.eql('http://first.call')
28+
29+
i.deinstrumentNetwork()
30+
i = createInstrumenter(callback, windowMock)
31+
i.instrumentNetwork()
32+
var xhr = new windowMock.XMLHttpRequest();
33+
xhr.open('GET', new URL('http://second.call'))
34+
xhr.send()
35+
xhr.onreadystatechange()
36+
expect(callback.callCount).to.eql(2)
37+
expect(callback.args[1][0].url).to.eql('http://second.call/')
38+
39+
done()
40+
})
41+
42+
it('should capture XHR requests with string URL', function (done) {
43+
var callback = sinon.spy();
44+
var windowMock = {
45+
fetch: function () { return Promise.resolve() }
46+
}
47+
48+
var i = createInstrumenter(callback, windowMock);
49+
i.instrumentNetwork()
50+
51+
windowMock.fetch('http://first.call')
52+
expect(callback.callCount).to.eql(1)
53+
expect(callback.args[0][0].url).to.eql('http://first.call')
54+
55+
i.deinstrumentNetwork()
56+
i = createInstrumenter(callback, windowMock)
57+
i.instrumentNetwork()
58+
59+
windowMock.fetch(new URL('http://second.call'))
60+
expect(callback.callCount).to.eql(2)
61+
expect(callback.args[1][0].url).to.eql('http://second.call/')
62+
63+
done()
64+
})
65+
})
66+
67+
function createInstrumenter(callback, windowMock) {
68+
return new Instrumenter({ scrubFields: [] }, { captureNetwork: callback }, { wrap: function () { }, client: { notifier: { diagnostic: {} } } }, windowMock);
69+
}

0 commit comments

Comments
 (0)