unnbound-logger-sdk 2.0.7 → 2.0.9
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 +52 -6
- package/dist/types.d.ts +1 -0
- package/dist/unnbound-logger.d.ts +2 -0
- package/dist/unnbound-logger.js +36 -13
- package/package.json +1 -1
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;
|
|
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
|
|
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
|
-
- **
|
|
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
package/dist/unnbound-logger.js
CHANGED
|
@@ -89,6 +89,11 @@ class UnnboundLogger {
|
|
|
89
89
|
// Axios response interceptor (should be used separately)
|
|
90
90
|
this.axiosResponseInterceptor = {
|
|
91
91
|
onFulfilled: (response) => {
|
|
92
|
+
// Check if the URL should be ignored
|
|
93
|
+
const url = `${response.config?.baseURL || ''}${response.config?.url}`;
|
|
94
|
+
if (url && this.shouldIgnorePath(url, this.ignoreAxiosTraceRoutes)) {
|
|
95
|
+
return response;
|
|
96
|
+
}
|
|
92
97
|
// Calculate duration
|
|
93
98
|
const startTime = response.config.metadata?.startTime || Date.now();
|
|
94
99
|
const requestId = response.config.metadata?.requestId;
|
|
@@ -121,6 +126,11 @@ class UnnboundLogger {
|
|
|
121
126
|
return response;
|
|
122
127
|
},
|
|
123
128
|
onRejected: (error) => {
|
|
129
|
+
// Check if the URL should be ignored
|
|
130
|
+
const url = `${error.config?.baseURL || ''}${error.config?.url}`;
|
|
131
|
+
if (url && this.shouldIgnorePath(url, this.ignoreAxiosTraceRoutes)) {
|
|
132
|
+
return Promise.reject(error);
|
|
133
|
+
}
|
|
124
134
|
// Calculate duration for error responses
|
|
125
135
|
const startTime = error.config?.metadata?.startTime || Date.now();
|
|
126
136
|
const requestId = error.config?.metadata?.requestId;
|
|
@@ -169,6 +179,8 @@ class UnnboundLogger {
|
|
|
169
179
|
}
|
|
170
180
|
};
|
|
171
181
|
this.workflowId = process.env.UNNBOUND_WORKFLOW_ID || '';
|
|
182
|
+
this.workflowUrl = process.env.UNNBOUND_WORKFLOW_URL || '';
|
|
183
|
+
this.serviceId = process.env.UNNBOUND_SERVICE_ID || '';
|
|
172
184
|
this.deploymentId = process.env.UNNBOUND_DEPLOYMENT_ID || '';
|
|
173
185
|
this.traceHeaderKey = options.traceHeaderKey || 'unnbound-trace-id';
|
|
174
186
|
this.ignoreTraceRoutes = options.ignoreTraceRoutes || [];
|
|
@@ -219,6 +231,7 @@ class UnnboundLogger {
|
|
|
219
231
|
logId,
|
|
220
232
|
type: 'general',
|
|
221
233
|
workflowId: this.workflowId,
|
|
234
|
+
serviceId: this.serviceId,
|
|
222
235
|
traceId,
|
|
223
236
|
requestId,
|
|
224
237
|
deploymentId: this.deploymentId,
|
|
@@ -300,11 +313,10 @@ class UnnboundLogger {
|
|
|
300
313
|
if (reqUrl?.startsWith('http://') || reqUrl?.startsWith('https://')) {
|
|
301
314
|
return reqUrl;
|
|
302
315
|
}
|
|
303
|
-
// Check if we have a
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
return `${serviceBaseUrl.replace(/\/$/, '')}${reqUrl}`;
|
|
316
|
+
// Check if we have a workflow URL configured (preferred method)
|
|
317
|
+
if (this.workflowUrl) {
|
|
318
|
+
// Use workflow URL as the base URL
|
|
319
|
+
return `${this.workflowUrl.replace(/\/$/, '')}${reqUrl}`;
|
|
308
320
|
}
|
|
309
321
|
// Fallback to constructing from request info for incoming requests
|
|
310
322
|
const protocol = req.protocol || (req.secure ? 'https' : 'http');
|
|
@@ -328,12 +340,15 @@ class UnnboundLogger {
|
|
|
328
340
|
req.res.locals.startTime = startTime;
|
|
329
341
|
req.res.locals.traceId = traceId;
|
|
330
342
|
req.res.locals.workflowId = this.workflowId;
|
|
343
|
+
req.res.locals.workflowUrl = this.workflowUrl;
|
|
344
|
+
req.res.locals.serviceId = this.serviceId;
|
|
331
345
|
}
|
|
332
346
|
const logEntry = {
|
|
333
347
|
logId,
|
|
334
348
|
type: 'httpRequest',
|
|
335
349
|
message: req.ip === 'outgoing' ? 'Outgoing HTTP Request' : 'Incoming HTTP Request',
|
|
336
350
|
workflowId: this.workflowId,
|
|
351
|
+
serviceId: this.serviceId,
|
|
337
352
|
traceId,
|
|
338
353
|
requestId,
|
|
339
354
|
deploymentId: this.deploymentId,
|
|
@@ -346,8 +361,9 @@ class UnnboundLogger {
|
|
|
346
361
|
body: (0, logger_utils_1.safeJsonParse)(req.body),
|
|
347
362
|
},
|
|
348
363
|
};
|
|
349
|
-
const
|
|
350
|
-
|
|
364
|
+
const { message: logMessage, ...logData } = logEntry;
|
|
365
|
+
this.logger[options.level || 'info'](logData, logMessage);
|
|
366
|
+
return logEntry;
|
|
351
367
|
}
|
|
352
368
|
/**
|
|
353
369
|
* Logs an HTTP response
|
|
@@ -360,6 +376,7 @@ class UnnboundLogger {
|
|
|
360
376
|
const requestId = res.locals.requestId || options.requestId || (0, uuid_1.v4)();
|
|
361
377
|
const startTime = res.locals.startTime || options.startTime || Date.now();
|
|
362
378
|
const workflowId = res.locals.workflowId || this.workflowId;
|
|
379
|
+
const serviceId = res.locals.serviceId || this.serviceId;
|
|
363
380
|
const traceId = res.locals.traceId || options.traceId || trace_context_1.traceContext.getTraceId() || (0, uuid_1.v4)();
|
|
364
381
|
const duration = options.duration || (Date.now() - startTime);
|
|
365
382
|
// Determine log level based on status code
|
|
@@ -377,6 +394,7 @@ class UnnboundLogger {
|
|
|
377
394
|
type: 'httpResponse',
|
|
378
395
|
message: (0, http_status_messages_1.getStatusMessage)(res.statusCode),
|
|
379
396
|
workflowId: workflowId || '',
|
|
397
|
+
serviceId: serviceId || '',
|
|
380
398
|
traceId,
|
|
381
399
|
requestId,
|
|
382
400
|
deploymentId: this.deploymentId,
|
|
@@ -390,8 +408,9 @@ class UnnboundLogger {
|
|
|
390
408
|
body: (0, logger_utils_1.safeJsonParse)(res.locals.body),
|
|
391
409
|
},
|
|
392
410
|
};
|
|
393
|
-
const
|
|
394
|
-
|
|
411
|
+
const { message: logMessage, ...logData } = logEntry;
|
|
412
|
+
this.logger[level](logData, logMessage);
|
|
413
|
+
return logEntry;
|
|
395
414
|
}
|
|
396
415
|
/**
|
|
397
416
|
* Logs an SFTP transaction
|
|
@@ -409,14 +428,16 @@ class UnnboundLogger {
|
|
|
409
428
|
type: 'sftpTransaction',
|
|
410
429
|
message: `SFTP ${operation.operation} ${operation.status} - ${operation.path}`,
|
|
411
430
|
workflowId: this.workflowId,
|
|
431
|
+
serviceId: this.serviceId,
|
|
412
432
|
traceId,
|
|
413
433
|
requestId,
|
|
414
434
|
deploymentId: this.deploymentId,
|
|
415
435
|
duration,
|
|
416
436
|
sftp: operation,
|
|
417
437
|
};
|
|
418
|
-
const
|
|
419
|
-
|
|
438
|
+
const { message: logMessage, ...logData } = logEntry;
|
|
439
|
+
this.logger[level](logData, logMessage);
|
|
440
|
+
return logEntry;
|
|
420
441
|
}
|
|
421
442
|
/**
|
|
422
443
|
* Logs a database query transaction
|
|
@@ -434,14 +455,16 @@ class UnnboundLogger {
|
|
|
434
455
|
type: 'dbQueryTransaction',
|
|
435
456
|
message: `DB Query ${query.status} - ${query.vendor}`,
|
|
436
457
|
workflowId: this.workflowId,
|
|
458
|
+
serviceId: this.serviceId,
|
|
437
459
|
traceId,
|
|
438
460
|
requestId,
|
|
439
461
|
deploymentId: this.deploymentId,
|
|
440
462
|
duration,
|
|
441
463
|
db: query,
|
|
442
464
|
};
|
|
443
|
-
const
|
|
444
|
-
|
|
465
|
+
const { message: logMessage, ...logData } = logEntry;
|
|
466
|
+
this.logger[level](logData, logMessage);
|
|
467
|
+
return logEntry;
|
|
445
468
|
}
|
|
446
469
|
}
|
|
447
470
|
exports.UnnboundLogger = UnnboundLogger;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "unnbound-logger-sdk",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.9",
|
|
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",
|