Skip to content

Commit 99d7476

Browse files
committed
feat(browser): support dom.maxStringLength configuration (#6175)
1 parent b49082e commit 99d7476

File tree

3 files changed

+40
-7
lines changed

3 files changed

+40
-7
lines changed

packages/browser/src/integrations/breadcrumbs.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,13 @@ import { WINDOW } from '../helpers';
1515
/** JSDoc */
1616
interface BreadcrumbsOptions {
1717
console: boolean;
18-
dom: boolean | { serializeAttribute: string | string[] };
18+
dom:
19+
| boolean
20+
| {
21+
serializeAttribute?: string | string[];
22+
/** maxStringLength gets capped at 1024 to prevent 100 breadcrumbs exceeding 1MB event payload size */
23+
maxStringLength?: number;
24+
};
1925
fetch: boolean;
2026
history: boolean;
2127
sentry: boolean;
@@ -97,6 +103,10 @@ function _domBreadcrumb(dom: BreadcrumbsOptions['dom']): (handlerData: { [key: s
97103
function _innerDomBreadcrumb(handlerData: { [key: string]: any }): void {
98104
let target;
99105
let keyAttrs = typeof dom === 'object' ? dom.serializeAttribute : undefined;
106+
const customMaxStringLength =
107+
typeof dom === 'object' && typeof dom.maxStringLength === 'number'
108+
? Math.min(dom.maxStringLength, 1024)
109+
: undefined;
100110

101111
if (typeof keyAttrs === 'string') {
102112
keyAttrs = [keyAttrs];
@@ -105,8 +115,8 @@ function _domBreadcrumb(dom: BreadcrumbsOptions['dom']): (handlerData: { [key: s
105115
// Accessing event.target can throw (see getsentry/raven-js#838, #768)
106116
try {
107117
target = handlerData.event.target
108-
? htmlTreeAsString(handlerData.event.target as Node, keyAttrs)
109-
: htmlTreeAsString(handlerData.event as unknown as Node, keyAttrs);
118+
? htmlTreeAsString(handlerData.event.target as Node, keyAttrs, customMaxStringLength)
119+
: htmlTreeAsString(handlerData.event as unknown as Node, keyAttrs, customMaxStringLength);
110120
} catch (e) {
111121
target = '<unknown>';
112122
}

packages/utils/src/browser.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ 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(elem: unknown, keyAttrs?: string[], customMaxStringLength?: number): string {
1416
type SimpleNode = {
1517
parentNode: SimpleNode;
1618
} | null;
@@ -22,7 +24,7 @@ export function htmlTreeAsString(elem: unknown, keyAttrs?: string[]): string {
2224
try {
2325
let currentElem = elem as SimpleNode;
2426
const MAX_TRAVERSE_HEIGHT = 5;
25-
const MAX_OUTPUT_LEN = 80;
27+
const maxStringLength = customMaxStringLength || DEFAULT_MAX_STRING_LENGTH;
2628
const out = [];
2729
let height = 0;
2830
let len = 0;
@@ -35,9 +37,9 @@ export function htmlTreeAsString(elem: unknown, keyAttrs?: string[]): string {
3537
nextStr = _htmlElementAsString(currentElem, keyAttrs);
3638
// bail out if
3739
// - nextStr is the 'html' element
38-
// - the length of the string that would be created exceeds MAX_OUTPUT_LEN
40+
// - the length of the string that would be created exceeds maxStringLength
3941
// (ignore this limit if we are on the first iteration)
40-
if (nextStr === 'html' || (height > 1 && len + out.length * sepLength + nextStr.length >= MAX_OUTPUT_LEN)) {
42+
if (nextStr === 'html' || (height > 1 && len + out.length * sepLength + nextStr.length >= maxStringLength)) {
4143
break;
4244
}
4345

packages/utils/test/browser.test.ts

Lines changed: 21 additions & 0 deletions
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">
@@ -44,6 +48,23 @@ describe('htmlTreeAsString', () => {
4448
'body > ul > li.li-class[title="li-title"] > img[test-id="cat-2-test-id"]',
4549
);
4650
});
51+
52+
it('caps string output according to provided maxStringLength', () => {
53+
const el = document.createElement('div');
54+
el.innerHTML = `<div id="main-cta">
55+
<div class="container">
56+
<button class="bg-blue-500 hover:bg-blue-700 text-white hover:text-blue-100" />
57+
</div>
58+
</div>`;
59+
document.body.appendChild(el);
60+
61+
expect(htmlTreeAsString(document.querySelector('button'))).toBe(
62+
'button.bg-blue-500.hover:bg-blue-700.text-white.hover:text-blue-100',
63+
);
64+
expect(htmlTreeAsString(document.querySelector('button'), undefined, 100)).toBe(
65+
'div#main-cta > div.container > button.bg-blue-500.hover:bg-blue-700.text-white.hover:text-blue-100',
66+
);
67+
});
4768
});
4869

4970
describe('getDomElement', () => {

0 commit comments

Comments
 (0)