0
# Data Normalization & Processing
1
2
**DEPRECATED**: Import all functions from `@sentry/core` instead of `@sentry/utils`.
3
4
Data normalization and serialization utilities for preparing data structures for transmission, debugging, and storage while handling circular references and deep objects.
5
6
## Capabilities
7
8
### Core Normalization
9
10
Primary functions for normalizing complex data structures.
11
12
```typescript { .api }
13
/**
14
* Normalizes any input to a JSON-serializable format with depth and property limits
15
* @param input - Any input value to normalize
16
* @param depth - Maximum depth to traverse (default: 3)
17
* @param maxProperties - Maximum number of properties to include (default: 1000)
18
* @returns Normalized, JSON-serializable version of the input
19
*/
20
function normalize(input: any, depth?: number, maxProperties?: number): any;
21
22
/**
23
* Normalizes an object to fit within specified size constraints
24
* @param object - Object to normalize
25
* @param minSize - Minimum size in characters (default: 1024)
26
* @param maxSize - Maximum size in characters (default: 64 * 1024)
27
* @returns Normalized object that fits within size constraints
28
*/
29
function normalizeToSize(
30
object: { [key: string]: any },
31
minSize?: number,
32
maxSize?: number,
33
): { [key: string]: any };
34
```
35
36
**Usage Examples:**
37
38
```typescript
39
import { normalize, normalizeToSize } from "@sentry/core";
40
41
// Basic normalization with circular reference handling
42
const circularObj = { name: 'test' };
43
circularObj.self = circularObj;
44
45
const normalized = normalize(circularObj, 2);
46
// Result: { name: 'test', self: '[Circular ~]' }
47
48
// Size-constrained normalization for transmission
49
const largeObject = {
50
users: Array(1000).fill(0).map((_, i) => ({
51
id: i,
52
name: `User ${i}`,
53
data: 'x'.repeat(100)
54
}))
55
};
56
57
const constrained = normalizeToSize(largeObject, 1024, 8192);
58
// Result: Truncated version that fits within 8KB
59
```
60
61
### Object Manipulation
62
63
Functions for manipulating and transforming object structures.
64
65
```typescript { .api }
66
/**
67
* Converts any input to a plain object format
68
* @param input - Input value to convert
69
* @returns Plain object representation
70
*/
71
function convertToPlainObject(input: any): PlainObject;
72
73
/**
74
* Removes all properties with undefined values from an object
75
* @param inputValue - Object to clean
76
* @returns Object with undefined properties removed
77
*/
78
function dropUndefinedKeys(inputValue: { [key: string]: any }): { [key: string]: any };
79
80
/**
81
* Adds a non-enumerable property to an object
82
* @param obj - Target object
83
* @param name - Property name
84
* @param value - Property value
85
*/
86
function addNonEnumerableProperty(obj: any, name: string, value: any): void;
87
88
/**
89
* Converts any value to an object representation
90
* @param wat - Value to objectify
91
* @returns Object representation of the value
92
*/
93
function objectify(wat: unknown): { [key: string]: any };
94
```
95
96
**Usage Examples:**
97
98
```typescript
99
import {
100
convertToPlainObject,
101
dropUndefinedKeys,
102
addNonEnumerableProperty,
103
objectify
104
} from "@sentry/core";
105
106
// Convert complex objects to plain objects
107
class CustomError extends Error {
108
code = 'CUSTOM_ERROR';
109
details = { severity: 'high' };
110
}
111
112
const error = new CustomError('Something failed');
113
const plainError = convertToPlainObject(error);
114
// Result: { name: 'CustomError', message: 'Something failed', code: 'CUSTOM_ERROR', details: {...} }
115
116
// Clean up API response data
117
const apiResponse = {
118
id: 123,
119
name: 'John',
120
email: undefined,
121
phone: null,
122
address: undefined
123
};
124
125
const cleaned = dropUndefinedKeys(apiResponse);
126
// Result: { id: 123, name: 'John', phone: null }
127
128
// Add metadata without affecting enumeration
129
const data = { user: 'john', action: 'login' };
130
addNonEnumerableProperty(data, '__metadata', { timestamp: Date.now() });
131
132
console.log(Object.keys(data)); // ['user', 'action'] - metadata not included
133
console.log(data.__metadata); // { timestamp: ... } - but still accessible
134
135
// Convert various types to objects for consistent handling
136
console.log(objectify('hello')); // { '0': 'h', '1': 'e', '2': 'l', '3': 'l', '4': 'o' }
137
console.log(objectify([1, 2, 3])); // { '0': 1, '1': 2, '2': 3 }
138
console.log(objectify(null)); // {}
139
```
140
141
### Array Processing
142
143
Utilities for array manipulation and normalization.
144
145
```typescript { .api }
146
/**
147
* Converts any value to an array
148
* @param wat - Value to convert to array
149
* @returns Array representation of the value
150
*/
151
function arrayify(wat: unknown): any[];
152
153
/**
154
* Flattens nested arrays to a single level
155
* @param arr - Array to flatten (can contain nested arrays)
156
* @returns Flattened array
157
*/
158
function flatten<T>(arr: ReadonlyArray<T | ReadonlyArray<T>>): T[];
159
```
160
161
**Usage Examples:**
162
163
```typescript
164
import { arrayify, flatten } from "@sentry/core";
165
166
// Convert various types to arrays
167
console.log(arrayify('hello')); // ['hello']
168
console.log(arrayify(42)); // [42]
169
console.log(arrayify([1, 2, 3])); // [1, 2, 3]
170
console.log(arrayify(null)); // []
171
172
// Flatten nested arrays
173
const nested = [1, [2, 3], [4, [5, 6]], 7];
174
const flattened = flatten(nested);
175
// Result: [1, 2, 3, 4, 5, 6, 7]
176
177
// Practical use case: processing form data
178
function processFormFields(fields: unknown): string[] {
179
const fieldArray = arrayify(fields);
180
const flattened = flatten(fieldArray);
181
return flattened.map(field => String(field));
182
}
183
```
184
185
### String Processing
186
187
Utilities for string manipulation and normalization.
188
189
```typescript { .api }
190
/**
191
* Truncates a string to a maximum length with ellipsis
192
* @param str - String to truncate
193
* @param max - Maximum length (default: Infinity)
194
* @returns Truncated string with ellipsis if needed
195
*/
196
function truncate(str: string, max?: number): string;
197
198
/**
199
* Safely joins array elements with a separator, handling various types
200
* @param arr - Array to join
201
* @param separator - Separator string (default: ', ')
202
* @returns Joined string
203
*/
204
function safeJoin(arr: any[], separator?: string): string;
205
206
/**
207
* Extracts exception keys for creating error messages
208
* @param ex - Exception object
209
* @returns String representation of exception keys
210
*/
211
function extractExceptionKeysForMessage(ex: Exception): string;
212
213
/**
214
* Escapes a string for safe use in regular expressions
215
* @param str - String to escape
216
* @returns Escaped string safe for RegExp constructor
217
*/
218
function escapeStringForRegex(str: string): string;
219
```
220
221
**Usage Examples:**
222
223
```typescript
224
import {
225
truncate,
226
safeJoin,
227
escapeStringForRegex
228
} from "@sentry/core";
229
230
// Truncate long strings for display
231
const longMessage = 'This is a very long error message that should be truncated';
232
const short = truncate(longMessage, 50);
233
// Result: 'This is a very long error message that should...'
234
235
// Safe array joining with mixed types
236
const mixedArray = ['hello', 42, null, undefined, { name: 'object' }];
237
const joined = safeJoin(mixedArray, ' | ');
238
// Result: 'hello | 42 | null | undefined | [object Object]'
239
240
// Escape user input for regex
241
const userSearch = 'user@example.com (primary)';
242
const escapedPattern = escapeStringForRegex(userSearch);
243
const regex = new RegExp(escapedPattern, 'i');
244
```
245
246
## Data Processing Patterns
247
248
### Event Data Preparation
249
250
Typical workflow for preparing event data for transmission:
251
252
```typescript
253
import {
254
normalize,
255
normalizeToSize,
256
dropUndefinedKeys,
257
truncate
258
} from "@sentry/core";
259
260
function prepareEventData(rawEvent: any): any {
261
// Step 1: Clean up undefined values
262
let event = dropUndefinedKeys(rawEvent);
263
264
// Step 2: Normalize complex structures and handle circular references
265
event = normalize(event, 5, 1000);
266
267
// Step 3: Truncate long strings
268
if (event.message) {
269
event.message = truncate(event.message, 1000);
270
}
271
272
// Step 4: Ensure final size constraints
273
event = normalizeToSize(event, 1024, 64 * 1024);
274
275
return event;
276
}
277
```
278
279
### Safe Object Processing
280
281
Pattern for safely processing unknown objects:
282
283
```typescript
284
import {
285
convertToPlainObject,
286
isPlainObject,
287
objectify
288
} from "@sentry/core";
289
290
function safeObjectProcessor(input: unknown): Record<string, any> {
291
// Convert to plain object for safe processing
292
const plainObj = convertToPlainObject(input);
293
294
// Ensure we have a plain object to work with
295
if (!isPlainObject(plainObj)) {
296
return objectify(plainObj);
297
}
298
299
return plainObj;
300
}
301
```
302
303
### Data Serialization Pipeline
304
305
Complete pipeline for serializing complex data:
306
307
```typescript
308
import {
309
normalize,
310
flatten,
311
arrayify,
312
truncate,
313
safeJoin
314
} from "@sentry/core";
315
316
function createSerializationPipeline() {
317
return {
318
// Step 1: Normalize structure
319
normalize: (data: any) => normalize(data, 3, 500),
320
321
// Step 2: Flatten arrays if needed
322
flattenArrays: (data: any) => {
323
if (Array.isArray(data)) {
324
return flatten(arrayify(data));
325
}
326
return data;
327
},
328
329
// Step 3: Truncate strings
330
truncateStrings: (data: any) => {
331
if (typeof data === 'string') {
332
return truncate(data, 500);
333
}
334
if (Array.isArray(data)) {
335
return data.map(item =>
336
typeof item === 'string' ? truncate(item, 500) : item
337
);
338
}
339
return data;
340
},
341
342
// Step 4: Create final string representation
343
stringify: (data: any) => {
344
if (Array.isArray(data)) {
345
return safeJoin(data, ', ');
346
}
347
return JSON.stringify(data);
348
}
349
};
350
}
351
```
352
353
## Types
354
355
```typescript { .api }
356
interface PlainObject {
357
[key: string]: any;
358
}
359
360
type Primitive =
361
| null
362
| undefined
363
| string
364
| number
365
| boolean
366
| symbol
367
| bigint;
368
```
369
370
**Migration Note**: All data processing functions have been moved from `@sentry/utils` to `@sentry/core`. Update your imports accordingly.