unnbound-logger-sdk 2.0.10 → 3.0.1

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
@@ -1,6 +1,6 @@
1
1
  # Unnbound Logger
2
2
 
3
- A structured logging library with TypeScript support built on Pino. Provides consistent, well-typed logging across different operational contexts. All logs are output in JSON format for better machine readability and parsing.
3
+ A structured logging library with TypeScript support built on Pino. Provides consistent, well-typed logging across different operational contexts with automatic trace and span tracking. All logs are output in JSON format for better machine readability and parsing.
4
4
 
5
5
  ## Installation
6
6
 
@@ -11,60 +11,40 @@ npm install unnbound-logger
11
11
  ## Basic Usage
12
12
 
13
13
  ```typescript
14
- import { UnnboundLogger } from 'unnbound-logger';
15
-
16
- // Create a new logger instance
17
- const logger = new UnnboundLogger();
14
+ import { logger } from 'unnbound-logger';
18
15
 
19
16
  // Log with string messages
20
17
  logger.info('Application started');
21
18
  logger.warn('Resource usage high');
22
- logger.error(new Error('Database connection failed'));
19
+ logger.error({ err: new Error('Database connection failed') }, 'Something bad happened');
23
20
  logger.debug('Debug information');
24
21
 
25
- // Log with object messages (wrapped in 'data' field)
26
- logger.info({
27
- event: 'user_login',
28
- userId: '123',
29
- timestamp: new Date().toISOString()
30
- });
31
- // Results in: { "data": { "event": "user_login", "userId": "123", "timestamp": "..." }, "message": "Structured log data", ... }
22
+ // Log with object messages (merged into top level)
23
+ logger.info({ event: 'user_login', userId: '123' }, 'Event received.');
24
+ // Results in: { "event": "user_login", "userId": "123", "message": "Application started", ... }
32
25
 
33
- // Log with both string message and metadata (metadata added to top level)
34
- logger.info('User logged in', {
35
- userId: '123',
36
- timestamp: new Date().toISOString()
37
- });
38
- // Results in: { "userId": "123", "timestamp": "...", "message": "User logged in", ... }
39
-
40
- // Log with object message and additional metadata
41
- logger.info(
42
- { event: 'user_login', userId: '123' },
43
- { timestamp: new Date().toISOString() }
44
- );
45
- // Results in: { "data": { "event": "user_login", "userId": "123" }, "timestamp": "...", "message": "Structured log data", ... }
26
+ // Log with both string message and metadata (metadata merged into top level)
27
+ logger.info({ userId: '123' }, 'User logged in');
28
+ // Results in: { "userId": "123", "message": "User logged in", ... }
46
29
  ```
47
30
 
48
31
  ## Log Format
49
32
 
50
- All logs follow a standardized format:
33
+ All logs follow a standardized format based on Pino with additional context:
51
34
 
52
35
  ```typescript
53
36
  interface Log<T extends LogType = 'general'> {
54
- logId: string; // Unique identifier for each log entry
55
37
  level: LogLevel; // "info" | "debug" | "error" | "warn"
56
- type: T; // "general" | "httpRequest" | "httpResponse" | "sftpTransaction" | "dbQueryTransaction"
57
38
  message: string;
58
- workflowId: string;
59
- serviceId: string;
60
- traceId: string;
61
- requestId: string;
62
- deploymentId: string; // Automatically populated from UNNBOUND_DEPLOYMENT_ID
63
- error?: SerializableError; // Only present for Error objects
64
- }
65
-
66
- interface LogTransaction<T extends LogType> extends Log<T> {
67
- duration: number; // Duration in milliseconds
39
+ traceId?: string; // Automatically included when in trace context
40
+ spanId?: string; // Automatically included when in span context
41
+ type?: T; // "general" | "http" | "sftp" | "dbQueryTransaction"
42
+ serviceId?: string; // From UNNBOUND_SERVICE_ID environment variable
43
+ deploymentId?: string; // From UNNBOUND_DEPLOYMENT_ID environment variable
44
+ workflowId?: string; // From UNNBOUND_WORKFLOW_ID environment variable
45
+ environment?: string; // From ENVIRONMENT environment variable
46
+ err?: unknown; // Only present for Error objects
47
+ duration?: number; // Duration in milliseconds for span operations
68
48
  }
69
49
  ```
70
50
 
