@beethovn/logging 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Beethovn Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,506 @@
1
+ # @beethovn/logging
2
+
3
+ Structured logging with correlation tracking for the Beethovn monorepo.
4
+
5
+ ## Features
6
+
7
+ - **Structured Logging**: JSON-formatted logs for easy parsing and analysis
8
+ - **Correlation Tracking**: Automatic correlation ID propagation across async operations
9
+ - **Context Management**: Track user ID, tenant ID, and custom context fields
10
+ - **Error Integration**: Seamless integration with `@beethovn/errors` package
11
+ - **Multiple Log Levels**: DEBUG, INFO, WARN, ERROR with priority filtering
12
+ - **Transport System**: Flexible output to console, files, or custom destinations
13
+ - **Child Loggers**: Create context-specific loggers with shared configuration
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ pnpm add @beethovn/logging
19
+ ```
20
+
21
+ ## Quick Start
22
+
23
+ ```typescript
24
+ import { Logger, LogLevel } from '@beethovn/logging';
25
+
26
+ const logger = new Logger({
27
+ level: LogLevel.INFO,
28
+ service: 'payment-service',
29
+ json: true,
30
+ });
31
+
32
+ logger.info('Payment processed', { paymentId: '123', amount: 100 });
33
+ ```
34
+
35
+ ## Core Concepts
36
+
37
+ ### Log Levels
38
+
39
+ ```typescript
40
+ enum LogLevel {
41
+ DEBUG = 'debug', // Detailed debugging information
42
+ INFO = 'info', // General informational messages
43
+ WARN = 'warn', // Warning messages
44
+ ERROR = 'error', // Error messages
45
+ }
46
+ ```
47
+
48
+ ### Structured Log Entry
49
+
50
+ Every log entry includes:
51
+
52
+ ```typescript
53
+ interface LogEntry {
54
+ timestamp: string; // ISO 8601 timestamp
55
+ level: LogLevel; // Log level
56
+ message: string; // Log message
57
+ service?: string; // Service name
58
+ correlationId?: string; // Request correlation ID
59
+ userId?: string; // User ID from context
60
+ tenantId?: string; // Tenant ID from context
61
+ metadata?: Record<string, unknown>; // Additional data
62
+ error?: { // Error details (if present)
63
+ name: string;
64
+ code: string;
65
+ message: string;
66
+ stack?: string;
67
+ metadata?: Record<string, unknown>;
68
+ };
69
+ }
70
+ ```
71
+
72
+ ## Usage Examples
73
+
74
+ ### Basic Logging
75
+
76
+ ```typescript
77
+ const logger = new Logger({
78
+ level: LogLevel.INFO,
79
+ service: 'user-service',
80
+ });
81
+
82
+ logger.debug('User lookup started', { userId: '123' });
83
+ logger.info('User authenticated', { userId: '123' });
84
+ logger.warn('Rate limit approaching', { remaining: 10 });
85
+ logger.error('Database connection failed');
86
+ ```
87
+
88
+ ### Error Logging
89
+
90
+ ```typescript
91
+ import { ErrorFactory } from '@beethovn/errors';
92
+
93
+ try {
94
+ await processPayment(paymentId);
95
+ } catch (error: unknown) {
96
+ const err = ErrorFactory.fromUnknown(error, 'processPayment');
97
+ logger.error('Payment processing failed', err, { paymentId });
98
+ }
99
+ ```
100
+
101
+ ### Correlation Tracking
102
+
103
+ ```typescript
104
+ import { CorrelationContextManager } from '@beethovn/logging';
105
+
106
+ // In your request handler
107
+ const correlationId = CorrelationContextManager.generateCorrelationId();
108
+
109
+ CorrelationContextManager.run(
110
+ {
111
+ correlationId,
112
+ userId: req.user.id,
113
+ tenantId: req.tenant.id,
114
+ },
115
+ async () => {
116
+ // All logs within this context automatically include correlation data
117
+ logger.info('Processing request');
118
+ await service.execute();
119
+ logger.info('Request completed');
120
+ }
121
+ );
122
+ ```
123
+
124
+ ### Child Loggers
125
+
126
+ ```typescript
127
+ const mainLogger = new Logger({ service: 'api-server' });
128
+
129
+ // Create specialized logger for payment operations
130
+ const paymentLogger = mainLogger.child({ service: 'payment-processor' });
131
+
132
+ paymentLogger.info('Payment started', { paymentId: '123' });
133
+ // Logs with service: 'payment-processor'
134
+ ```
135
+
136
+ ### Custom Transports
137
+
138
+ ```typescript
139
+ import { Logger, type LogTransport, type LogEntry } from '@beethovn/logging';
140
+
141
+ class CustomTransport implements LogTransport {
142
+ log(entry: LogEntry): void {
143
+ // Send to external logging service
144
+ externalService.send(entry);
145
+ }
146
+ }
147
+
148
+ const logger = new Logger();
149
+ logger.addTransport(new CustomTransport());
150
+ ```
151
+
152
+ ### Console Transport
153
+
154
+ ```typescript
155
+ import { Logger, ConsoleTransport } from '@beethovn/logging';
156
+
157
+ const logger = new Logger({ json: false }); // Disable default JSON output
158
+ logger.addTransport(new ConsoleTransport({
159
+ json: false, // Human-readable format
160
+ colorize: true, // ANSI color codes
161
+ }));
162
+
163
+ logger.info('User logged in', { userId: '123' });
164
+ // Output: 2024-01-01T12:00:00.000Z [INFO] user-service User logged in
165
+ // Metadata: { "userId": "123" }
166
+ ```
167
+
168
+ ## Correlation Context Manager
169
+
170
+ The `CorrelationContextManager` uses Node.js `AsyncLocalStorage` to maintain context across async operations without explicit parameter passing.
171
+
172
+ ### API
173
+
174
+ ```typescript
175
+ class CorrelationContextManager {
176
+ // Run code with correlation context
177
+ static run<T>(context: LogContext, fn: () => T): T;
178
+
179
+ // Get current context
180
+ static getContext(): LogContext | undefined;
181
+
182
+ // Get correlation ID from context
183
+ static getCorrelationId(): string | undefined;
184
+
185
+ // Get user ID from context
186
+ static getUserId(): string | undefined;
187
+
188
+ // Get tenant ID from context
189
+ static getTenantId(): string | undefined;
190
+
191
+ // Update current context
192
+ static updateContext(updates: Partial<LogContext>): void;
193
+
194
+ // Generate new correlation ID
195
+ static generateCorrelationId(): string;
196
+ }
197
+ ```
198
+
199
+ ### Express Middleware Example
200
+
201
+ ```typescript
202
+ import { CorrelationContextManager } from '@beethovn/logging';
203
+
204
+ app.use((req, res, next) => {
205
+ const correlationId =
206
+ req.headers['x-correlation-id'] as string ||
207
+ CorrelationContextManager.generateCorrelationId();
208
+
209
+ CorrelationContextManager.run(
210
+ {
211
+ correlationId,
212
+ userId: req.user?.id,
213
+ tenantId: req.tenant?.id,
214
+ },
215
+ () => next()
216
+ );
217
+ });
218
+ ```
219
+
220
+ ### Event Handler Example
221
+
222
+ ```typescript
223
+ eventBus.on('payment.created', async (event) => {
224
+ CorrelationContextManager.run(
225
+ {
226
+ correlationId: event.correlationId,
227
+ userId: event.userId,
228
+ },
229
+ async () => {
230
+ logger.info('Processing payment event', { paymentId: event.paymentId });
231
+ await processPayment(event);
232
+ logger.info('Payment event processed');
233
+ }
234
+ );
235
+ });
236
+ ```
237
+
238
+ ## Integration with @beethovn/errors
239
+
240
+ The logger automatically extracts and formats error details from `BeethovnError` instances:
241
+
242
+ ```typescript
243
+ import { ValidationError } from '@beethovn/errors';
244
+
245
+ const error = new ValidationError('Invalid email format', 'email');
246
+ logger.error('Validation failed', error, { userId: '123' });
247
+
248
+ // Log output includes:
249
+ // {
250
+ // "level": "error",
251
+ // "message": "Validation failed",
252
+ // "error": {
253
+ // "name": "ValidationError",
254
+ // "code": "VALIDATION_ERROR",
255
+ // "message": "Invalid email format",
256
+ // "stack": "...",
257
+ // "metadata": { "field": "email" }
258
+ // },
259
+ // "metadata": { "userId": "123" }
260
+ // }
261
+ ```
262
+
263
+ ## Configuration
264
+
265
+ ### Logger Config
266
+
267
+ ```typescript
268
+ interface LoggerConfig {
269
+ level: LogLevel; // Minimum log level (default: INFO)
270
+ service: string; // Service name (default: 'beethovn')
271
+ json: boolean; // JSON output format (default: true)
272
+ timestamps: boolean; // Include timestamps (default: true)
273
+ colorize: boolean; // ANSI color codes (default: false)
274
+ }
275
+ ```
276
+
277
+ ### Log Context
278
+
279
+ ```typescript
280
+ interface LogContext {
281
+ correlationId?: string; // Request correlation ID
282
+ userId?: string; // Authenticated user ID
283
+ tenantId?: string; // Multi-tenant ID
284
+ service?: string; // Service name override
285
+ [key: string]: unknown; // Custom fields
286
+ }
287
+ ```
288
+
289
+ ## Best Practices
290
+
291
+ ### 1. Use Appropriate Log Levels
292
+
293
+ ```typescript
294
+ logger.debug('Cache hit', { key }); // Development debugging
295
+ logger.info('User registered', { userId }); // Business events
296
+ logger.warn('Cache miss', { key }); // Potential issues
297
+ logger.error('Database error', err); // Errors requiring attention
298
+ ```
299
+
300
+ ### 2. Include Structured Metadata
301
+
302
+ ```typescript
303
+ // ✅ Good: Structured metadata
304
+ logger.info('Order placed', {
305
+ orderId: '123',
306
+ userId: '456',
307
+ total: 99.99,
308
+ items: 3,
309
+ });
310
+
311
+ // ❌ Bad: Unstructured string
312
+ logger.info(`Order 123 placed by user 456 for $99.99`);
313
+ ```
314
+
315
+ ### 3. Always Use Correlation Context
316
+
317
+ ```typescript
318
+ // ✅ Good: Context-wrapped handler
319
+ app.post('/orders', (req, res) => {
320
+ CorrelationContextManager.run(
321
+ {
322
+ correlationId: req.headers['x-correlation-id'] || generateId(),
323
+ userId: req.user.id,
324
+ },
325
+ async () => {
326
+ await createOrder(req.body);
327
+ }
328
+ );
329
+ });
330
+
331
+ // ❌ Bad: No correlation tracking
332
+ app.post('/orders', async (req, res) => {
333
+ await createOrder(req.body);
334
+ });
335
+ ```
336
+
337
+ ### 4. Create Service-Specific Loggers
338
+
339
+ ```typescript
340
+ // ✅ Good: Service-specific logger
341
+ const paymentLogger = new Logger({ service: 'payment-service' });
342
+
343
+ // ❌ Bad: Generic logger everywhere
344
+ const logger = new Logger({ service: 'app' });
345
+ ```
346
+
347
+ ### 5. Log Errors with Context
348
+
349
+ ```typescript
350
+ // ✅ Good: Error with context
351
+ try {
352
+ await operation();
353
+ } catch (error: unknown) {
354
+ const err = ErrorFactory.fromUnknown(error);
355
+ logger.error('Operation failed', err, { operationId, userId });
356
+ }
357
+
358
+ // ❌ Bad: Generic error log
359
+ try {
360
+ await operation();
361
+ } catch (error) {
362
+ logger.error('Error occurred', error);
363
+ }
364
+ ```
365
+
366
+ ## Log Output Examples
367
+
368
+ ### JSON Output (Default)
369
+
370
+ ```json
371
+ {
372
+ "timestamp": "2024-01-01T12:00:00.000Z",
373
+ "level": "info",
374
+ "message": "Payment processed",
375
+ "service": "payment-service",
376
+ "correlationId": "cor-1704110400000-a1b2c3d4",
377
+ "userId": "user-123",
378
+ "tenantId": "tenant-456",
379
+ "metadata": {
380
+ "paymentId": "pay-789",
381
+ "amount": 99.99,
382
+ "currency": "USD"
383
+ }
384
+ }
385
+ ```
386
+
387
+ ### Formatted Output
388
+
389
+ ```
390
+ 2024-01-01T12:00:00.000Z [INFO] payment-service (cor-1704110400000-a1b2c3d4) Payment processed
391
+ Metadata: {
392
+ "paymentId": "pay-789",
393
+ "amount": 99.99,
394
+ "currency": "USD"
395
+ }
396
+ ```
397
+
398
+ ### Error Output
399
+
400
+ ```json
401
+ {
402
+ "timestamp": "2024-01-01T12:00:00.000Z",
403
+ "level": "error",
404
+ "message": "Payment processing failed",
405
+ "service": "payment-service",
406
+ "correlationId": "cor-1704110400000-a1b2c3d4",
407
+ "metadata": {
408
+ "paymentId": "pay-789"
409
+ },
410
+ "error": {
411
+ "name": "DatabaseError",
412
+ "code": "DATABASE_ERROR",
413
+ "message": "Connection timeout",
414
+ "stack": "DatabaseError: Connection timeout\n at ...",
415
+ "metadata": {
416
+ "operation": "insert",
417
+ "table": "payments"
418
+ }
419
+ }
420
+ }
421
+ ```
422
+
423
+ ## Testing
424
+
425
+ ```typescript
426
+ import { describe, it, expect, vi } from 'vitest';
427
+ import { Logger, LogLevel } from '@beethovn/logging';
428
+
429
+ describe('MyService', () => {
430
+ it('should log operations', () => {
431
+ const logger = new Logger({ json: true });
432
+ const logSpy = vi.spyOn(console, 'log');
433
+
434
+ logger.info('Operation completed', { id: '123' });
435
+
436
+ expect(logSpy).toHaveBeenCalledWith(
437
+ expect.stringContaining('"message":"Operation completed"')
438
+ );
439
+ });
440
+ });
441
+ ```
442
+
443
+ ## Migration Guide
444
+
445
+ ### From console.log
446
+
447
+ ```typescript
448
+ // Before
449
+ console.log('User logged in:', userId);
450
+
451
+ // After
452
+ logger.info('User logged in', { userId });
453
+ ```
454
+
455
+ ### From winston/bunyan
456
+
457
+ ```typescript
458
+ // Before (winston)
459
+ const logger = winston.createLogger({
460
+ transports: [new winston.transports.Console()],
461
+ });
462
+
463
+ // After
464
+ const logger = new Logger({
465
+ service: 'my-service',
466
+ });
467
+ logger.addTransport(new ConsoleTransport());
468
+ ```
469
+
470
+ ## Performance Considerations
471
+
472
+ - Log level filtering happens before serialization (zero overhead for filtered logs)
473
+ - JSON serialization only occurs for logs that will be output
474
+ - Correlation context uses `AsyncLocalStorage` (minimal overhead)
475
+ - Child loggers share transports (no duplication)
476
+
477
+ ## TypeScript Support
478
+
479
+ Full TypeScript support with strict types:
480
+
481
+ ```typescript
482
+ import type { LogEntry, LogContext, LoggerConfig } from '@beethovn/logging';
483
+
484
+ const config: LoggerConfig = {
485
+ level: LogLevel.INFO,
486
+ service: 'my-service',
487
+ json: true,
488
+ timestamps: true,
489
+ colorize: false,
490
+ };
491
+
492
+ const context: LogContext = {
493
+ correlationId: 'cor-123',
494
+ userId: 'user-456',
495
+ };
496
+ ```
497
+
498
+ ## License
499
+
500
+ MIT
501
+
502
+ ---
503
+
504
+ **Package Version:** 1.0.0
505
+ **Dependencies:** @beethovn/errors
506
+ **Node Version:** >= 18.0.0
@@ -0,0 +1,83 @@
1
+ import type { LogContext } from './types.js';
2
+ /**
3
+ * Manages correlation context across async operations
4
+ *
5
+ * Uses Node.js AsyncLocalStorage to maintain context without
6
+ * explicitly passing it through every function call.
7
+ */
8
+ export declare class CorrelationContextManager {
9
+ private static storage;
10
+ /**
11
+ * Run a function with a specific correlation context
12
+ *
13
+ * @param context - The context to set
14
+ * @param fn - The function to run with this context
15
+ * @returns The result of the function
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * await CorrelationContextManager.run(
20
+ * { correlationId: 'req-123', userId: 'user-456' },
21
+ * async () => {
22
+ * // This and all nested async calls will have access to the context
23
+ * await processRequest();
24
+ * }
25
+ * );
26
+ * ```
27
+ */
28
+ static run<T>(context: LogContext, fn: () => T): T;
29
+ /**
30
+ * Get the current correlation context
31
+ *
32
+ * @returns The current context or undefined if not in a context
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * const context = CorrelationContextManager.getContext();
37
+ * console.log(context?.correlationId); // 'req-123'
38
+ * ```
39
+ */
40
+ static getContext(): LogContext | undefined;
41
+ /**
42
+ * Get correlation ID from current context
43
+ *
44
+ * @returns Correlation ID or undefined
45
+ */
46
+ static getCorrelationId(): string | undefined;
47
+ /**
48
+ * Get user ID from current context
49
+ *
50
+ * @returns User ID or undefined
51
+ */
52
+ static getUserId(): string | undefined;
53
+ /**
54
+ * Get tenant ID from current context
55
+ *
56
+ * @returns Tenant ID or undefined
57
+ */
58
+ static getTenantId(): string | undefined;
59
+ /**
60
+ * Update the current context with new values
61
+ *
62
+ * @param updates - Partial context to merge with current
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * CorrelationContextManager.updateContext({ userId: 'user-789' });
67
+ * ```
68
+ */
69
+ static updateContext(updates: Partial<LogContext>): void;
70
+ /**
71
+ * Generate a new correlation ID
72
+ *
73
+ * @returns A new correlation ID in format: cor-{timestamp}-{random}
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * const id = CorrelationContextManager.generateCorrelationId();
78
+ * // 'cor-1704240000000-a1b2c3d4'
79
+ * ```
80
+ */
81
+ static generateCorrelationId(): string;
82
+ }
83
+ //# sourceMappingURL=CorrelationContextManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CorrelationContextManager.d.ts","sourceRoot":"","sources":["../../src/core/CorrelationContextManager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;;GAKG;AACH,qBAAa,yBAAyB;IACpC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAuC;IAE7D;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC;IAIlD;;;;;;;;;;OAUG;IACH,MAAM,CAAC,UAAU,IAAI,UAAU,GAAG,SAAS;IAI3C;;;;OAIG;IACH,MAAM,CAAC,gBAAgB,IAAI,MAAM,GAAG,SAAS;IAI7C;;;;OAIG;IACH,MAAM,CAAC,SAAS,IAAI,MAAM,GAAG,SAAS;IAItC;;;;OAIG;IACH,MAAM,CAAC,WAAW,IAAI,MAAM,GAAG,SAAS;IAIxC;;;;;;;;;OASG;IACH,MAAM,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,IAAI;IAOxD;;;;;;;;;;OAUG;IACH,MAAM,CAAC,qBAAqB,IAAI,MAAM;CAKvC"}
@@ -0,0 +1,102 @@
1
+ import { AsyncLocalStorage } from 'node:async_hooks';
2
+ /**
3
+ * Manages correlation context across async operations
4
+ *
5
+ * Uses Node.js AsyncLocalStorage to maintain context without
6
+ * explicitly passing it through every function call.
7
+ */
8
+ export class CorrelationContextManager {
9
+ static storage = new AsyncLocalStorage();
10
+ /**
11
+ * Run a function with a specific correlation context
12
+ *
13
+ * @param context - The context to set
14
+ * @param fn - The function to run with this context
15
+ * @returns The result of the function
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * await CorrelationContextManager.run(
20
+ * { correlationId: 'req-123', userId: 'user-456' },
21
+ * async () => {
22
+ * // This and all nested async calls will have access to the context
23
+ * await processRequest();
24
+ * }
25
+ * );
26
+ * ```
27
+ */
28
+ static run(context, fn) {
29
+ return this.storage.run(context, fn);
30
+ }
31
+ /**
32
+ * Get the current correlation context
33
+ *
34
+ * @returns The current context or undefined if not in a context
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * const context = CorrelationContextManager.getContext();
39
+ * console.log(context?.correlationId); // 'req-123'
40
+ * ```
41
+ */
42
+ static getContext() {
43
+ return this.storage.getStore();
44
+ }
45
+ /**
46
+ * Get correlation ID from current context
47
+ *
48
+ * @returns Correlation ID or undefined
49
+ */
50
+ static getCorrelationId() {
51
+ return this.getContext()?.correlationId;
52
+ }
53
+ /**
54
+ * Get user ID from current context
55
+ *
56
+ * @returns User ID or undefined
57
+ */
58
+ static getUserId() {
59
+ return this.getContext()?.userId;
60
+ }
61
+ /**
62
+ * Get tenant ID from current context
63
+ *
64
+ * @returns Tenant ID or undefined
65
+ */
66
+ static getTenantId() {
67
+ return this.getContext()?.tenantId;
68
+ }
69
+ /**
70
+ * Update the current context with new values
71
+ *
72
+ * @param updates - Partial context to merge with current
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * CorrelationContextManager.updateContext({ userId: 'user-789' });
77
+ * ```
78
+ */
79
+ static updateContext(updates) {
80
+ const current = this.getContext();
81
+ if (current) {
82
+ Object.assign(current, updates);
83
+ }
84
+ }
85
+ /**
86
+ * Generate a new correlation ID
87
+ *
88
+ * @returns A new correlation ID in format: cor-{timestamp}-{random}
89
+ *
90
+ * @example
91
+ * ```typescript
92
+ * const id = CorrelationContextManager.generateCorrelationId();
93
+ * // 'cor-1704240000000-a1b2c3d4'
94
+ * ```
95
+ */
96
+ static generateCorrelationId() {
97
+ const timestamp = Date.now();
98
+ const random = Math.random().toString(36).substring(2, 10);
99
+ return `cor-${timestamp}-${random}`;
100
+ }
101
+ }
102
+ //# sourceMappingURL=CorrelationContextManager.js.map