Skip to content

Commit 3671931

Browse files
romainneutronbenvinegar
authored andcommitted
Record fetch requests in breadcrumb (#744)
1 parent 3ddc479 commit 3671931

File tree

4 files changed

+84
-2
lines changed

4 files changed

+84
-2
lines changed

package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"bundle-collapser": "^1.2.1",
2323
"chai": "2.3.0",
2424
"derequire": "2.0.3",
25+
"es6-promise": "^4.0.5",
2526
"grunt": "^0.4.5",
2627
"grunt-browserify": "^4.0.1",
2728
"grunt-cli": "^0.1.13",
@@ -43,7 +44,8 @@
4344
"proxyquireify": "^3.0.2",
4445
"sinon": "1.7.3",
4546
"through2": "^2.0.0",
46-
"typescript": "^1.8.10"
47+
"typescript": "^1.8.10",
48+
"whatwg-fetch": "^1.0.0"
4749
},
4850
"keywords": [
4951
"exceptions",

src/raven.js

+38-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ Raven.prototype = {
128128
xhr: true,
129129
console: true,
130130
dom: true,
131-
location: true
131+
location: true,
132132
};
133133

134134
var autoBreadcrumbs = globalOptions.autoBreadcrumbs;
@@ -971,6 +971,43 @@ Raven.prototype = {
971971
}, wrappedBuiltIns);
972972
}
973973

974+
if (autoBreadcrumbs.xhr && 'fetch' in _window) {
975+
fill(_window, 'fetch', function(origFetch) {
976+
return function (fn, t) { // preserve arity
977+
// Make a copy of the arguments to prevent deoptimization
978+
// https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments
979+
var args = new Array(arguments.length);
980+
for(var i = 0; i < args.length; ++i) {
981+
args[i] = arguments[i];
982+
}
983+
984+
var method = 'GET';
985+
986+
if (args[1] && args[1].method) {
987+
method = args[1].method;
988+
}
989+
990+
var fetchData = {
991+
method: method,
992+
url: args[0],
993+
status_code: null
994+
};
995+
996+
self.captureBreadcrumb({
997+
type: 'http',
998+
category: 'fetch',
999+
data: fetchData
1000+
});
1001+
1002+
return origFetch.apply(this, args).then(function (response) {
1003+
fetchData.status_code = response.status;
1004+
1005+
return response;
1006+
});
1007+
};
1008+
}, wrappedBuiltIns);
1009+
}
1010+
9741011
// Capture breadcrumbs from any click that is unhandled / bubbled up all the way
9751012
// to the document. Do this before we instrument addEventListener.
9761013
if (autoBreadcrumbs.dom && this._hasDocument) {

test/integration/frame.html

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
<head>
44
<meta charset="utf-8">
55
<title></title>
6+
<script src="../../node_modules/es6-promise/dist/es6-promise.auto.js"></script>
7+
<script src="../../node_modules/whatwg-fetch/fetch.js"></script>
68
<script>
79
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
810
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating

test/integration/test.js

+41
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,7 @@ describe('integration', function () {
405405
assert.equal(breadcrumbs.length, 1);
406406

407407
assert.equal(breadcrumbs[0].type, 'http');
408+
assert.equal(breadcrumbs[0].category, 'xhr');
408409
assert.equal(breadcrumbs[0].data.method, 'GET');
409410
// NOTE: not checking status code because we seem to get
410411
// statusCode 0/undefined from Phantom when fetching
@@ -441,6 +442,46 @@ describe('integration', function () {
441442
);
442443
});
443444

445+
it('should record a fetch request', function (done) {
446+
var iframe = this.iframe;
447+
448+
iframeExecute(iframe, done,
449+
function () {
450+
// some browsers trigger onpopstate for load / reset breadcrumb state
451+
Raven._breadcrumbs = [];
452+
453+
fetch('/test/integration/example.json').then(function () {
454+
setTimeout(done);
455+
}, function () {
456+
setTimeout(done);
457+
});
458+
},
459+
function () {
460+
var Raven = iframe.contentWindow.Raven,
461+
breadcrumbs = Raven._breadcrumbs;
462+
463+
if ('fetch' in window) {
464+
assert.equal(breadcrumbs.length, 1);
465+
466+
assert.equal(breadcrumbs[0].type, 'http');
467+
assert.equal(breadcrumbs[0].category, 'fetch');
468+
assert.equal(breadcrumbs[0].data.method, 'GET');
469+
} else {
470+
// otherwise we use a fetch polyfill based on xhr
471+
assert.equal(breadcrumbs.length, 2);
472+
473+
assert.equal(breadcrumbs[0].type, 'http');
474+
assert.equal(breadcrumbs[0].category, 'fetch');
475+
assert.equal(breadcrumbs[0].data.method, 'GET');
476+
477+
assert.equal(breadcrumbs[1].type, 'http');
478+
assert.equal(breadcrumbs[1].category, 'xhr');
479+
assert.equal(breadcrumbs[1].data.method, 'GET');
480+
}
481+
}
482+
);
483+
});
484+
444485
it('should record a mouse click on element WITH click handler present', function (done) {
445486
var iframe = this.iframe;
446487

0 commit comments

Comments
 (0)