Skip to content

Commit 6e09ffe

Browse files
authored
feat(browser): support dom.maxStringLength configuration (#6175) (#6311)
1 parent a171f35 commit 6e09ffe

File tree

3 files changed

+57
-7
lines changed

3 files changed

+57
-7
lines changed

packages/browser/src/integrations/breadcrumbs.ts

+22-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
addInstrumentationHandler,
77
getEventDescription,
88
htmlTreeAsString,
9+
logger,
910
parseUrl,
1011
safeJoin,
1112
severityLevelFromString,
@@ -16,13 +17,21 @@ import { WINDOW } from '../helpers';
1617
/** JSDoc */
1718
interface BreadcrumbsOptions {
1819
console: boolean;
19-
dom: boolean | { serializeAttribute: string | string[] };
20+
dom:
21+
| boolean
22+
| {
23+
serializeAttribute?: string | string[];
24+
maxStringLength?: number;
25+
};
2026
fetch: boolean;
2127
history: boolean;
2228
sentry: boolean;
2329
xhr: boolean;
2430
}
2531

32+
/** maxStringLength gets capped to prevent 100 breadcrumbs exceeding 1MB event payload size */
33+
const MAX_ALLOWED_STRING_LENGTH = 1024;
34+
2635
export const BREADCRUMB_INTEGRATION_ID = 'Breadcrumbs';
2736

2837
/**
@@ -118,15 +127,25 @@ function _domBreadcrumb(dom: BreadcrumbsOptions['dom']): (handlerData: { [key: s
118127
let target;
119128
let keyAttrs = typeof dom === 'object' ? dom.serializeAttribute : undefined;
120129

130+
let maxStringLength =
131+
typeof dom === 'object' && typeof dom.maxStringLength === 'number' ? dom.maxStringLength : undefined;
132+
if (maxStringLength && maxStringLength > MAX_ALLOWED_STRING_LENGTH) {
133+
__DEBUG_BUILD__ &&
134+
logger.warn(
135+
`\`dom.maxStringLength\` cannot exceed ${MAX_ALLOWED_STRING_LENGTH}, but a value of ${maxStringLength} was configured. Sentry will use ${MAX_ALLOWED_STRING_LENGTH} instead.`,
136+
);
137+
maxStringLength = MAX_ALLOWED_STRING_LENGTH;
138+
}
139+
121140
if (typeof keyAttrs === 'string') {
122141
keyAttrs = [keyAttrs];
123142
}
124143

125144
// Accessing event.target can throw (see getsentry/raven-js#838, #768)
126145
try {
127146
target = handlerData.event.target
128-
? htmlTreeAsString(handlerData.event.target as Node, keyAttrs)
129-
: htmlTreeAsString(handlerData.event as unknown as Node, keyAttrs);
147+
? htmlTreeAsString(handlerData.event.target as Node, { keyAttrs, maxStringLength })
148+
: htmlTreeAsString(handlerData.event as unknown as Node, { keyAttrs, maxStringLength });
130149
} catch (e) {
131150
target = '<unknown>';
132151
}

packages/utils/src/browser.ts

+10-4
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,18 @@ import { getGlobalObject } from './worldwide';
44
// eslint-disable-next-line deprecation/deprecation
55
const WINDOW = getGlobalObject<Window>();
66

7+
const DEFAULT_MAX_STRING_LENGTH = 80;
8+
79
/**
810
* Given a child DOM element, returns a query-selector statement describing that
911
* and its ancestors
1012
* e.g. [HTMLElement] => body > div > input#foo.btn[name=baz]
1113
* @returns generated DOM path
1214
*/
13-
export function htmlTreeAsString(elem: unknown, keyAttrs?: string[]): string {
15+
export function htmlTreeAsString(
16+
elem: unknown,
17+
options: string[] | { keyAttrs?: string[]; maxStringLength?: number } = {},
18+
): string {
1419
type SimpleNode = {
1520
parentNode: SimpleNode;
1621
} | null;
@@ -22,21 +27,22 @@ export function htmlTreeAsString(elem: unknown, keyAttrs?: string[]): string {
2227
try {
2328
let currentElem = elem as SimpleNode;
2429
const MAX_TRAVERSE_HEIGHT = 5;
25-
const MAX_OUTPUT_LEN = 80;
2630
const out = [];
2731
let height = 0;
2832
let len = 0;
2933
const separator = ' > ';
3034
const sepLength = separator.length;
3135
let nextStr;
36+
const keyAttrs = Array.isArray(options) ? options : options.keyAttrs;
37+
const maxStringLength = (!Array.isArray(options) && options.maxStringLength) || DEFAULT_MAX_STRING_LENGTH;
3238

3339
while (currentElem && height++ < MAX_TRAVERSE_HEIGHT) {
3440
nextStr = _htmlElementAsString(currentElem, keyAttrs);
3541
// bail out if
3642
// - nextStr is the 'html' element
37-
// - the length of the string that would be created exceeds MAX_OUTPUT_LEN
43+
// - the length of the string that would be created exceeds maxStringLength
3844
// (ignore this limit if we are on the first iteration)
39-
if (nextStr === 'html' || (height > 1 && len + out.length * sepLength + nextStr.length >= MAX_OUTPUT_LEN)) {
45+
if (nextStr === 'html' || (height > 1 && len + out.length * sepLength + nextStr.length >= maxStringLength)) {
4046
break;
4147
}
4248

packages/utils/test/browser.test.ts

+25
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ beforeAll(() => {
99
});
1010

1111
describe('htmlTreeAsString', () => {
12+
beforeEach(() => {
13+
document.body.innerHTML = '';
14+
});
15+
1216
it('generates html tree for a simple element', () => {
1317
const el = document.createElement('ul');
1418
el.innerHTML = `<li class="container">
@@ -40,9 +44,30 @@ describe('htmlTreeAsString', () => {
4044
</li>`;
4145
document.body.appendChild(el);
4246

47+
// Two formats for specifying keyAttrs
4348
expect(htmlTreeAsString(document.getElementById('cat-2'), ['test-id'])).toBe(
4449
'body > ul > li.li-class[title="li-title"] > img[test-id="cat-2-test-id"]',
4550
);
51+
expect(htmlTreeAsString(document.getElementById('cat-2'), { keyAttrs: ['test-id'] })).toBe(
52+
'body > ul > li.li-class[title="li-title"] > img[test-id="cat-2-test-id"]',
53+
);
54+
});
55+
56+
it('caps string output according to provided maxStringLength', () => {
57+
const el = document.createElement('div');
58+
el.innerHTML = `<div id="main-cta">
59+
<div class="container">
60+
<button class="bg-blue-500 hover:bg-blue-700 text-white hover:text-blue-100" />
61+
</div>
62+
</div>`;
63+
document.body.appendChild(el);
64+
65+
expect(htmlTreeAsString(document.querySelector('button'))).toBe(
66+
'button.bg-blue-500.hover:bg-blue-700.text-white.hover:text-blue-100',
67+
);
68+
expect(htmlTreeAsString(document.querySelector('button'), { maxStringLength: 100 })).toBe(
69+
'div#main-cta > div.container > button.bg-blue-500.hover:bg-blue-700.text-white.hover:text-blue-100',
70+
);
4671
});
4772
});
4873

0 commit comments

Comments
 (0)