Skip to content

Commit 2fbd7cc

Browse files
authored
fix(core): Use maxValueLength in extra error data integration (#12174)
fixes #12168 We should truncate extra error data keys using `maxValueLength` to make sure event payload size stays reasonably small.
1 parent 1d66b8a commit 2fbd7cc

File tree

2 files changed

+48
-18
lines changed

2 files changed

+48
-18
lines changed

packages/core/src/integrations/extraerrordata.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { Contexts, Event, EventHint, ExtendedError, IntegrationFn } from '@sentry/types';
2-
import { addNonEnumerableProperty, isError, isPlainObject, logger, normalize } from '@sentry/utils';
2+
import { addNonEnumerableProperty, isError, isPlainObject, logger, normalize, truncate } from '@sentry/utils';
33
import { defineIntegration } from '../integration';
44

55
import { DEBUG_BUILD } from '../debug-build';
@@ -27,8 +27,9 @@ const _extraErrorDataIntegration = ((options: Partial<ExtraErrorDataOptions> = {
2727
const { depth = 3, captureErrorCause = true } = options;
2828
return {
2929
name: INTEGRATION_NAME,
30-
processEvent(event, hint) {
31-
return _enhanceEventWithErrorData(event, hint, depth, captureErrorCause);
30+
processEvent(event, hint, client) {
31+
const { maxValueLength = 250 } = client.getOptions();
32+
return _enhanceEventWithErrorData(event, hint, depth, captureErrorCause, maxValueLength);
3233
},
3334
};
3435
}) satisfies IntegrationFn;
@@ -40,13 +41,14 @@ function _enhanceEventWithErrorData(
4041
hint: EventHint = {},
4142
depth: number,
4243
captureErrorCause: boolean,
44+
maxValueLength: number,
4345
): Event {
4446
if (!hint.originalException || !isError(hint.originalException)) {
4547
return event;
4648
}
4749
const exceptionName = (hint.originalException as ExtendedError).name || hint.originalException.constructor.name;
4850

49-
const errorData = _extractErrorData(hint.originalException as ExtendedError, captureErrorCause);
51+
const errorData = _extractErrorData(hint.originalException as ExtendedError, captureErrorCause, maxValueLength);
5052

5153
if (errorData) {
5254
const contexts: Contexts = {
@@ -74,7 +76,11 @@ function _enhanceEventWithErrorData(
7476
/**
7577
* Extract extra information from the Error object
7678
*/
77-
function _extractErrorData(error: ExtendedError, captureErrorCause: boolean): Record<string, unknown> | null {
79+
function _extractErrorData(
80+
error: ExtendedError,
81+
captureErrorCause: boolean,
82+
maxValueLength: number,
83+
): Record<string, unknown> | null {
7884
// We are trying to enhance already existing event, so no harm done if it won't succeed
7985
try {
8086
const nativeKeys = [
@@ -97,7 +103,7 @@ function _extractErrorData(error: ExtendedError, captureErrorCause: boolean): Re
97103
continue;
98104
}
99105
const value = error[key];
100-
extraErrorInfo[key] = isError(value) ? value.toString() : value;
106+
extraErrorInfo[key] = isError(value) || typeof value === 'string' ? truncate(`${value}`, maxValueLength) : value;
101107
}
102108

103109
// Error.cause is a standard property that is non enumerable, we therefore need to access it separately.

packages/core/test/lib/integrations/extraerrordata.test.ts

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@ import type { Event as SentryEvent, ExtendedError } from '@sentry/types';
22

33
import { extraErrorDataIntegration } from '../../../src/integrations/extraerrordata';
44

5+
import { TestClient, getDefaultTestClientOptions } from '../../mocks/client';
6+
57
const extraErrorData = extraErrorDataIntegration();
68
let event: SentryEvent;
79

810
describe('ExtraErrorData()', () => {
11+
const testClient = new TestClient(getDefaultTestClientOptions({ maxValueLength: 250 }));
912
beforeEach(() => {
1013
event = {};
1114
});
@@ -20,7 +23,7 @@ describe('ExtraErrorData()', () => {
2023
{
2124
originalException: error,
2225
},
23-
{} as any,
26+
testClient,
2427
) as SentryEvent;
2528

2629
expect(enhancedEvent.contexts).toEqual({
@@ -31,6 +34,27 @@ describe('ExtraErrorData()', () => {
3134
});
3235
});
3336

37+
it('should use maxValueLength to truncate extra data', () => {
38+
const error = new TypeError('foo') as ExtendedError;
39+
error.baz = 42;
40+
error.foo = 'a'.repeat(300);
41+
42+
const enhancedEvent = extraErrorData.processEvent?.(
43+
event,
44+
{
45+
originalException: error,
46+
},
47+
testClient,
48+
) as SentryEvent;
49+
50+
expect(enhancedEvent.contexts).toEqual({
51+
TypeError: {
52+
baz: 42,
53+
foo: `${'a'.repeat(250)}...`,
54+
},
55+
});
56+
});
57+
3458
it('doesnt choke on linked errors and stringify names instead', () => {
3559
const error = new TypeError('foo') as ExtendedError;
3660
error.cause = new SyntaxError('bar');
@@ -40,7 +64,7 @@ describe('ExtraErrorData()', () => {
4064
{
4165
originalException: error,
4266
},
43-
{} as any,
67+
testClient,
4468
) as SentryEvent;
4569

4670
expect(enhancedEvent.contexts).toEqual({
@@ -65,7 +89,7 @@ describe('ExtraErrorData()', () => {
6589
{
6690
originalException: error,
6791
},
68-
{} as any,
92+
testClient,
6993
) as SentryEvent;
7094

7195
expect(enhancedEvent.contexts).toEqual({
@@ -93,7 +117,7 @@ describe('ExtraErrorData()', () => {
93117
{
94118
originalException: error,
95119
},
96-
{} as any,
120+
testClient,
97121
) as SentryEvent;
98122

99123
expect(enhancedEvent.contexts).toEqual({
@@ -112,14 +136,14 @@ describe('ExtraErrorData()', () => {
112136
{
113137
originalException: error,
114138
},
115-
{} as any,
139+
testClient,
116140
) as SentryEvent;
117141

118142
expect(enhancedEvent).toEqual(event);
119143
});
120144

121145
it('should return event if there is no SentryEventHint', () => {
122-
const enhancedEvent = extraErrorData.processEvent?.(event, {}, {} as any);
146+
const enhancedEvent = extraErrorData.processEvent?.(event, {}, testClient);
123147

124148
expect(enhancedEvent).toEqual(event);
125149
});
@@ -131,7 +155,7 @@ describe('ExtraErrorData()', () => {
131155
// @ts-expect-error Allow event to have extra properties
132156
notOriginalException: 'fooled you',
133157
},
134-
{} as any,
158+
testClient,
135159
);
136160

137161
expect(enhancedEvent).toEqual(event);
@@ -153,7 +177,7 @@ describe('ExtraErrorData()', () => {
153177
{
154178
originalException: error,
155179
},
156-
{} as any,
180+
testClient,
157181
) as SentryEvent;
158182

159183
expect(enhancedEvent.contexts).toEqual({
@@ -180,7 +204,7 @@ describe('ExtraErrorData()', () => {
180204
{
181205
originalException: error,
182206
},
183-
{} as any,
207+
testClient,
184208
) as SentryEvent;
185209

186210
expect(enhancedEvent.contexts).toEqual({
@@ -204,7 +228,7 @@ describe('ExtraErrorData()', () => {
204228
{
205229
originalException: error,
206230
},
207-
{} as any,
231+
testClient,
208232
) as SentryEvent;
209233

210234
expect(enhancedEvent.contexts).toEqual({
@@ -232,7 +256,7 @@ describe('ExtraErrorData()', () => {
232256
{
233257
originalException: error,
234258
},
235-
{} as any,
259+
testClient,
236260
) as SentryEvent;
237261

238262
expect(enhancedEvent.contexts).toEqual({
@@ -261,7 +285,7 @@ describe('ExtraErrorData()', () => {
261285
{
262286
originalException: error,
263287
},
264-
{} as any,
288+
testClient,
265289
) as SentryEvent;
266290

267291
expect(enhancedEvent.contexts).not.toEqual({

0 commit comments

Comments
 (0)