Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
package.build.npm.esm.integrations.breadcrumbs.js Maven / Gradle / Ivy
import { addClickKeypressInstrumentationHandler, addXhrInstrumentationHandler, addHistoryInstrumentationHandler, SENTRY_XHR_DATA_KEY } from '@sentry-internal/browser-utils';
import { defineIntegration, getClient, addBreadcrumb } from '@sentry/core';
import { addConsoleInstrumentationHandler, addFetchInstrumentationHandler, getEventDescription, logger, htmlTreeAsString, getComponentName, severityLevelFromString, safeJoin, getBreadcrumbLogLevelFromHttpStatusCode, parseUrl } from '@sentry/utils';
import { DEBUG_BUILD } from '../debug-build.js';
import { WINDOW } from '../helpers.js';
/** maxStringLength gets capped to prevent 100 breadcrumbs exceeding 1MB event payload size */
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) {
addConsoleInstrumentationHandler(_getConsoleBreadcrumbHandler(client));
}
if (_options.dom) {
addClickKeypressInstrumentationHandler(_getDomBreadcrumbHandler(client, _options.dom));
}
if (_options.xhr) {
addXhrInstrumentationHandler(_getXhrBreadcrumbHandler(client));
}
if (_options.fetch) {
addFetchInstrumentationHandler(_getFetchBreadcrumbHandler(client));
}
if (_options.history) {
addHistoryInstrumentationHandler(_getHistoryBreadcrumbHandler(client));
}
if (_options.sentry) {
client.on('beforeSendEvent', _getSentryBreadcrumbHandler(client));
}
},
};
}) ;
const breadcrumbsIntegration = defineIntegration(_breadcrumbsIntegration);
/**
* Adds a breadcrumb for Sentry events or transactions if this option is enabled.
*/
function _getSentryBreadcrumbHandler(client) {
return function addSentryBreadcrumb(event) {
if (getClient() !== client) {
return;
}
addBreadcrumb(
{
category: `sentry.${event.type === 'transaction' ? 'transaction' : 'event'}`,
event_id: event.event_id,
level: event.level,
message: getEventDescription(event),
},
{
event,
},
);
};
}
/**
* A HOC that creaes a function that creates breadcrumbs from DOM API calls.
* This is a HOC so that we get access to dom options in the closure.
*/
function _getDomBreadcrumbHandler(
client,
dom,
) {
return function _innerDomBreadcrumb(handlerData) {
if (getClient() !== client) {
return;
}
let target;
let componentName;
let keyAttrs = typeof dom === 'object' ? dom.serializeAttribute : undefined;
let maxStringLength =
typeof dom === 'object' && typeof dom.maxStringLength === 'number' ? dom.maxStringLength : undefined;
if (maxStringLength && maxStringLength > MAX_ALLOWED_STRING_LENGTH) {
DEBUG_BUILD &&
logger.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];
}
// Accessing event.target can throw (see getsentry/raven-js#838, #768)
try {
const event = handlerData.event ;
const element = _isEvent(event) ? event.target : event;
target = htmlTreeAsString(element, { keyAttrs, maxStringLength });
componentName = getComponentName(element);
} catch (e) {
target = '';
}
if (target.length === 0) {
return;
}
const breadcrumb = {
category: `ui.${handlerData.name}`,
message: target,
};
if (componentName) {
breadcrumb.data = { 'ui.component_name': componentName };
}
addBreadcrumb(breadcrumb, {
event: handlerData.event,
name: handlerData.name,
global: handlerData.global,
});
};
}
/**
* Creates breadcrumbs from console API calls
*/
function _getConsoleBreadcrumbHandler(client) {
return function _consoleBreadcrumb(handlerData) {
if (getClient() !== client) {
return;
}
const breadcrumb = {
category: 'console',
data: {
arguments: handlerData.args,
logger: 'console',
},
level: severityLevelFromString(handlerData.level),
message: safeJoin(handlerData.args, ' '),
};
if (handlerData.level === 'assert') {
if (handlerData.args[0] === false) {
breadcrumb.message = `Assertion failed: ${safeJoin(handlerData.args.slice(1), ' ') || 'console.assert'}`;
breadcrumb.data.arguments = handlerData.args.slice(1);
} else {
// Don't capture a breadcrumb for passed assertions
return;
}
}
addBreadcrumb(breadcrumb, {
input: handlerData.args,
level: handlerData.level,
});
};
}
/**
* Creates breadcrumbs from XHR API calls
*/
function _getXhrBreadcrumbHandler(client) {
return function _xhrBreadcrumb(handlerData) {
if (getClient() !== client) {
return;
}
const { startTimestamp, endTimestamp } = handlerData;
const sentryXhrData = handlerData.xhr[SENTRY_XHR_DATA_KEY];
// We only capture complete, non-sentry requests
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 level = getBreadcrumbLogLevelFromHttpStatusCode(status_code);
addBreadcrumb(
{
category: 'xhr',
data,
type: 'http',
level,
},
hint,
);
};
}
/**
* Creates breadcrumbs from fetch API calls
*/
function _getFetchBreadcrumbHandler(client) {
return function _fetchBreadcrumb(handlerData) {
if (getClient() !== client) {
return;
}
const { startTimestamp, endTimestamp } = handlerData;
// We only capture complete fetch requests
if (!endTimestamp) {
return;
}
if (handlerData.fetchData.url.match(/sentry_key/) && handlerData.fetchData.method === 'POST') {
// We will not create breadcrumbs for fetch requests that contain `sentry_key` (internal sentry requests)
return;
}
if (handlerData.error) {
const data = handlerData.fetchData;
const hint = {
data: handlerData.error,
input: handlerData.args,
startTimestamp,
endTimestamp,
};
addBreadcrumb(
{
category: 'fetch',
data,
level: 'error',
type: 'http',
},
hint,
);
} else {
const response = handlerData.response ;
const data = {
...handlerData.fetchData,
status_code: response && response.status,
};
const hint = {
input: handlerData.args,
response,
startTimestamp,
endTimestamp,
};
const level = getBreadcrumbLogLevelFromHttpStatusCode(data.status_code);
addBreadcrumb(
{
category: 'fetch',
data,
type: 'http',
level,
},
hint,
);
}
};
}
/**
* Creates breadcrumbs from history API calls
*/
function _getHistoryBreadcrumbHandler(client) {
return function _historyBreadcrumb(handlerData) {
if (getClient() !== client) {
return;
}
let from = handlerData.from;
let to = handlerData.to;
const parsedLoc = parseUrl(WINDOW.location.href);
let parsedFrom = from ? parseUrl(from) : undefined;
const parsedTo = parseUrl(to);
// Initial pushState doesn't provide `from` information
if (!parsedFrom || !parsedFrom.path) {
parsedFrom = parsedLoc;
}
// Use only the path component of the URL if the URL matches the current
// document (almost all the time when using pushState)
if (parsedLoc.protocol === parsedTo.protocol && parsedLoc.host === parsedTo.host) {
to = parsedTo.relative;
}
if (parsedLoc.protocol === parsedFrom.protocol && parsedLoc.host === parsedFrom.host) {
from = parsedFrom.relative;
}
addBreadcrumb({
category: 'navigation',
data: {
from,
to,
},
});
};
}
function _isEvent(event) {
return !!event && !!(event ).target;
}
export { breadcrumbsIntegration };
//# sourceMappingURL=breadcrumbs.js.map