@grafana/faro-web-sdk
Version:
Faro instrumentations, metas, transports for web.
123 lines • 4.31 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.monitorHttpRequests = monitorHttpRequests;
exports.__resetHttpRequestMonitorForTests = __resetHttpRequestMonitorForTests;
const faro_core_1 = require("@grafana/faro-core");
const url_1 = require("../../../utils/url");
const const_1 = require("./const");
const apiTypeFetch = 'fetch';
const apiTypeXhr = 'xhr';
/**
* Monitors if any http requests are in progress.
*/
let httpRequestObservable;
let isInstrumented = false;
let originalXhrOpen;
let originalFetchFn;
function monitorHttpRequests() {
if (httpRequestObservable) {
return httpRequestObservable;
}
httpRequestObservable = new faro_core_1.Observable();
function emitStartMessage(requestProps) {
httpRequestObservable.notify({
type: const_1.MESSAGE_TYPE_HTTP_REQUEST_START,
request: requestProps,
});
}
function emitEndMessage(requestProps) {
httpRequestObservable.notify({
type: const_1.MESSAGE_TYPE_HTTP_REQUEST_END,
request: requestProps,
});
}
if (!isInstrumented) {
monitorFetch({
onRequestStart: emitStartMessage,
onRequestEnd: emitEndMessage,
});
monitorXhr({
onRequestStart: emitStartMessage,
onRequestEnd: emitEndMessage,
});
isInstrumented = true;
}
return httpRequestObservable;
}
function monitorXhr({ onRequestStart, onRequestEnd, }) {
if (!originalXhrOpen) {
originalXhrOpen = XMLHttpRequest.prototype.open;
}
XMLHttpRequest.prototype.open = function () {
const url = arguments[1];
const isIgnoredUrl = (0, url_1.isUrlIgnored)(url);
const method = arguments[0];
const requestId = (0, faro_core_1.genShortID)();
// request has started to load data.
this.addEventListener('loadstart', function () {
if (!isIgnoredUrl) {
onRequestStart({ url, method, requestId, apiType: apiTypeXhr });
}
});
// transaction completes successfully.
this.addEventListener('load', function () {
if (!isIgnoredUrl) {
onRequestEnd({ url, method, requestId, apiType: apiTypeXhr });
}
});
this.addEventListener('error', function () {
if (!isIgnoredUrl) {
onRequestEnd({ url, method, requestId, apiType: apiTypeXhr });
}
});
this.addEventListener('abort', function () {
if (!isIgnoredUrl) {
onRequestEnd({ url, method, requestId, apiType: apiTypeXhr });
}
});
originalXhrOpen.apply(this, arguments);
};
}
function monitorFetch({ onRequestEnd, onRequestStart, }) {
if (!originalFetchFn) {
originalFetchFn = window.fetch;
}
window.fetch = function () {
var _a, _b;
const url = (_a = (0, url_1.getUrlFromResource)(arguments[0])) !== null && _a !== void 0 ? _a : '';
const isIgnoredUrl = (0, url_1.isUrlIgnored)(url);
const method = ((_b = arguments[1]) !== null && _b !== void 0 ? _b : {}).method;
const requestId = (0, faro_core_1.genShortID)();
if (!isIgnoredUrl) {
onRequestStart({ url, method, requestId, apiType: apiTypeFetch });
}
return originalFetchFn
.apply(this, arguments)
.then((response) => {
if (!isIgnoredUrl) {
onRequestEnd({ url, method, requestId, apiType: apiTypeFetch });
}
return response;
})
.catch((error) => {
if (!isIgnoredUrl) {
onRequestEnd({ url, method, requestId, apiType: apiTypeFetch });
}
throw error;
});
};
}
// Test-only utility to reset instrumentation and singleton between tests
function __resetHttpRequestMonitorForTests() {
if (originalXhrOpen) {
XMLHttpRequest.prototype.open = originalXhrOpen;
}
if (originalFetchFn) {
window.fetch = originalFetchFn;
}
httpRequestObservable = undefined;
isInstrumented = false;
originalXhrOpen = undefined;
originalFetchFn = undefined;
}
//# sourceMappingURL=httpRequestMonitor.js.map