unnbound-logger-sdk 2.0.3 → 2.0.5

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/README.md CHANGED
@@ -48,12 +48,14 @@ All logs follow a standardized format:
48
48
 
49
49
  ```typescript
50
50
  interface Log<T extends LogType = 'general'> {
51
+ logId: string; // Unique identifier for each log entry
51
52
  level: LogLevel; // "info" | "debug" | "error" | "warn"
52
53
  type: T; // "general" | "httpRequest" | "httpResponse" | "sftpTransaction" | "dbQueryTransaction"
53
54
  message: string;
55
+ workflowId: string; // Workflow tracking (empty string if not set)
54
56
  traceId: string;
55
57
  requestId: string;
56
- deploymentId: string; // Automatically populated from DEPLOYMENT_ID environment variable
58
+ deploymentId: string; // Automatically populated from UNNBOUND_DEPLOYMENT_ID
57
59
  error?: SerializableError; // Only present for Error objects
58
60
  }
59
61
 
@@ -62,24 +64,44 @@ interface LogTransaction<T extends LogType> extends Log<T> {
62
64
  }
63
65
  ```
64
66
 
65
- ## Deployment Tracking
67
+ ## Workflow and Deployment Tracking
66
68
 
67
- The logger automatically includes a `deploymentId` field in all log entries. This field is populated from the `DEPLOYMENT_ID` environment variable, allowing you to track logs across different deployments of your application.
69
+ ### Workflow Tracking
70
+
71
+ The logger includes a `workflowId` field in all log entries for tracking operations across services:
72
+
73
+ ```bash
74
+ # Set the workflow ID in your environment
75
+ export UNNBOUND_WORKFLOW_ID="order-processing-12345"
76
+
77
+ # Or in your deployment configuration
78
+ UNNBOUND_WORKFLOW_ID=order-processing-12345
79
+ ```
80
+
81
+ ```typescript
82
+ // Create a logger - workflowId is automatically set from environment
83
+ const logger = new UnnboundLogger();
84
+ // All logs will include the workflowId from UNNBOUND_WORKFLOW_ID environment variable
85
+ ```
86
+
87
+ ### Deployment Tracking
88
+
89
+ The logger automatically includes a `deploymentId` field in all log entries. This field is populated from the `UNNBOUND_DEPLOYMENT_ID` environment variable, allowing you to track logs per deployment.
68
90
 
69
91
  ```bash
70
92
  # Set the deployment ID in your environment
71
- export DEPLOYMENT_ID="v1.2.3-prod-20231201"
93
+ export UNNBOUND_DEPLOYMENT_ID="v1.2.3-prod-20231201"
72
94
 
73
95
  # Or in your deployment configuration
74
- DEPLOYMENT_ID=v1.2.3-prod-20231201
96
+ UNNBOUND_DEPLOYMENT_ID=v1.2.3-prod-20231201
75
97
  ```
76
98
 
77
- If the `DEPLOYMENT_ID` environment variable is not set, the `deploymentId` field will be an empty string. This field helps with:
99
+ If the environment variables are not set, the fields will be empty strings. These fields help with:
78
100
 
79
- - Tracking logs across different application deployments
80
- - Correlating issues with specific releases
81
- - Monitoring deployment health and performance
82
- - Debugging problems in specific deployment versions
101
+ - **Workflow ID**: Unique identifier for the workflow
102
+ - **Deployment ID**: Tracking logs across different application deployments
103
+ - **Correlating issues**: Link problems to specific workflows and releases
104
+ - **Monitoring**: Track health and performance across workflows and deployments
83
105
 
84
106
  ## HTTP Request/Response Logging
85
107
 
@@ -326,6 +348,13 @@ The main logger class that provides all logging functionality using Pino.
326
348
  new UnnboundLogger(options?: LoggerOptions)
