Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(Refactor) Minor improvements to NetworkTracking #434

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 80 additions & 74 deletions src/raygun.network-tracking.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ window.raygunNetworkTrackingFactory = function(window, Raygun) {
this.responseHandlers = [];
this.errorHandlers = [];

this.originalFetch = undefined;

this.wrapWithHandler = function(method) {
return function() {
try {
Expand Down Expand Up @@ -81,7 +83,7 @@ window.raygunNetworkTrackingFactory = function(window, Raygun) {
Raygun.Utilities.enhance(
this,
'send',
self.wrapWithHandler(function() {
function() {
var metadata = {
method: method,
requestURL: url,
Expand All @@ -93,12 +95,12 @@ window.raygunNetworkTrackingFactory = function(window, Raygun) {
}

self.executeHandlers(self.requestHandlers, metadata);
})
}
);

this.addEventListener(
'load',
self.wrapWithHandler(function() {
function() {
var body = 'N/A for non text responses';

if (this.responseType === '' || this.responseType === 'text') {
Expand All @@ -114,42 +116,42 @@ window.raygunNetworkTrackingFactory = function(window, Raygun) {
body: body,
duration: new Date().getTime() - initTime,
});
})
}
);

this.addEventListener(
'error',
self.wrapWithHandler(function() {
function() {
self.executeHandlers(self.errorHandlers, {
requestURL: url,
responseURL: this.responseURL,
duration: new Date().getTime() - initTime,
});
})
}
);
})
);
}

var disableFetchLogging = function() {};

/**
* Two window objects can be defined inside the installation code snippets that users inject into their page when using Raygun4JS.
* These are used to intercept the original fetch method before a reference to it can be made.
* Because if a stored reference to the fetch method is made, we cannot get the status code from that point onwards.
*
* Because if a stored reference to the fetch method is made, we cannot get the status code from that point onwards.
*
* window.__raygunOriginalFetch - the window.fetch method as of when the code snippet was executed
* window.__raygunFetchCallback - a callback which is executed when the code snippet fetch method is called
* window.__raygunFetchCallback - a callback which is executed when the code snippet fetch method is called
*/
var originalFetch = window.__raygunOriginalFetch || window.fetch;
self.originalFetch = window.__raygunOriginalFetch || window.fetch;

// If fetch has been polyfilled we don't want to hook into it as it then uses XMLHttpRequest
// This results in doubled up breadcrumbs
// Can't reliably detect when it has been polyfilled but no IE version supports fetch
// So if this is IE, don't hook into fetch
if (typeof originalFetch === 'function' && typeof originalFetch.polyfill === 'undefined' && !Raygun.Utilities.isIE()) {


if (
typeof self.originalFetch === 'function' &&
typeof self.originalFetch.polyfill === 'undefined' &&
!Raygun.Utilities.isIE()
) {
var processFetch = function() {
var fetchInput = arguments[0];
var url, baseUrl;
Expand All @@ -171,66 +173,68 @@ window.raygunNetworkTrackingFactory = function(window, Raygun) {
url = Raygun.Utilities.resolveFullUrl(url);
baseUrl = url.split('?')[0];

var promise = originalFetch.apply(null, arguments);
var promise = self.originalFetch.apply(null, arguments);

try {
var metadata = {
method: method,
requestURL: url,
baseUrl: baseUrl,
};

if (options && options.body) {
metadata.body = options.body;
}
var metadata = {
method: method,
requestURL: url,
baseUrl: baseUrl,
};

self.executeHandlers(self.requestHandlers, metadata);

promise.then(
self.wrapWithHandler(function(response) {
var body = 'N/A when the fetch response does not support clone()';
var ourResponse = typeof response.clone === 'function' ? response.clone() : undefined;

function executeHandlers() {
Raygun.Utilities.log('tracking fetch response for', url);
self.executeHandlers(self.responseHandlers, {
status: response.status,
requestURL: url,
responseURL: response.url,
body: body,
baseUrl: baseUrl,
duration: new Date().getTime() - initTime,
});
}
if (options && options.body) {
metadata.body = options.body;
}

if (ourResponse) {
try {
ourResponse.text().then(function(text) {
body = Raygun.Utilities.truncate(text, 500);
self.executeHandlers(self.requestHandlers, metadata);

executeHandlers();
}).catch(function() { executeHandlers(); });
} catch(_e) {
executeHandlers();
}
} else {
executeHandlers();
}
})
).catch(
self.wrapWithHandler(function(error) {
self.executeHandlers(self.errorHandlers, {
metadata: {
requestUrl: url,
error: error.toString(),
duration: new Date().getTime() - initTime,
},
promise
.then(function (response) {
var ourResponse = typeof response.clone === 'function' ? response.clone() : undefined;

function executeResponseHandlers(body) {
Raygun.Utilities.log('tracking fetch response for', url);
self.executeHandlers(self.responseHandlers, {
status: response.status,
requestURL: url,
responseURL: response.url,
body: body,
baseUrl: baseUrl,
duration: new Date().getTime() - initTime,
});
})
);
} catch (e) {
Raygun.Utilities.log(e);
}
}

if (ourResponse && typeof ourResponse.text === 'function') {
// Return the promise so that it may be handled by the parent catch.
return ourResponse.text().then(
// Fulfilled
function (text) {
var truncatedResponseText = Raygun.Utilities.truncate(text, 500);
executeResponseHandlers(truncatedResponseText);
},
// Rejected
function (reason) {
var err = '';
if (reason instanceof Error) {
err = ': ' + reason.message;
} else if (typeof reason === 'string') {
err = ': ' + reason;
}
executeResponseHandlers('N/A response.text() rejected' + err);
}
);
}

executeResponseHandlers('N/A when the fetch response does not support clone()');
})
.catch(function (error) {
self.executeHandlers(self.errorHandlers, {
metadata: {
requestUrl: url,
error: error.toString(),
duration: new Date().getTime() - initTime,
},
});
});

return promise;
};
Expand All @@ -240,11 +244,13 @@ window.raygunNetworkTrackingFactory = function(window, Raygun) {
} else {
window.fetch = processFetch;
}
}
};

disableFetchLogging = function() {
window.fetch = originalFetch;
delete window.__raygunFetchCallback;
};
NetworkTracking.prototype.disableFetchLogging = function() {
if (this.originalFetch !== undefined) {
window.fetch = this.originalFetch;
delete window.__raygunFetchCallback;
}
};

Expand Down