@@ -80,15 +60,15 @@ export UNNBOUND_WORKFLOW_ID="order-processing-12345"
80
60
  export UNNBOUND_WORKFLOW_URL="https://workflows.example.com/order-processing-12345"
81
61
  export UNNBOUND_SERVICE_ID="order-service"
82
62
 
83
- # Or in your deployment configuration
63
+ # Or in your deployment configuration
84
64
  UNNBOUND_WORKFLOW_ID=order-processing-12345
85
65
  UNNBOUND_WORKFLOW_URL=https://workflows.example.com/order-processing-12345
86
66
  UNNBOUND_SERVICE_ID=order-service
87
67
  ```
88
68
 
89
69
  ```typescript
90
- // Create a logger - workflowId and serviceId are automatically set from environment
91
- const logger = new UnnboundLogger();
70
+ // Import the logger - workflowId and serviceId are automatically set from environment
71
+ import { logger } from 'unnbound-logger';
92
72
  ```
93
73
 
94
74
  ### Deployment Tracking
@@ -114,70 +94,47 @@ If the environment variables are not set, the fields will be empty strings. Thes
114
94
 
115
95
  ## Object Logging Behavior
116
96
 
117
- The logger handles different message types differently to ensure consistent structure in your logs:
97
+ The logger uses Pino's standard behavior for handling different message types:
118
98
 
119
99
  ### String Messages with Metadata
120
- When you pass a string message with additional metadata, the metadata is wrapped in a `data` field:
100
+
101
+ When you pass a string message with additional metadata, the metadata is merged into the top level:
121
102
 
122
103
  ```typescript
123
104
  logger.info('User action completed', { userId: '123', action: 'login' });
124
- // Result: { "message": "User action completed", "data": { "userId": "123", "action": "login" }, ... }
105
+ // Result: { "message": "User action completed", "userId": "123", "action": "login", ... }
125
106
  ```
126
107
 
127
108
  ### Object Messages
128
- When you pass an object as the message, it gets wrapped in a `data` field to prevent unknown properties from polluting the top level:
129
-
130
- ```typescript
131
- logger.info({ userId: '123', action: 'login', timestamp: '2025-01-01T12:00:00Z' });
132
- // Result: { "message": "Structured log data", "data": { "userId": "123", "action": "login", "timestamp": "2025-01-01T12:00:00Z" }, ... }
133
- ```
134
109
 
135
- If the object contains a `message` property, it remains in the `data` object and doesn't affect the top-level message:
110
+ When you pass an object as the message, it's merged into the top level:
136
111
 
137
112
  ```typescript
138
- logger.info({ message: 'Custom message', userId: '123' });
139
- // Result: { "message": "Structured log data", "data": { "message": "Custom message", "userId": "123" }, ... }
113
+ logger.info({ userId: '123', action: 'login' });
114
+ // Result: { "userId": "123", "action": "login", "message": "Application started", ... }
140
115
  ```
141
116
 
142
117
  ### Error Objects
118
+
143
119
  Error objects are handled specially and include serialized error information:
144
120
 
145
121
  ```typescript
146
- logger.error(new Error('Something went wrong'));
147
- // Result: { "message": "Error", "error": { "name": "Error", "message": "Something went wrong", "stack": "..." }, ... }
122
+ logger.error({ err: new Error('Something went wrong') });
123
+ // Result: { "message": "Error", "err": { "name": "Error", "message": "Something went wrong", "stack": "..." }, ... }
148
124
  ```
149
125
 
150
- This structure ensures your UI can reliably access all object data through the `data` field without worrying about unknown properties at the top level. Whether you pass an object as the message or as metadata, it will always be contained within the `data` field.
126
+ This follows Pino's standard behavior where all object properties are merged into the top level of the log entry.
151
127
 
152
128
  ## HTTP Request/Response Logging
153
129
 
154
130
  ```typescript
155
- import { UnnboundLogger } from 'unnbound-logger';
131
+ import { logger, traceMiddleware } from 'unnbound-logger';
156
132
  import express from 'express';
157
133
 
158
134
  const app = express();