327
349
  ```
328
350
 
351
+ **LoggerOptions:**
352
+ - `traceHeaderKey?: string` - Custom trace header name (default: 'unnbound-trace-id')
353
+ - `ignoreTraceRoutes?: string[]` - Routes to ignore in Express middleware
354
+ - `ignoreAxiosTraceRoutes?: string[]` - Routes to ignore in Axios middleware
355
+
356
+ **Note:** `workflowId` and `deploymentId` are configured via environment variables (`UNNBOUND_WORKFLOW_ID`, `UNNBOUND_DEPLOYMENT_ID`).
357
+
329
358
  #### Methods
330
359
 
331
360
  - `log(level: LogLevel, message: string | Error | Record<string, unknown>, options?: GeneralLogOptions): void`
package/dist/types.d.ts CHANGED
@@ -19,10 +19,12 @@ export interface SerializableError {
19
19
  stack?: string;
20
20
  }
21
21
  export interface Log<T extends LogType = 'general'> {
22
+ logId: string;
22
23
  level: LogLevel;
23
24
  type: T;
24
25
  message: string;
25
26
  deploymentId: string;
27
+ workflowId: string;
26
28
  traceId: string;
27
29
  requestId: string;
28
30
  error?: SerializableError;
@@ -75,12 +77,6 @@ export interface DbQueryTransactionLog extends LogTransaction<'dbQueryTransactio
75
77
  * Configuration options for the logger
76
78
  */
77
79
  export interface LoggerOptions {
78
- /** Default log level */
79
- defaultLevel?: LogLevel;
80
- /** Optional service name to include in logs */
81
- serviceName?: string;
82
- /** Optional environment name to include in logs */
83
- environment?: string;
84
80
  /** Optional trace header key */
85
81
  traceHeaderKey?: string;
86
82
  /** Routes to ignore in trace middleware (supports glob patterns) */
@@ -14,9 +14,7 @@ declare module 'axios' {
14
14
  */
15
15
  export declare class UnnboundLogger {
16
16
  private logger;
17
- private defaultLevel;
18
- private serviceName?;
19
- private environment?;
17
+ private workflowId;
20
18
  private deploymentId;
21
19
  private traceHeaderKey;
22
20
  private ignoreTraceRoutes;
@@ -168,20 +168,15 @@ class UnnboundLogger {
168
168
  return Promise.reject(error);
169
169
  }
170
170
  };
171
- this.defaultLevel = options.defaultLevel || 'info';
172
- this.serviceName = options.serviceName;
173
- this.environment = options.environment;
174
- this.deploymentId = process.env.DEPLOYMENT_ID || '';
171
+ this.workflowId = process.env.UNNBOUND_WORKFLOW_ID || '';
172
+ this.deploymentId = process.env.UNNBOUND_DEPLOYMENT_ID || '';
175
173
  this.traceHeaderKey = options.traceHeaderKey || 'unnbound-trace-id';
176
174
  this.ignoreTraceRoutes = options.ignoreTraceRoutes || [];
177
175
  this.ignoreAxiosTraceRoutes = options.ignoreAxiosTraceRoutes || [];
178
176
  // Create Pino logger
179
177
  this.logger = (0, pino_1.default)({
180
- level: this.defaultLevel,
181
- base: {
182
- ...(this.serviceName && { service: this.serviceName }),
183
- ...(this.environment && { environment: this.environment }),
184
- },
178
+ level: 'info',
179
+ base: {}, // Disable all default base fields (pid, hostname)
185
180
  timestamp: false, // Let CloudWatch handle timestamps
186
181
  formatters: {
187
182
  level: (label) => {
@@ -214,10 +209,19 @@ class UnnboundLogger {
214
209
  * @param options - Additional logging options
215
210
  */
216
211
  log(level, message, options = {}) {
212
+ const logId = (0, uuid_1.v4)();
217
213
  const traceId = options.traceId || trace_context_1.traceContext.getTraceId() || (0, uuid_1.v4)();
218
214
  const requestId = options.requestId || (0, uuid_1.v4)();
219
215
  let logEntry;
220
216
  const { traceId: optionTraceId, requestId: optionRequestId, ...restOptions } = options;
217
+ const baseEntry = {
218
+ logId,
219
+ type: 'general',
220
+ workflowId: this.workflowId,
221
+ traceId,
222
+ requestId,
223
+ deploymentId: this.deploymentId,
224
+ };
221
225
  if (message instanceof Error) {
222
226
  const error = {
223
227
  name: message.name,
@@ -225,10 +229,7 @@ class UnnboundLogger {
225
229
  stack: message.stack,
226
230
  };
227
231
  logEntry = {
228
- type: 'general',
229
- traceId,
230
- requestId,
231
- deploymentId: this.deploymentId,
232
+ ...baseEntry,
232
233
  message: message.name,
233
234
  error,
234
235
  ...restOptions,
@@ -236,10 +237,7 @@ class UnnboundLogger {
236
237
  }
237
238
  else if (typeof message === 'string') {
238
239
  logEntry = {
239
- type: 'general',
240
- traceId,
241
- requestId,
242
- deploymentId: this.deploymentId,
240
+ ...baseEntry,
243
241
  message,
244
242
  ...restOptions,
245
243
  };
@@ -247,10 +245,7 @@ class UnnboundLogger {
247
245
  else {
248
246
  // If message is an object, it's part of the log entry
249
247
  logEntry = {
250
- type: 'general',
251
- traceId,
252
- requestId,
253
- deploymentId: this.deploymentId,
248
+ ...baseEntry,
254
249
  ...message,
255
250
  message: message.message || 'Structured log data',
256
251
  ...restOptions,
@@ -319,6 +314,7 @@ class UnnboundLogger {
319
314
  * @returns The request ID for correlating with the response
320
315
  */
321
316
  httpRequest(req, options = {}) {
317
+ const logId = (0, uuid_1.v4)();
322
318
  const traceId = options.traceId || trace_context_1.traceContext.getTraceId() || (0, uuid_1.v4)();
323
319
  const requestId = options.requestId || (0, uuid_1.v4)();
324
320
  const startTime = options.startTime || Date.now();
@@ -327,10 +323,13 @@ class UnnboundLogger {
327
323
  req.res.locals.requestId = requestId;
328
324
  req.res.locals.startTime = startTime;
329
325
  req.res.locals.traceId = traceId;
326
+ req.res.locals.workflowId = this.workflowId;
330
327
  }
331
328
  const logEntry = {
329
+ logId,
332
330
  type: 'httpRequest',
333
331
  message: req.ip === 'outgoing' ? 'Outgoing HTTP Request' : 'Incoming HTTP Request',
332
+ workflowId: this.workflowId,
334
333
  traceId,
335
334
  requestId,
336
335
  deploymentId: this.deploymentId,
@@ -343,7 +342,7 @@ class UnnboundLogger {
343
342
  body: (0, logger_utils_1.safeJsonParse)(req.body),
344
343
  },
345
344
  };
346
- this.logger[options.level || 'info'](logEntry);
345
+ this.log(options.level || 'info', logEntry);
347
346
  return requestId;
348
347
  }
349
348
  /**
@@ -353,12 +352,14 @@ class UnnboundLogger {
353
352
  * @param options - Additional logging options
354
353
  */
355
354
  httpResponse(res, req, options = {}) {
355
+ const logId = (0, uuid_1.v4)();
356
356
  const requestId = res.locals.requestId || options.requestId || (0, uuid_1.v4)();
357
357
  const startTime = res.locals.startTime || options.startTime || Date.now();
358
+ const workflowId = res.locals.workflowId || this.workflowId;
358
359
  const traceId = res.locals.traceId || options.traceId || trace_context_1.traceContext.getTraceId() || (0, uuid_1.v4)();
359
360
  const duration = options.duration || (Date.now() - startTime);
360
361
  // Determine log level based on status code
361
- let level = options.level || this.defaultLevel;
362
+ let level = options.level || 'info';
362
363
  if (!options.level) {
363
364
  if (res.statusCode >= 400) {
364
365
  level = 'error';
@@ -368,8 +369,10 @@ class UnnboundLogger {
368
369
  }
369
370
  }
370
371
  const logEntry = {
372
+ logId,
371
373
  type: 'httpResponse',
372
374
  message: (0, http_status_messages_1.getStatusMessage)(res.statusCode),
375
+ workflowId: workflowId || '',
373
376
  traceId,
374
377
  requestId,
375
378
  deploymentId: this.deploymentId,
@@ -383,7 +386,7 @@ class UnnboundLogger {
383
386
  body: (0, logger_utils_1.safeJsonParse)(res.locals.body),
384
387
  },
385
388
  };
386
- this.logger[level](logEntry);
389
+ this.log(level, logEntry);
387
390
  }
388
391
  /**
389
392
  * Logs an SFTP transaction
@@ -391,20 +394,23 @@ class UnnboundLogger {
391
394
  * @param options - Additional logging options
392
395
  */
393
396
  sftpTransaction(operation, options = {}) {
397
+ const logId = (0, uuid_1.v4)();
394
398
  const traceId = options.traceId || trace_context_1.traceContext.getTraceId() || (0, uuid_1.v4)();
395
399
  const requestId = options.requestId || (0, uuid_1.v4)();
396
400
  const duration = options.duration || (options.startTime ? Date.now() - options.startTime : 0);
397
401
  const level = operation.status === 'success' ? 'info' : 'error';
398
402
  const logEntry = {
403
+ logId,
399
404
  type: 'sftpTransaction',
400
405
  message: `SFTP ${operation.operation} ${operation.status} - ${operation.path}`,
406
+ workflowId: this.workflowId,
401
407
  traceId,
402
408
  requestId,
403
409
  deploymentId: this.deploymentId,
404
410
  duration,
405
411
  sftp: operation,
406
412
  };
407
- this.logger[level](logEntry);
413
+ this.log(level, logEntry);
408
414
  }
409
415
  /**
410
416
  * Logs a database query transaction
@@ -412,20 +418,23 @@ class UnnboundLogger {
412
418
  * @param options - Additional logging options
413
419
  */
414
420
  dbQueryTransaction(query, options = {}) {
421
+ const logId = (0, uuid_1.v4)();
415
422
  const traceId = options.traceId || trace_context_1.traceContext.getTraceId() || (0, uuid_1.v4)();
416
423
  const requestId = options.requestId || (0, uuid_1.v4)();
417
424
  const duration = options.duration || (options.startTime ? Date.now() - options.startTime : 0);
418
425
  const level = query.status === 'success' ? 'info' : 'error';
419
426
  const logEntry = {
427
+ logId,
420
428
  type: 'dbQueryTransaction',
421
429
  message: `DB Query ${query.status} - ${query.vendor}`,
430
+ workflowId: this.workflowId,
422
431
  traceId,
423
432
  requestId,
424
433
  deploymentId: this.deploymentId,
425
434
  duration,
426
435
  db: query,
427
436
  };
428
- this.logger[level](logEntry);
437
+ this.log(level, logEntry);
429
438
  }
430
439
  }
431
440
  exports.UnnboundLogger = UnnboundLogger;
@@ -49,7 +49,7 @@ exports.httpStatusDetails = {
49
49
  function getStatusMessage(statusCode) {
50
50
  const status = exports.httpStatusDetails[statusCode];
51
51
  if (status) {
52
- return `${status.message} - ${status.description}`;
52
+ return `${statusCode} ${status.message} - ${status.description}`;
53
53
  }
54
- return 'Unknown Status';
54
+ return `${statusCode} Unknown Status`;
55
55
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "unnbound-logger-sdk",
3
- "version": "2.0.3",
4
- "description": "A structured logging library with TypeScript support using Pino. Provides consistent, well-typed logging across different operational contexts with automatic trace ID propagation.",
3
+ "version": "2.0.5",
4
+ "description": "A structured logging library with TypeScript support using Pino. Provides consistent, well-typed logging with automatic logId, workflowId, traceId, and deploymentId tracking across operational contexts.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "scripts": {