unnbound-logger-sdk 2.0.7 → 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 || [];
@@ -219,6 +221,7 @@ class UnnboundLogger {
219
221
  logId,
220
222
  type: 'general',
221
223
  workflowId: this.workflowId,
224
+ serviceId: this.serviceId,
222
225
  traceId,
223
226
  requestId,
224
227
  deploymentId: this.deploymentId,
@@ -300,11 +303,10 @@ class UnnboundLogger {
300
303
  if (reqUrl?.startsWith('http://') || reqUrl?.startsWith('https://')) {
301
304
  return reqUrl;
302
305
  }
303
- // Check if we have a base URL configured via environment variable
304
- const serviceBaseUrl = process.env.SERVICE_BASE_URL;
305
- if (serviceBaseUrl) {
306
- // Use configured base URL (useful for ECS when you know your service URL)
307
- 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}`;
308
310
  }
309
311
  // Fallback to constructing from request info for incoming requests
310
312
  const protocol = req.protocol || (req.secure ? 'https' : 'http');
@@ -328,12 +330,15 @@ class UnnboundLogger {
328
330
  req.res.locals.startTime = startTime;
329
331
  req.res.locals.traceId = traceId;
330
332
  req.res.locals.workflowId = this.workflowId;
333
+ req.res.locals.workflowUrl = this.workflowUrl;
334
+ req.res.locals.serviceId = this.serviceId;
331
335
  }
332
336
  const logEntry = {
333
337
  logId,
334
338
  type: 'httpRequest',
335
339
  message: req.ip === 'outgoing' ? 'Outgoing HTTP Request' : 'Incoming HTTP Request',
336
340
  workflowId: this.workflowId,
341
+ serviceId: this.serviceId,
337
342
  traceId,
338
343
  requestId,
339
344
  deploymentId: this.deploymentId,
@@ -346,8 +351,9 @@ class UnnboundLogger {
346
351
  body: (0, logger_utils_1.safeJsonParse)(req.body),
347
352
  },
348
353
  };
349
- const result = this.log(options.level || 'info', logEntry);
350
- return result;
354
+ const { message: logMessage, ...logData } = logEntry;
355
+ this.logger[options.level || 'info'](logData, logMessage);
356
+ return logEntry;
351
357
  }
352
358
  /**
353
359
  * Logs an HTTP response
@@ -360,6 +366,7 @@ class UnnboundLogger {
360
366
  const requestId = res.locals.requestId || options.requestId || (0, uuid_1.v4)();
361
367
  const startTime = res.locals.startTime || options.startTime || Date.now();
362
368
  const workflowId = res.locals.workflowId || this.workflowId;
369
+ const serviceId = res.locals.serviceId || this.serviceId;
363
370
  const traceId = res.locals.traceId || options.traceId || trace_context_1.traceContext.getTraceId() || (0, uuid_1.v4)();
364
371
  const duration = options.duration || (Date.now() - startTime);
365
372
  // Determine log level based on status code
@@ -377,6 +384,7 @@ class UnnboundLogger {
377
384
  type: 'httpResponse',
378
385
  message: (0, http_status_messages_1.getStatusMessage)(res.statusCode),
379
386
  workflowId: workflowId || '',
387
+ serviceId: serviceId || '',
380
388
  traceId,
381
389
  requestId,
382
390
  deploymentId: this.deploymentId,
@@ -390,8 +398,9 @@ class UnnboundLogger {
390
398
  body: (0, logger_utils_1.safeJsonParse)(res.locals.body),
391
399
  },
392
400
  };
393
- const result = this.log(level, logEntry);
394
- return result;
401
+ const { message: logMessage, ...logData } = logEntry;
402
+ this.logger[level](logData, logMessage);
403
+ return logEntry;
395
404
  }
396
405
  /**
397
406
  * Logs an SFTP transaction
@@ -409,14 +418,16 @@ class UnnboundLogger {
409
418
  type: 'sftpTransaction',
410
419
  message: `SFTP ${operation.operation} ${operation.status} - ${operation.path}`,
411
420
  workflowId: this.workflowId,
421
+ serviceId: this.serviceId,
412
422
  traceId,
413
423
  requestId,
414
424
  deploymentId: this.deploymentId,
415
425
  duration,
416
426
  sftp: operation,
417
427
  };
418
- const result = this.log(level, logEntry);
419
- return result;
428
+ const { message: logMessage, ...logData } = logEntry;
429
+ this.logger[level](logData, logMessage);
430
+ return logEntry;
420
431
  }
421
432
  /**
422
433
  * Logs a database query transaction
@@ -434,14 +445,16 @@ class UnnboundLogger {
434
445
  type: 'dbQueryTransaction',
435
446
  message: `DB Query ${query.status} - ${query.vendor}`,
436
447
  workflowId: this.workflowId,
448
+ serviceId: this.serviceId,
437
449
  traceId,
438
450
  requestId,
439
451
  deploymentId: this.deploymentId,
440
452
  duration,
441
453
  db: query,
442
454
  };
443
- const result = this.log(level, logEntry);
444
- return result;
455
+ const { message: logMessage, ...logData } = logEntry;
456
+ this.logger[level](logData, logMessage);
457
+ return logEntry;
445
458
  }
446
459
  }
447
460
  exports.UnnboundLogger = UnnboundLogger;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unnbound-logger-sdk",
3
- "version": "2.0.7",
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",