159
- const logger = new UnnboundLogger();
160
-
161
- // Middleware to log requests
162
- app.use((req, res, next) => {
163
- // Log the request and get the request ID
164
- const requestId = logger.httpRequest(req, {
165
- startTime: Date.now()
166
- });
167
-
168
- // Store the request ID in res.locals for later use
169
- res.locals.requestId = requestId;
170
-
171
- // Add response listener to log the response
172
- res.on('finish', () => {
173
- logger.httpResponse(res, req, {
174
- requestId,
175
- startTime: res.locals.startTime
176
- });
177
- });
178
-
179
- next();
180
- });
135
+
136
+ // Apply trace middleware for automatic HTTP logging
137
+ app.use(traceMiddleware());
181
138
 
182
139
  // Example route
183
140
  app.post('/api/users', (req, res) => {
@@ -186,11 +143,13 @@ app.post('/api/users', (req, res) => {
186
143
  });
187
144
  ```
188
145
 
189
- The logger automatically captures:
146
+ The trace middleware automatically captures:
147
+
190
148
  - Request method, URL, body, and headers (filtered for security)
191
149
  - Response status code, body, and headers (filtered for security)
192
150
  - Request duration
193
- - Trace ID and request ID for correlation
151
+ - Trace ID and span ID for correlation
152
+ - Automatic span tracking for the entire request lifecycle
194
153
 
195
154
  ### Full URL Logging for Webhook Endpoints
196
155
 
@@ -210,13 +169,12 @@ export UNNBOUND_WORKFLOW_URL="https://api.yourservice.com"
210
169
 
211
170
  ```typescript
212
171
  import express from 'express';
213
- import { UnnboundLogger } from 'unnbound-logger';
172
+ import { traceMiddleware } from 'unnbound-logger';
214
173
 
215
174
  const app = express();
216
- const logger = new UnnboundLogger();
217
175
 
218
176
  // Apply trace middleware for automatic logging
219
- app.use(logger.traceMiddleware);
177
+ app.use(traceMiddleware());
220
178
 
221
179
  // Webhook endpoints - URLs automatically logged with full domain
222
180
  app.post('/webhooks/stripe', (req, res) => {
@@ -232,67 +190,6 @@ app.post('/webhooks/github', (req, res) => {
232
190
 
233
191
  This ensures webhook logs contain the complete URL for easy debugging and monitoring.
234
192
 
235
- ## SFTP Transaction Logging
236
-
237
- For logging SFTP operations:
238
-
239
- ```typescript
240
- import { UnnboundLogger } from 'unnbound-logger';
241
-
242
- const logger = new UnnboundLogger();
243
-
244
- // Log an SFTP upload
245
- logger.sftpTransaction({
246
- host: 'sftp.example.com',
247
- username: 'ftpuser',
248
- operation: 'upload',
249
- path: '/uploads/file.txt',
250
- status: 'success',
251
- bytesTransferred: 1024
252
- });
253
-
254
- // Log an SFTP download with failure
255
- logger.sftpTransaction({
256
- host: 'sftp.example.com',
257
- username: 'ftpuser',
258
- operation: 'download',
259
- path: '/downloads/file.txt',
260
- status: 'failure'
261
- }, {
262
- startTime: Date.now() - 5000 // Started 5 seconds ago
263
- });
264
- ```
265
-
266
- ## Database Query Transaction Logging
267
-
268
- For logging database operations:
269
-
270
- ```typescript
271
- import { UnnboundLogger } from 'unnbound-logger';
272
-
273
- const logger = new UnnboundLogger();
274
-
275
- // Log a successful database query
276
- logger.dbQueryTransaction({
277
- instance: 'localhost:5432',
278
- vendor: 'postgres',
279
- query: 'SELECT * FROM users WHERE active = true',
280
- status: 'success',
281
- rowsReturned: 150
282
- });
283
-
284
- // Log a failed database operation
285
- logger.dbQueryTransaction({
286
- instance: 'prod-db-cluster',
287
- vendor: 'mysql',
288
- query: 'UPDATE users SET last_login = NOW()',
289
- status: 'failure',
290
- rowsAffected: 0
291
- }, {
292
- duration: 2500 // Operation took 2.5 seconds
293
- });
294
- ```
295
-
296
193
  ## Middleware Usage
297
194
 
298
195
  ### Express Trace Middleware
@@ -300,155 +197,180 @@ logger.dbQueryTransaction({
300
197
  The library provides a comprehensive trace middleware for Express applications that automatically handles trace context and HTTP logging:
301
198
 
302
199
  ```typescript
303
- import { UnnboundLogger } from 'unnbound-logger';
200
+ import { traceMiddleware } from 'unnbound-logger';
304
201
  import express from 'express';
305
202
 
306
203
  const app = express();
307
- const logger = new UnnboundLogger();
308
204
 
309
205
  // Apply the comprehensive trace middleware globally
310
- app.use(logger.traceMiddleware);
206
+ app.use(traceMiddleware());
311
207
  ```
312
208
 
313
209
  The trace middleware automatically:
210
+
314
211
  - Generates and maintains trace IDs across the request lifecycle
315
- - Logs incoming requests with method, URL, headers, and body (filtered for security)
212
+ - Logs incoming requests with method, URL, headers, and body
316
213
  - Logs outgoing responses with status code, headers, body, and duration
317
214
  - Measures request duration automatically
318
215
  - Handles errors and logs them appropriately
319
216
  - Captures response bodies for logging
217
+ - Creates spans for the entire request lifecycle
320
218
 
321
219
  ### Axios Trace Middleware
322
220
 
323
221
  For comprehensive logging of outgoing HTTP requests made with Axios:
324
222
 
325
223
  ```typescript
326
- import { UnnboundLogger } from 'unnbound-logger';
224
+ import { traceAxios } from 'unnbound-logger';
327
225
  import axios from 'axios';
328
226
 
329
- const logger = new UnnboundLogger();
330
-
331
- // Add both request and response interceptors for complete HTTP logging
332
- axios.interceptors.request.use(
333
- logger.axiosTraceMiddleware.onFulfilled,
334
- logger.axiosTraceMiddleware.onRejected
335
- );
336
-
337
- axios.interceptors.response.use(
338
- logger.axiosResponseInterceptor.onFulfilled,
339
- logger.axiosResponseInterceptor.onRejected
340
- );
227
+ // Create an axios instance and wrap it with tracing
228
+ const client = traceAxios(axios.create());
341
229
 
342
- // All requests made with axios will be automatically logged
343
- axios.get('https://api.example.com/data');
230
+ // All requests made with this client will be automatically logged
231
+ client.get('https://api.example.com/data');
344
232
  ```
345
233
 
346
234
  The Axios middleware:
347
- - Logs outgoing requests with method, URL, headers, and body (filtered for security)
235
+
236
+ - Logs outgoing requests with method, URL, headers, and body
348
237
  - Maintains trace context across requests by propagating trace IDs
349
238
  - Logs successful responses with status, headers, body, and duration
350
239
  - Logs error responses with detailed error information
240
+ - Creates spans for each HTTP request
351
241
  - Supports request/response filtering through configuration
352
242
 
353
- ## Function Tracing with withTrace
243
+ ## Function Tracing with startSpan
354
244
 
355
- The `withTrace` higher-order function allows you to wrap any function with automatic trace context. This is particularly useful for maintaining consistent trace IDs across async operations and distributed systems:
245
+ The `startSpan` function allows you to wrap any async operation with automatic span tracking and logging. This is particularly useful for maintaining consistent trace IDs across async operations and distributed systems:
356
246
 
357
247
  ```typescript
358
- import { UnnboundLogger } from 'unnbound-logger';
359
- import { withTrace } from 'unnbound-logger/utils/with-trace';
360
- import { traceContext } from 'unnbound-logger/utils/trace-context';
361
-
362
- const logger = new UnnboundLogger();
248
+ import { logger, startSpan } from 'unnbound-logger';
363
249
 
364
- // Example: Wrapping a function with trace context
365
- const operation = (value: number) => {
366
- const traceId = traceContext.getTraceId();
367
- logger.info('Processing value', { value, traceId });
250
+ // Example: Wrapping a function with span tracking
251
+ const operation = async (value: number) => {
252
+ logger.info('Processing value', { value });
368
253
  return value * 2;
369
254
  };
370
255
 
371
- // Wrap the function with trace context
372
- const tracedOperation = withTrace(operation);
256
+ // Wrap the function with span tracking
257
+ const result = await startSpan('Processing operation', operation, () => ({
258
+ operationType: 'calculation',
259
+ }));
373
260
 
374
261
  // Execute the function
375
- const result = tracedOperation(21); // Returns 42
376
- ```
377
-
378
- ### Using Custom Trace IDs
379
-
380
- You can provide your own trace ID when wrapping a function:
381
-
382
- ```typescript
383
- const customTraceId = 'custom-trace-123';
384
- const tracedOperation = withTrace(operation, customTraceId);
262
+ const result = await startSpan('Processing operation', () => operation(21)); // Returns 42
385
263
  ```
386
264
 
387
265
  ### Async Operations
388
266
 
389
- The trace context is maintained across async operations:
267
+ The span context is maintained across async operations:
390
268
 
391
269
  ```typescript
392
270
  const asyncOperation = async (value: number) => {
393
- const traceId1 = traceContext.getTraceId();
394
- logger.info('First step', { traceId: traceId1 });
271
+ logger.info('First step', { value });
395
272
 
396
273
  await someAsyncWork();
397
274
 
398
- const traceId2 = traceContext.getTraceId();
399
- logger.info('Second step', { traceId: traceId2 });
400
- // traceId1 and traceId2 will be the same
275
+ logger.info('Second step', { value });
276
+ return value * 2;
401
277
  };
402
278
 
403
- const tracedOperation = withTrace(asyncOperation);
404
- await tracedOperation(42);
279
+ const result = await startSpan('Async operation', asyncOperation, () => ({
280
+ operationType: 'async_calculation',
281
+ }));
405
282
  ```
406
283
 
407
284
  ### Benefits
408
285
 
409
- - Automatic trace ID generation
286
+ - Automatic span ID generation and tracking
410
287
  - Consistent trace context across async operations
411
- - Support for custom trace IDs
288
+ - Automatic duration measurement
289
+ - Error handling and logging
412
290
  - Type-safe implementation
413
- - Works with both sync and async functions
414
- - Maintains separate trace contexts for different operations
415
-
416
- > **Note:** When using `UnnboundLogger`, you don't need to manually call `traceContext.getTraceId()` in your logging calls. The logger automatically includes the current trace ID in all log entries. The example above shows manual trace ID retrieval for demonstration purposes, but in practice, you can simply use the logger methods directly:
417
- >
418
- > ```typescript
419
- > const operation = (value: number) => {
420
- > logger.info('Processing value', { value }); // Trace ID is automatically included
421
- > return value * 2;
422
- > };
423
- > ```
291
+ - Works with async functions
292
+ - Maintains separate span contexts for different operations
293
+
294
+ > **Note:** When using the logger within spans, you don't need to manually manage trace IDs. The logger automatically includes the current trace ID and span ID in all log entries.
424
295
 
425
296
  ## API Reference
426
297
 
427
- ### UnnboundLogger
298
+ ### logger
428
299
 
429
- The main logger class that provides all logging functionality using Pino.
300
+ The main logger instance that provides all logging functionality using Pino.
430
301
 
431
- #### Constructor
302
+ #### Usage
432
303
 
433
304
  ```typescript
434
- new UnnboundLogger(options?: LoggerOptions)
305
+ import { logger } from 'unnbound-logger';
435
306
  ```
436
307
 
437
- **LoggerOptions:**
438
- - `traceHeaderKey?: string` - Custom trace header name (default: 'unnbound-trace-id')
439
- - `ignoreTraceRoutes?: string[]` - Routes to ignore in Express middleware
440
- - `ignoreAxiosTraceRoutes?: string[]` - Routes to ignore in Axios middleware
441
-
442
- **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.
308
+ The logger is a Pino instance with additional context automatically included from environment variables and trace context.
443
309
 
444
310
  #### Methods
445
311
 
446
- - `log(level: LogLevel, message: string | Error | Record<string, unknown>, options?: GeneralLogOptions): Log`
447
- - `error(message: string | Error | Record<string, unknown>, options?: GeneralLogOptions): Log`
448
- - `warn(message: string | Error | Record<string, unknown>, options?: GeneralLogOptions): Log`
449
- - `info(message: string | Error | Record<string, unknown>, options?: GeneralLogOptions): Log`
450
- - `debug(message: string | Error | Record<string, unknown>, options?: GeneralLogOptions): Log`
451
- - `httpRequest(req: Request, options?: HttpRequestLogOptions): HttpRequestLog`
452
- - `httpResponse(res: Response, req: Request, options: HttpResponseLogOptions): HttpResponseLog`
453
- - `sftpTransaction(operation: SftpOperation, options?: SftpTransactionLogOptions): SftpTransactionLog`
454
- - `dbQueryTransaction(query: DbQuery, options?: DbQueryTransactionLogOptions): DbQueryTransactionLog`
312
+ - `logger.info(object: {}, message: string): void`
313
+ - `logger.warn(object: {}, message: string): void`
314
+ - `logger.error(object: {}, message: string): void`
315
+ - `logger.debug(object: {}, message: string): void`
316
+
317
+ ### traceMiddleware
318
+
319
+ Express middleware for automatic HTTP request/response logging and trace context management.
320
+
321
+ #### Usage
322
+
323
+ ```typescript
324
+ import { traceMiddleware } from 'unnbound-logger';
325
+
326
+ app.use(traceMiddleware(options?: HttpOptions));
327
+ ```
328
+
329
+ **HttpOptions:**
330
+
331
+ - `traceHeaderKey?: string` - Custom trace header name (default: 'x-unnbound-trace-id')
332
+ - `ignoreTraceRoutes?: string[]` - Routes to ignore in middleware (default: ['/health', '/healthcheck'])
333
+
334
+ ### traceAxios
335
+
336
+ Wraps an Axios instance with automatic request/response logging and trace context propagation.
337
+
338
+ #### Usage
339
+
340
+ ```typescript
341
+ import { traceAxios } from 'unnbound-logger';
342
+ import axios from 'axios';
343
+
344
+ const client = traceAxios(axios.create(), options?: HttpOptions);
345
+ ```
346
+
347
+ ### startSpan
348
+
349
+ Creates a span for tracking async operations with automatic logging and duration measurement.
350
+
351
+ #### Usage
352
+
353
+ ```typescript
354
+ import { startSpan } from 'unnbound-logger';
355
+
356
+ const result = await startSpan<T>(
357
+ spanName: string,
358
+ callback: () => Promise<T>,
359
+ getter?: LogPayloadGetter<T>
360
+ );
361
+ ```
362
+
363
+ **Parameters:**
364
+
365
+ - `spanName`: The name of the span for logging
366
+ - `callback`: The async function to execute within the span
367
+ - `getter`: Optional function to generate log payload based on operation result/error
368
+
369
+ ### Environment Variables
370
+
371
+ - `UNNBOUND_WORKFLOW_ID` - Workflow identifier (included in all logs)
372
+ - `UNNBOUND_SERVICE_ID` - Service identifier (included in all logs)
373
+ - `UNNBOUND_DEPLOYMENT_ID` - Deployment identifier (included in all logs)
374
+ - `UNNBOUND_WORKFLOW_URL` - Base URL for webhook endpoint logging
375
+ - `ENVIRONMENT` - Environment name (included in all logs)
376
+ - `LOG_LEVEL` - Log level (default: 'info')
@@ -0,0 +1,9 @@
1
+ import { Axios } from 'axios';
2
+ import { HttpOptions } from './types';
3
+ /**
4
+ * Wraps an axios instance to add tracing and span tracking
5
+ * @param axios - The axios instance to wrap
6
+ * @param options - Configuration options for HTTP tracing
7
+ * @returns The wrapped axios instance with span tracking
8
+ */
9
+ export declare const traceAxios: (client: Axios, { ignoreTraceRoutes, traceHeaderKey, }?: HttpOptions) => Axios;
package/dist/axios.js ADDED
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.traceAxios = void 0;
4
+ const axios_1 = require("axios");
5
+ const types_1 = require("./types");
6
+ const storage_1 = require("./storage");
7
+ const utils_1 = require("./utils");
8
+ const span_1 = require("./span");
9
+ const buildOutgoingHttpPayload = (config, res) => ({
10
+ type: 'http',
11
+ http: {
12
+ url: [config.baseURL, config.url].filter(Boolean).join(''),
13
+ method: config.method?.toUpperCase() || 'GET',
14
+ incoming: false,
15
+ request: {
16
+ headers: config.headers,
17
+ body: (0, utils_1.safeJsonParse)(config.data),
18
+ },
19
+ response: res
20
+ ? {
21
+ headers: res?.headers,
22
+ status: res.status,
23
+ body: (0, utils_1.safeJsonParse)(res.data),
24
+ }
25
+ : undefined,
26
+ },
27
+ });
28
+ /**
29
+ * Wraps an axios instance to add tracing and span tracking
30
+ * @param axios - The axios instance to wrap
31
+ * @param options - Configuration options for HTTP tracing
32
+ * @returns The wrapped axios instance with span tracking
33
+ */
34
+ const traceAxios = (client, { ignoreTraceRoutes = types_1.defaultIgnoreTraceRoutes, traceHeaderKey = types_1.defaultTraceHeaderKey, } = {
35
+ ignoreTraceRoutes: types_1.defaultIgnoreTraceRoutes,
36
+ traceHeaderKey: types_1.defaultTraceHeaderKey,
37
+ }) => {
38
+ const createSpanWrappedRequest = (originalMethod, method) => {
39
+ const { headers: defaultHeaders, ...partialDefaultConfig } = client.defaults;
40
+ const headers = { ...defaultHeaders.common, ...(method && defaultHeaders[method]) };
41
+ const defaultConfig = { ...partialDefaultConfig, headers };
42
+ return async (config) => {
43
+ config = (0, axios_1.mergeConfig)(defaultConfig, config);
44
+ // Determine the actual config and URL
45
+ const url = [config.baseURL, config.url].filter(Boolean).join('');
46
+ // Check if this request should be ignored
47
+ if ((0, utils_1.shouldIgnorePath)(url, ignoreTraceRoutes))
48
+ return originalMethod(config);
49
+ const traceId = storage_1.storage.getStore()?.[storage_1.ContextAttribute.TraceId];
50
+ config = { ...config, headers: { ...config.headers, [traceHeaderKey]: traceId } };
51
+ // Execute the request within a span
52
+ return (0, span_1.startSpan)(`Outgoing HTTP request`, () => originalMethod(config), (options) => {
53
+ if (!options)
54
+ return buildOutgoingHttpPayload(config);
55
+ if (options.error)
56
+ return buildOutgoingHttpPayload(config, (0, axios_1.isAxiosError)(options.error) ? options.error.response : undefined);
57
+ return buildOutgoingHttpPayload(config, options.result);
58
+ });
59
+ };
60
+ };
61
+ const request = client.request.bind(client);
62
+ const tracedRequest = createSpanWrappedRequest(request);
63
+ client.request = tracedRequest;
64
+ ['post', 'put', 'patch'].forEach((method) => {
65
+ const func = createSpanWrappedRequest(request, method);
66
+ client[method] = (url, data, config) => func({ ...config, url, data });
67
+ });
68
+ ['delete', 'get', 'head', 'options'].forEach((method) => {
69
+ const func = createSpanWrappedRequest(request, method);
70
+ client[method] = (url, config) => func({ ...config, url });
71
+ });
72
+ return client;
73
+ };
74
+ exports.traceAxios = traceAxios;
package/dist/http.d.ts ADDED
File without changes
package/dist/http.js ADDED
@@ -0,0 +1 @@
1
+ "use strict";
package/dist/index.d.ts CHANGED
@@ -4,7 +4,9 @@
4
4
  * A structured logging library built on Pino with TypeScript support.
5
5
  * Provides consistent, well-typed logging across different operational contexts.
6
6
  */
7
- import { UnnboundLogger } from './unnbound-logger';
8
- import { LogLevel, LogType, HttpMethod, LoggerOptions, GeneralLogOptions, HttpRequestLogOptions, HttpResponseLogOptions, SftpTransactionLogOptions, DbQueryTransactionLogOptions, Log, LogTransaction, HttpRequestLog, HttpResponseLog, SftpTransactionLog, DbQueryTransactionLog, SerializableError } from './types';
9
- import { clearTraceId } from './utils/logger-utils';
10
- export { UnnboundLogger, LogLevel, LogType, HttpMethod, LoggerOptions, GeneralLogOptions, HttpRequestLogOptions, HttpResponseLogOptions, SftpTransactionLogOptions, DbQueryTransactionLogOptions, Log, LogTransaction, HttpRequestLog, HttpResponseLog, SftpTransactionLog, DbQueryTransactionLog, SerializableError, clearTraceId, };
7
+ export type { LogLevel, LogType, HttpMethod, Log, LogTransaction, SftpLog, HttpLog, SftpPayload, } from './types';
8
+ export type { UnnboundLogger } from './logger';
9
+ export { logger } from './logger';
10
+ export { startSpan } from './span';
11
+ export { traceAxios } from './axios';
12
+ export { traceMiddleware } from './middleware';