unnbound-logger-sdk 2.0.6 → 2.0.8

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
@@ -52,7 +52,8 @@ interface Log<T extends LogType = 'general'> {
52
52
  level: LogLevel; // "info" | "debug" | "error" | "warn"
53
53
  type: T; // "general" | "httpRequest" | "httpResponse" | "sftpTransaction" | "dbQueryTransaction"
54
54
  message: string;
55
- workflowId: string; // Workflow tracking (empty string if not set)
55
+ workflowId: string;
56
+ serviceId: string;
56
57
  traceId: string;
57
58
  requestId: string;
58
59
  deploymentId: string; // Automatically populated from UNNBOUND_DEPLOYMENT_ID
@@ -73,15 +74,18 @@ The logger includes a `workflowId` field in all log entries for tracking operati
73
74
  ```bash
74
75
  # Set the workflow ID in your environment
75
76
  export UNNBOUND_WORKFLOW_ID="order-processing-12345"
77
+ export UNNBOUND_WORKFLOW_URL="https://workflows.example.com/order-processing-12345"
78
+ export UNNBOUND_SERVICE_ID="order-service"
76
79
 
77
80
  # Or in your deployment configuration
78
81
  UNNBOUND_WORKFLOW_ID=order-processing-12345
82
+ UNNBOUND_WORKFLOW_URL=https://workflows.example.com/order-processing-12345
83
+ UNNBOUND_SERVICE_ID=order-service
79
84
  ```
80
85
 
81
86
  ```typescript
82
- // Create a logger - workflowId is automatically set from environment
87
+ // Create a logger - workflowId and serviceId are automatically set from environment
83
88
  const logger = new UnnboundLogger();
84
- // All logs will include the workflowId from UNNBOUND_WORKFLOW_ID environment variable
85
89
  ```
86
90
 
87
91
  ### Deployment Tracking
@@ -98,8 +102,10 @@ UNNBOUND_DEPLOYMENT_ID=v1.2.3-prod-20231201
98
102
 
99
103
  If the environment variables are not set, the fields will be empty strings. These fields help with:
100
104
 
101
- - **Workflow ID**: Unique identifier for the workflow
102
- - **Deployment ID**: Tracking logs across different application deployments
105
+ - **Workflow ID**: Unique identifier for the workflow (logged in each entry)
106
+ - **Workflow URL**: Used internally for URL construction in webhook endpoints (not logged as a field)
107
+ - **Service ID**: Identifier for the specific service/component (logged in each entry)
108
+ - **Deployment ID**: Tracking logs across different application deployments (logged in each entry)
103
109
  - **Correlating issues**: Link problems to specific workflows and releases
104
110
  - **Monitoring**: Track health and performance across workflows and deployments
105
111
 
@@ -146,6 +152,46 @@ The logger automatically captures:
146
152
  - Request duration
147
153
  - Trace ID and request ID for correlation
148
154
 
155
+ ### Full URL Logging for Webhook Endpoints
156
+
157
+ When webhook endpoints receive incoming requests, the logger automatically constructs and logs the full URL using a smart fallback strategy:
158
+
159
+ 1. **Preferred: Uses `UNNBOUND_WORKFLOW_URL`** - If set, this becomes the base URL for all logged requests
160
+ 2. **Fallback: Constructs from request headers** - Uses protocol, host, and forwarded headers from the incoming request
161
+
162
+ ```bash
163
+ # Set your workflow URL to ensure full URLs in logs
164
+ export UNNBOUND_WORKFLOW_URL="https://api.yourservice.com"
165
+
166
+ # Example webhook endpoints will be logged as:
167
+ # POST https://api.yourservice.com/webhooks/stripe
168
+ # POST https://api.yourservice.com/webhooks/github
169
+ ```
170
+
171
+ ```typescript
172
+ import express from 'express';
173
+ import { UnnboundLogger } from 'unnbound-logger';
174
+
175
+ const app = express();
176
+ const logger = new UnnboundLogger();
177
+
178
+ // Apply trace middleware for automatic logging
179
+ app.use(logger.traceMiddleware);
180
+
181
+ // Webhook endpoints - URLs automatically logged with full domain
182
+ app.post('/webhooks/stripe', (req, res) => {
183
+ // Request logged as: https://api.yourservice.com/webhooks/stripe
184
+ res.status(200).send('OK');
185
+ });
186
+
187
+ app.post('/webhooks/github', (req, res) => {
188
+ // Request logged as: https://api.yourservice.com/webhooks/github
189
+ res.status(200).send('OK');
190
+ });
191
+ ```
192
+
193
+ This ensures webhook logs contain the complete URL for easy debugging and monitoring.
194
+
149
195
  ## SFTP Transaction Logging
150
196
 
151
197
  For logging SFTP operations:
@@ -353,7 +399,7 @@ new UnnboundLogger(options?: LoggerOptions)
353
399
  - `ignoreTraceRoutes?: string[]` - Routes to ignore in Express middleware
354
400
  - `ignoreAxiosTraceRoutes?: string[]` - Routes to ignore in Axios middleware
355
401
 
356
- **Note:** `workflowId` and `deploymentId` are configured via environment variables (`UNNBOUND_WORKFLOW_ID`, `UNNBOUND_DEPLOYMENT_ID`).
402
+ **Note:** `workflowId`, `serviceId`, and `deploymentId` are configured via environment variables (`UNNBOUND_WORKFLOW_ID`, `UNNBOUND_SERVICE_ID`, `UNNBOUND_DEPLOYMENT_ID`). The `UNNBOUND_WORKFLOW_URL` is used for URL construction in webhook endpoints.
357
403
 
358
404
  #### Methods
359
405
 
package/dist/types.d.ts CHANGED
@@ -23,6 +23,7 @@ export interface Log<T extends LogType = 'general'> {
23
23
  level: LogLevel;
24
24
  type: T;
25
25
  message: string;
26
+ serviceId: string;
26
27
  deploymentId: string;
27
28
  workflowId: string;
28
29
  traceId: string;
@@ -15,6 +15,8 @@ declare module 'axios' {
15
15
  export declare class UnnboundLogger {
16
16
  private logger;
17
17
  private workflowId;
18
+ private workflowUrl;
19
+ private serviceId;
18
20
  private deploymentId;
19
21
  private traceHeaderKey;
20
22
  private ignoreTraceRoutes;
@@ -169,6 +169,8 @@ class UnnboundLogger {
169
169
  }
170
170
  };
171
171
  this.workflowId = process.env.UNNBOUND_WORKFLOW_ID || '';
172
+ this.workflowUrl = process.env.UNNBOUND_WORKFLOW_URL || '';
173
+ this.serviceId = process.env.UNNBOUND_SERVICE_ID || '';
172
174
  this.deploymentId = process.env.UNNBOUND_DEPLOYMENT_ID || '';
173
175
  this.traceHeaderKey = options.traceHeaderKey || 'unnbound-trace-id';
174
176
  this.ignoreTraceRoutes = options.ignoreTraceRoutes || [];
@@ -178,6 +180,7 @@ class UnnboundLogger {
178
180
  level: 'info',
179
181
  base: {}, // Disable all default base fields (pid, hostname)
180
182
  timestamp: false, // Let CloudWatch handle timestamps
183
+ messageKey: 'messages', // Change message field from 'msg' to 'messages'
181
184
  formatters: {
182
185
  level: (label) => {
183
186
  return { level: label };
@@ -218,6 +221,7 @@ class UnnboundLogger {
218
221
  logId,
219
222
  type: 'general',
220
223
  workflowId: this.workflowId,
224
+ serviceId: this.serviceId,
221
225
  traceId,
222
226
  requestId,
223
227
  deploymentId: this.deploymentId,
@@ -299,11 +303,10 @@ class UnnboundLogger {
299
303
  if (reqUrl?.startsWith('http://') || reqUrl?.startsWith('https://')) {
300
304
  return reqUrl;
301
305
  }
302
- // Check if we have a base URL configured via environment variable
303
- const serviceBaseUrl = process.env.SERVICE_BASE_URL;
304
- if (serviceBaseUrl) {
305
- // Use configured base URL (useful for ECS when you know your service URL)
306
- return `${serviceBaseUrl.replace(/\/$/, '')}${reqUrl}`;
306
+ // Check if we have a workflow URL configured (preferred method)
307
+ if (this.workflowUrl) {
308
+ // Use workflow URL as the base URL
309
+ return `${this.workflowUrl.replace(/\/$/, '')}${reqUrl}`;
307
310
  }
308
311
  // Fallback to constructing from request info for incoming requests
309
312
  const protocol = req.protocol || (req.secure ? 'https' : 'http');
@@ -327,12 +330,15 @@ class UnnboundLogger {
327
330
  req.res.locals.startTime = startTime;
328
331
  req.res.locals.traceId = traceId;
329
332
  req.res.locals.workflowId = this.workflowId;
333
+ req.res.locals.workflowUrl = this.workflowUrl;
334
+ req.res.locals.serviceId = this.serviceId;
330
335
  }
331
336
  const logEntry = {
332
337
  logId,
333
338
  type: 'httpRequest',
334
339
  message: req.ip === 'outgoing' ? 'Outgoing HTTP Request' : 'Incoming HTTP Request',
335
340
  workflowId: this.workflowId,
341
+ serviceId: this.serviceId,
336
342
  traceId,
337
343
  requestId,
338
344
  deploymentId: this.deploymentId,
@@ -345,8 +351,9 @@ class UnnboundLogger {
345
351
  body: (0, logger_utils_1.safeJsonParse)(req.body),
346
352
  },
347
353
  };
348
- const result = this.log(options.level || 'info', logEntry);
349
- return result;
354
+ const { message: logMessage, ...logData } = logEntry;
355
+ this.logger[options.level || 'info'](logData, logMessage);
356
+ return logEntry;
350
357
  }
351
358
  /**
352
359
  * Logs an HTTP response
@@ -359,6 +366,7 @@ class UnnboundLogger {
359
366
  const requestId = res.locals.requestId || options.requestId || (0, uuid_1.v4)();
360
367
  const startTime = res.locals.startTime || options.startTime || Date.now();
361
368
  const workflowId = res.locals.workflowId || this.workflowId;
369
+ const serviceId = res.locals.serviceId || this.serviceId;
362
370
  const traceId = res.locals.traceId || options.traceId || trace_context_1.traceContext.getTraceId() || (0, uuid_1.v4)();
363
371
  const duration = options.duration || (Date.now() - startTime);
364
372
  // Determine log level based on status code
@@ -376,6 +384,7 @@ class UnnboundLogger {
376
384
  type: 'httpResponse',
377
385
  message: (0, http_status_messages_1.getStatusMessage)(res.statusCode),
378
386
  workflowId: workflowId || '',
387
+ serviceId: serviceId || '',
379
388
  traceId,
380
389
  requestId,
381
390
  deploymentId: this.deploymentId,
@@ -389,8 +398,9 @@ class UnnboundLogger {
389
398
  body: (0, logger_utils_1.safeJsonParse)(res.locals.body),
390
399
  },
391
400
  };
392
- const result = this.log(level, logEntry);
393
- return result;
401
+ const { message: logMessage, ...logData } = logEntry;
402
+ this.logger[level](logData, logMessage);
403
+ return logEntry;
394
404
  }
395
405
  /**
396
406
  * Logs an SFTP transaction
@@ -408,14 +418,16 @@ class UnnboundLogger {
408
418
  type: 'sftpTransaction',
409
419
  message: `SFTP ${operation.operation} ${operation.status} - ${operation.path}`,
410
420
  workflowId: this.workflowId,
421
+ serviceId: this.serviceId,
411
422
  traceId,
412
423
  requestId,
413
424
  deploymentId: this.deploymentId,
414
425
  duration,
415
426
  sftp: operation,
416
427
  };
417
- const result = this.log(level, logEntry);
418
- return result;
428
+ const { message: logMessage, ...logData } = logEntry;
429
+ this.logger[level](logData, logMessage);
430
+ return logEntry;
419
431
  }
420
432
  /**
421
433
  * Logs a database query transaction
@@ -433,14 +445,16 @@ class UnnboundLogger {
433
445
  type: 'dbQueryTransaction',
434
446
  message: `DB Query ${query.status} - ${query.vendor}`,
435
447
  workflowId: this.workflowId,
448
+ serviceId: this.serviceId,
436
449
  traceId,
437
450
  requestId,
438
451
  deploymentId: this.deploymentId,
439
452
  duration,
440
453
  db: query,
441
454
  };
442
- const result = this.log(level, logEntry);
443
- return result;
455
+ const { message: logMessage, ...logData } = logEntry;
456
+ this.logger[level](logData, logMessage);
457
+ return logEntry;
444
458
  }
445
459
  }
446
460
  exports.UnnboundLogger = UnnboundLogger;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unnbound-logger-sdk",
3
- "version": "2.0.6",
3
+ "version": "2.0.8",
4
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",