or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async-utilities.mddata-processing.mdenvelopes.mdenvironment.mderror-handling.mdindex.mdinstrumentation.mdlogging.mdstack-processing.mdtype-guards.md

data-processing.mddocs/

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.