@sentry/browser
Version:
Official Sentry SDK for browsers
250 lines (246 loc) • 7.63 kB
JavaScript
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const browser = require('@sentry/core/browser');
const browserUtils = require('@sentry-internal/browser-utils');
const debugBuild = require('../debug-build.js');
const helpers = require('../helpers.js');
const MAX_ALLOWED_STRING_LENGTH = 1024;
const INTEGRATION_NAME = "Breadcrumbs";
const _breadcrumbsIntegration = ((options = {}) => {
const _options = {
console: true,
dom: true,
fetch: true,
history: true,
sentry: true,
xhr: true,
...options
};
return {
name: INTEGRATION_NAME,
setup(client) {
if (_options.console) {
browser.addConsoleInstrumentationHandler(_getConsoleBreadcrumbHandler(client));
}
if (_options.dom) {
browserUtils.addClickKeypressInstrumentationHandler(_getDomBreadcrumbHandler(client, _options.dom));
}
if (_options.xhr) {
browserUtils.addXhrInstrumentationHandler(_getXhrBreadcrumbHandler(client));
}
if (_options.fetch) {
browser.addFetchInstrumentationHandler(_getFetchBreadcrumbHandler(client));
}
if (_options.history) {
browserUtils.addHistoryInstrumentationHandler(_getHistoryBreadcrumbHandler(client));
}
if (_options.sentry) {
client.on("beforeSendEvent", _getSentryBreadcrumbHandler(client));
}
}
};
});
const breadcrumbsIntegration = browser.defineIntegration(_breadcrumbsIntegration);
function _getSentryBreadcrumbHandler(client) {
return function addSentryBreadcrumb(event) {
if (browser.getClient() !== client) {
return;
}
browser.addBreadcrumb(
{
category: `sentry.${event.type === "transaction" ? "transaction" : "event"}`,
event_id: event.event_id,
level: event.level,
message: browser.getEventDescription(event)
},
{
event
}
);
};
}
function _getDomBreadcrumbHandler(client, dom) {
return function _innerDomBreadcrumb(handlerData) {
if (browser.getClient() !== client) {
return;
}
let target;
let componentName;
let keyAttrs = typeof dom === "object" ? dom.serializeAttribute : void 0;
let maxStringLength = typeof dom === "object" && typeof dom.maxStringLength === "number" ? dom.maxStringLength : void 0;
if (maxStringLength && maxStringLength > MAX_ALLOWED_STRING_LENGTH) {
debugBuild.DEBUG_BUILD && browser.debug.warn(
`\`dom.maxStringLength\` cannot exceed ${MAX_ALLOWED_STRING_LENGTH}, but a value of ${maxStringLength} was configured. Sentry will use ${MAX_ALLOWED_STRING_LENGTH} instead.`
);
maxStringLength = MAX_ALLOWED_STRING_LENGTH;
}
if (typeof keyAttrs === "string") {
keyAttrs = [keyAttrs];
}
try {
const event = handlerData.event;
const element = _isEvent(event) ? event.target : event;
target = browserUtils.htmlTreeAsString(element, { keyAttrs, maxStringLength });
componentName = browser.getComponentName(element);
} catch {
target = "<unknown>";
}
if (target.length === 0) {
return;
}
const breadcrumb = {
category: `ui.${handlerData.name}`,
message: target
};
if (componentName) {
breadcrumb.data = { "ui.component_name": componentName };
}
browser.addBreadcrumb(breadcrumb, {
event: handlerData.event,
name: handlerData.name,
global: handlerData.global
});
};
}
function _getConsoleBreadcrumbHandler(client) {
return function _consoleBreadcrumb(handlerData) {
if (browser.getClient() !== client) {
return;
}
const breadcrumb = {
category: "console",
data: {
arguments: handlerData.args,
logger: "console"
},
level: browser.severityLevelFromString(handlerData.level),
message: browser.safeJoin(handlerData.args, " ")
};
if (handlerData.level === "assert") {
if (handlerData.args[0] === false) {
breadcrumb.message = `Assertion failed: ${browser.safeJoin(handlerData.args.slice(1), " ") || "console.assert"}`;
breadcrumb.data.arguments = handlerData.args.slice(1);
} else {
return;
}
}
browser.addBreadcrumb(breadcrumb, {
input: handlerData.args,
level: handlerData.level
});
};
}
function _getXhrBreadcrumbHandler(client) {
return function _xhrBreadcrumb(handlerData) {
if (browser.getClient() !== client) {
return;
}
const { startTimestamp, endTimestamp } = handlerData;
const sentryXhrData = handlerData.xhr[browserUtils.SENTRY_XHR_DATA_KEY];
if (!startTimestamp || !endTimestamp || !sentryXhrData) {
return;
}
const { method, url, status_code, body } = sentryXhrData;
const data = {
method,
url,
status_code
};
const hint = {
xhr: handlerData.xhr,
input: body,
startTimestamp,
endTimestamp
};
const breadcrumb = {
category: "xhr",
data,
type: "http",
level: browser.getBreadcrumbLogLevelFromHttpStatusCode(status_code)
};
client.emit("beforeOutgoingRequestBreadcrumb", breadcrumb, hint);
browser.addBreadcrumb(breadcrumb, hint);
};
}
function _getFetchBreadcrumbHandler(client) {
return function _fetchBreadcrumb(handlerData) {
if (browser.getClient() !== client) {
return;
}
const { startTimestamp, endTimestamp } = handlerData;
if (!endTimestamp) {
return;
}
if (handlerData.fetchData.url.match(/sentry_key/) && handlerData.fetchData.method === "POST") {
return;
}
if (handlerData.error) {
const hint = {
data: handlerData.error,
input: handlerData.args,
startTimestamp,
endTimestamp
};
const breadcrumb = {
category: "fetch",
data: handlerData.fetchData,
level: "error",
type: "http"
};
client.emit("beforeOutgoingRequestBreadcrumb", breadcrumb, hint);
browser.addBreadcrumb(breadcrumb, hint);
} else {
const response = handlerData.response;
const data = {
...handlerData.fetchData,
status_code: response?.status
};
const hint = {
input: handlerData.args,
response,
startTimestamp,
endTimestamp
};
const breadcrumb = {
category: "fetch",
data,
type: "http",
level: browser.getBreadcrumbLogLevelFromHttpStatusCode(data.status_code)
};
client.emit("beforeOutgoingRequestBreadcrumb", breadcrumb, hint);
browser.addBreadcrumb(breadcrumb, hint);
}
};
}
function _getHistoryBreadcrumbHandler(client) {
return function _historyBreadcrumb(handlerData) {
if (browser.getClient() !== client) {
return;
}
let from = handlerData.from;
let to = handlerData.to;
const parsedLoc = browser.parseUrl(helpers.WINDOW.location.href);
let parsedFrom = from ? browser.parseUrl(from) : void 0;
const parsedTo = browser.parseUrl(to);
if (!parsedFrom?.path) {
parsedFrom = parsedLoc;
}
if (parsedLoc.protocol === parsedTo.protocol && parsedLoc.host === parsedTo.host) {
to = parsedTo.relative;
}
if (parsedLoc.protocol === parsedFrom.protocol && parsedLoc.host === parsedFrom.host) {
from = parsedFrom.relative;
}
browser.addBreadcrumb({
category: "navigation",
data: {
from,
to
}
});
};
}
function _isEvent(event) {
return !!event && !!event.target;
}
exports.breadcrumbsIntegration = breadcrumbsIntegration;
//# sourceMappingURL=breadcrumbs.js.map