unnbound-logger-sdk 1.1.3 → 2.0.0

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
@@ -53,6 +53,7 @@ interface Log<T extends LogType = 'general'> {
53
53
  message: string;
54
54
  traceId: string;
55
55
  requestId: string;
56
+ deploymentId: string; // Automatically populated from DEPLOYMENT_ID environment variable
56
57
  error?: SerializableError; // Only present for Error objects
57
58
  }
58
59
 
@@ -61,6 +62,25 @@ interface LogTransaction<T extends LogType> extends Log<T> {
61
62
  }
62
63
  ```
63
64
 
65
+ ## Deployment Tracking
66
+
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.
68
+
69
+ ```bash
70
+ # Set the deployment ID in your environment
71
+ export DEPLOYMENT_ID="v1.2.3-prod-20231201"
72
+
73
+ # Or in your deployment configuration
74
+ DEPLOYMENT_ID=v1.2.3-prod-20231201
75
+ ```
76
+
77
+ If the `DEPLOYMENT_ID` environment variable is not set, the `deploymentId` field will be an empty string. This field helps with:
78
+
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
83
+
64
84
  ## HTTP Request/Response Logging
65
85
 
66
86
  ```typescript
package/dist/index.d.ts CHANGED
@@ -6,8 +6,8 @@
6
6
  */
7
7
  import { UnnboundLogger } from './unnbound-logger';
8
8
  import { LogLevel, LogType, HttpMethod, LoggerOptions, GeneralLogOptions, HttpRequestLogOptions, HttpResponseLogOptions, SftpTransactionLogOptions, DbQueryTransactionLogOptions, Log, LogTransaction, HttpRequestLog, HttpResponseLog, SftpTransactionLog, DbQueryTransactionLog, SerializableError } from './types';
9
- import { generateUuid, clearTraceId } from './utils/id-generator';
10
- export { UnnboundLogger, LogLevel, LogType, HttpMethod, LoggerOptions, GeneralLogOptions, HttpRequestLogOptions, HttpResponseLogOptions, SftpTransactionLogOptions, DbQueryTransactionLogOptions, Log, LogTransaction, HttpRequestLog, HttpResponseLog, SftpTransactionLog, DbQueryTransactionLog, SerializableError, generateUuid, clearTraceId, };
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, };
11
11
  declare const defaultLogger: UnnboundLogger;
12
12
  export { defaultLogger };
13
13
  export declare const log: (level: LogLevel, message: string | Error | Record<string, unknown>, options?: GeneralLogOptions) => void;
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.dbQueryTransaction = exports.sftpTransaction = exports.httpResponse = exports.httpRequest = exports.debug = exports.info = exports.warn = exports.error = exports.log = exports.defaultLogger = exports.clearTraceId = exports.generateUuid = exports.UnnboundLogger = void 0;
3
+ exports.dbQueryTransaction = exports.sftpTransaction = exports.httpResponse = exports.httpRequest = exports.debug = exports.info = exports.warn = exports.error = exports.log = exports.defaultLogger = exports.clearTraceId = exports.UnnboundLogger = void 0;
4
4
  /**
5
5
  * unnbound-logger
6
6
  *
@@ -9,9 +9,8 @@ exports.dbQueryTransaction = exports.sftpTransaction = exports.httpResponse = ex
9
9
  */
10
10
  const unnbound_logger_1 = require("./unnbound-logger");
11
11
  Object.defineProperty(exports, "UnnboundLogger", { enumerable: true, get: function () { return unnbound_logger_1.UnnboundLogger; } });
12
- const id_generator_1 = require("./utils/id-generator");
13
- Object.defineProperty(exports, "generateUuid", { enumerable: true, get: function () { return id_generator_1.generateUuid; } });
14
- Object.defineProperty(exports, "clearTraceId", { enumerable: true, get: function () { return id_generator_1.clearTraceId; } });
12
+ const logger_utils_1 = require("./utils/logger-utils");
13
+ Object.defineProperty(exports, "clearTraceId", { enumerable: true, get: function () { return logger_utils_1.clearTraceId; } });
15
14
  // Create a default logger instance
16
15
  const defaultLogger = new unnbound_logger_1.UnnboundLogger();
17
16
  exports.defaultLogger = defaultLogger;
package/dist/types.d.ts CHANGED
@@ -22,6 +22,7 @@ export interface Log<T extends LogType = 'general'> {
22
22
  level: LogLevel;
23
23
  type: T;
24
24
  message: string;
25
+ deploymentId: string;
25
26
  traceId: string;
26
27
  requestId: string;
27
28
  error?: SerializableError;
@@ -5,6 +5,7 @@ declare module 'axios' {
5
5
  interface InternalAxiosRequestConfig {
6
6
  metadata?: {
7
7
  startTime: number;
8
+ requestId?: string;
8
9
  };
9
10
  }
10
11
  }
@@ -16,6 +17,7 @@ export declare class UnnboundLogger {
16
17
  private defaultLevel;
17
18
  private serviceName?;
18
19
  private environment?;
20
+ private deploymentId;
19
21
  private traceHeaderKey;
20
22
  private ignoreTraceRoutes;
21
23
  private ignoreAxiosTraceRoutes;
@@ -62,6 +64,12 @@ export declare class UnnboundLogger {
62
64
  * @param options - Additional logging options
63
65
  */
64
66
  debug(message: string | Error | Record<string, unknown>, options?: GeneralLogOptions): void;
67
+ /**
68
+ * Constructs the full URL from request information
69
+ * @param req - Express request object
70
+ * @returns Full URL string
71
+ */
72
+ private constructFullUrl;
65
73
  /**
66
74
  * Logs an HTTP request
67
75
  * @param req - Express request object
@@ -8,11 +8,11 @@ exports.UnnboundLogger = void 0;
8
8
  * Core logger implementation
9
9
  */
10
10
  const pino_1 = __importDefault(require("pino"));
11
- const id_generator_1 = require("./utils/id-generator");
12
11
  const logger_utils_1 = require("./utils/logger-utils");
13
12
  const uuid_1 = require("uuid");
14
13
  const trace_context_1 = require("./utils/trace-context");
15
14
  const axios_1 = require("axios");
15
+ const http_status_messages_1 = require("./utils/http-status-messages");
16
16
  /**
17
17
  * UnnboundLogger provides typed, structured logging using Pino
18
18
  */
@@ -59,17 +59,26 @@ class UnnboundLogger {
59
59
  headers.set(this.traceHeaderKey, traceId);
60
60
  config.headers = headers;
61
61
  }
62
- // Store request start time for duration calculation
63
- config.metadata = { startTime: Date.now() };
64
- // Log the outgoing request
65
- this.info(`HTTP Request: ${config.method?.toUpperCase()} ${config.baseURL || ''}${config.url}`, {
66
- type: 'httpRequest',
67
- httpRequest: {
68
- url: `${config.baseURL || ''}${config.url}`,
69
- method: config.method?.toUpperCase(),
70
- headers: (0, logger_utils_1.filterHeaders)(config.headers),
71
- body: config.data
72
- }
62
+ // Store request start time and generate requestId for duration calculation and correlation
63
+ const startTime = Date.now();
64
+ const requestId = (0, uuid_1.v4)();
65
+ config.metadata = { startTime, requestId };
66
+ // Log the outgoing request using proper httpRequest method
67
+ const mockReq = {
68
+ method: config.method?.toUpperCase() || 'UNKNOWN',
69
+ url: `${config.baseURL || ''}${config.url}`,
70
+ originalUrl: `${config.baseURL || ''}${config.url}`,
71
+ headers: config.headers || {},
72
+ body: config.data,
73
+ ip: 'outgoing', // Mark as outgoing request
74
+ protocol: 'https', // Default for outgoing
75
+ secure: true,
76
+ get: () => undefined // Mock get method for constructFullUrl
77
+ };
78
+ this.httpRequest(mockReq, {
79
+ traceId,
80
+ requestId,
81
+ startTime
73
82
  });
74
83
  return config;
75
84
  },
@@ -82,43 +91,78 @@ class UnnboundLogger {
82
91
  onFulfilled: (response) => {
83
92
  // Calculate duration
84
93
  const startTime = response.config.metadata?.startTime || Date.now();
94
+ const requestId = response.config.metadata?.requestId;
85
95
  const duration = Date.now() - startTime;
86
- // Log the successful response
87
- this.info(`HTTP Response: ${response.config.method?.toUpperCase()} ${response.config.baseURL || ''}${response.config.url} - ${response.status}`, {
88
- type: 'httpResponse',
96
+ // Log the successful response using proper httpResponse method
97
+ const mockReq = {
98
+ method: response.config.method?.toUpperCase() || 'UNKNOWN',
99
+ url: `${response.config.baseURL || ''}${response.config.url}`,
100
+ originalUrl: `${response.config.baseURL || ''}${response.config.url}`,
101
+ ip: 'outgoing', // Mark as outgoing request
102
+ protocol: 'https', // Default for outgoing
103
+ secure: true,
104
+ get: () => undefined // Mock get method for constructFullUrl
105
+ };
106
+ const mockRes = {
107
+ statusCode: response.status,
108
+ locals: {
109
+ body: response.data,
110
+ startTime: startTime,
111
+ traceId: trace_context_1.traceContext.getTraceId(),
112
+ requestId: requestId
113
+ },
114
+ getHeaders: () => response.headers || {}
115
+ };
116
+ this.httpResponse(mockRes, mockReq, {
117
+ requestId,
89
118
  duration,
90
- httpResponse: {
91
- url: `${response.config.baseURL || ''}${response.config.url}`,
92
- method: response.config.method?.toUpperCase(),
93
- status: response.status,
94
- headers: (0, logger_utils_1.filterHeaders)(response.headers),
95
- body: response.data
96
- }
119
+ traceId: trace_context_1.traceContext.getTraceId()
97
120
  });
98
121
  return response;
99
122
  },
100
123
  onRejected: (error) => {
101
124
  // Calculate duration for error responses
102
125
  const startTime = error.config?.metadata?.startTime || Date.now();
126
+ const requestId = error.config?.metadata?.requestId;
103
127
  const duration = Date.now() - startTime;
104
- // Log the error response
128
+ // Log the error response using proper httpResponse method
105
129
  if (error.response) {
106
- this.error(`HTTP Error Response: ${error.config?.method?.toUpperCase()} ${error.config?.baseURL || ''}${error.config?.url} - ${error.response.status}`, {
107
- type: 'httpResponse',
130
+ const mockReq = {
131
+ method: error.config?.method?.toUpperCase() || 'UNKNOWN',
132
+ url: `${error.config?.baseURL || ''}${error.config?.url}`,
133
+ originalUrl: `${error.config?.baseURL || ''}${error.config?.url}`,
134
+ ip: 'outgoing', // Mark as outgoing request
135
+ protocol: 'https', // Default for outgoing
136
+ secure: true,
137
+ get: () => undefined // Mock get method for constructFullUrl
138
+ };
139
+ const mockRes = {
140
+ statusCode: error.response.status,
141
+ locals: {
142
+ body: error.response.data,
143
+ startTime: startTime,
144
+ traceId: trace_context_1.traceContext.getTraceId(),
145
+ requestId: requestId
146
+ },
147
+ getHeaders: () => error.response.headers || {}
148
+ };
149
+ this.httpResponse(mockRes, mockReq, {
150
+ requestId,
108
151
  duration,
109
- httpResponse: {
110
- url: `${error.config?.baseURL || ''}${error.config?.url}`,
111
- method: error.config?.method?.toUpperCase(),
112
- status: error.response.status,
113
- headers: (0, logger_utils_1.filterHeaders)(error.response.headers),
114
- body: error.response.data
115
- }
152
+ traceId: trace_context_1.traceContext.getTraceId()
116
153
  });
117
154
  }
118
155
  else {
119
- this.error(`HTTP Request Failed: ${error.config?.method?.toUpperCase()} ${error.config?.baseURL || ''}${error.config?.url}`, {
120
- context: 'No response received',
121
- error: error.message
156
+ // For network errors without response, log as general error
157
+ this.error('HTTP Request Failed', {
158
+ context: {
159
+ reason: 'No response received',
160
+ method: error.config?.method?.toUpperCase() || 'UNKNOWN',
161
+ url: `${error.config?.baseURL || ''}${error.config?.url}`,
162
+ },
163
+ error: error.message,
164
+ requestId,
165
+ traceId: trace_context_1.traceContext.getTraceId()
122
166
  });
123
167
  }
124
168
  return Promise.reject(error);
@@ -127,6 +171,7 @@ class UnnboundLogger {
127
171
  this.defaultLevel = options.defaultLevel || 'info';
128
172
  this.serviceName = options.serviceName;
129
173
  this.environment = options.environment;
174
+ this.deploymentId = process.env.DEPLOYMENT_ID || '';
130
175
  this.traceHeaderKey = options.traceHeaderKey || 'unnbound-trace-id';
131
176
  this.ignoreTraceRoutes = options.ignoreTraceRoutes || [];
132
177
  this.ignoreAxiosTraceRoutes = options.ignoreAxiosTraceRoutes || [];
@@ -169,39 +214,46 @@ class UnnboundLogger {
169
214
  * @param options - Additional logging options
170
215
  */
171
216
  log(level, message, options = {}) {
172
- const traceId = options.traceId || trace_context_1.traceContext.getTraceId() || (0, id_generator_1.generateUuid)();
173
- const requestId = options.requestId || (0, id_generator_1.generateUuid)();
217
+ const traceId = options.traceId || trace_context_1.traceContext.getTraceId() || (0, uuid_1.v4)();
218
+ const requestId = options.requestId || (0, uuid_1.v4)();
174
219
  let logEntry;
175
- let error;
220
+ const { traceId: optionTraceId, requestId: optionRequestId, ...restOptions } = options;
176
221
  if (message instanceof Error) {
177
- error = {
222
+ const error = {
178
223
  name: message.name,
179
224
  message: message.message,
180
225
  stack: message.stack,
181
226
  };
182
227
  logEntry = {
183
228
  type: 'general',
184
- message: message.message,
185
229
  traceId,
186
230
  requestId,
231
+ deploymentId: this.deploymentId,
232
+ message: message.name,
187
233
  error,
234
+ ...restOptions,
188
235
  };
189
236
  }
190
237
  else if (typeof message === 'string') {
191
238
  logEntry = {
192
239
  type: 'general',
193
- message,
194
240
  traceId,
195
241
  requestId,
242
+ deploymentId: this.deploymentId,
243
+ message,
244
+ ...restOptions,
196
245
  };
197
246
  }
198
247
  else {
199
- // If message is an object, stringify it
248
+ // If message is an object, it's part of the log entry
200
249
  logEntry = {
201
250
  type: 'general',
202
- message: JSON.stringify(message),
203
251
  traceId,
204
252
  requestId,
253
+ deploymentId: this.deploymentId,
254
+ ...message,
255
+ message: message.message || 'Structured log data',
256
+ ...restOptions,
205
257
  };
206
258
  }
207
259
  this.logger[level](logEntry);
@@ -238,6 +290,28 @@ class UnnboundLogger {
238
290
  debug(message, options = {}) {
239
291
  this.log('debug', message, options);
240
292
  }
293
+ /**
294
+ * Constructs the full URL from request information
295
+ * @param req - Express request object
296
+ * @returns Full URL string
297
+ */
298
+ constructFullUrl(req) {
299
+ // If the URL is already absolute, return it directly
300
+ const reqUrl = req.originalUrl || req.url;
301
+ if (reqUrl?.startsWith('http://') || reqUrl?.startsWith('https://')) {
302
+ return reqUrl;
303
+ }
304
+ // Check if we have a base URL configured via environment variable
305
+ const serviceBaseUrl = process.env.SERVICE_BASE_URL;
306
+ if (serviceBaseUrl) {
307
+ // Use configured base URL (useful for ECS when you know your service URL)
308
+ return `${serviceBaseUrl.replace(/\/$/, '')}${reqUrl}`;
309
+ }
310
+ // Fallback to constructing from request info for incoming requests
311
+ const protocol = req.protocol || (req.secure ? 'https' : 'http');
312
+ const host = req.get('host') || req.get('x-forwarded-host') || 'localhost';
313
+ return `${protocol}://${host}${reqUrl}`;
314
+ }
241
315
  /**
242
316
  * Logs an HTTP request
243
317
  * @param req - Express request object
@@ -245,8 +319,8 @@ class UnnboundLogger {
245
319
  * @returns The request ID for correlating with the response
246
320
  */
247
321
  httpRequest(req, options = {}) {
248
- const traceId = options.traceId || trace_context_1.traceContext.getTraceId() || (0, id_generator_1.generateUuid)();
249
- const requestId = options.requestId || (0, id_generator_1.generateUuid)();
322
+ const traceId = options.traceId || trace_context_1.traceContext.getTraceId() || (0, uuid_1.v4)();
323
+ const requestId = options.requestId || (0, uuid_1.v4)();
250
324
  const startTime = options.startTime || Date.now();
251
325
  // Store request metadata in res.locals for later use
252
326
  if (req.res) {
@@ -256,15 +330,16 @@ class UnnboundLogger {
256
330
  }
257
331
  const logEntry = {
258
332
  type: 'httpRequest',
259
- message: `${req.method} ${req.originalUrl || req.url}`,
333
+ message: req.ip === 'outgoing' ? 'Outgoing HTTP Request' : 'Incoming HTTP Request',
260
334
  traceId,
261
335
  requestId,
336
+ deploymentId: this.deploymentId,
262
337
  duration: 0, // Will be updated in response
263
338
  httpRequest: {
264
- url: req.originalUrl || req.url,
339
+ url: this.constructFullUrl(req),
265
340
  method: req.method,
266
341
  headers: (0, logger_utils_1.filterHeaders)(req.headers),
267
- ip: req.ip,
342
+ ip: (0, logger_utils_1.normalizeIp)(req.ip),
268
343
  body: req.body,
269
344
  },
270
345
  };
@@ -278,9 +353,9 @@ class UnnboundLogger {
278
353
  * @param options - Additional logging options
279
354
  */
280
355
  httpResponse(res, req, options = {}) {
281
- const requestId = res.locals.requestId || options.requestId || (0, id_generator_1.generateUuid)();
356
+ const requestId = res.locals.requestId || options.requestId || (0, uuid_1.v4)();
282
357
  const startTime = res.locals.startTime || options.startTime || Date.now();
283
- const traceId = res.locals.traceId || options.traceId || trace_context_1.traceContext.getTraceId() || (0, id_generator_1.generateUuid)();
358
+ const traceId = res.locals.traceId || options.traceId || trace_context_1.traceContext.getTraceId() || (0, uuid_1.v4)();
284
359
  const duration = options.duration || (Date.now() - startTime);
285
360
  // Determine log level based on status code
286
361
  let level = options.level || this.defaultLevel;
@@ -297,15 +372,16 @@ class UnnboundLogger {
297
372
  }
298
373
  const logEntry = {
299
374
  type: 'httpResponse',
300
- message: `${req.method} ${req.originalUrl || req.url} - ${res.statusCode}`,
375
+ message: (0, http_status_messages_1.getStatusMessage)(res.statusCode),
301
376
  traceId,
302
377
  requestId,
378
+ deploymentId: this.deploymentId,
303
379
  duration,
304
380
  httpResponse: {
305
- url: req.originalUrl || req.url,
381
+ url: this.constructFullUrl(req),
306
382
  method: req.method,
307
383
  headers: (0, logger_utils_1.filterHeaders)(res.getHeaders()),
308
- ip: req.ip,
384
+ ip: (0, logger_utils_1.normalizeIp)(req.ip),
309
385
  status: res.statusCode,
310
386
  body: res.locals.body,
311
387
  },
@@ -318,8 +394,8 @@ class UnnboundLogger {
318
394
  * @param options - Additional logging options
319
395
  */
320
396
  sftpTransaction(operation, options = {}) {
321
- const traceId = options.traceId || trace_context_1.traceContext.getTraceId() || (0, id_generator_1.generateUuid)();
322
- const requestId = options.requestId || (0, id_generator_1.generateUuid)();
397
+ const traceId = options.traceId || trace_context_1.traceContext.getTraceId() || (0, uuid_1.v4)();
398
+ const requestId = options.requestId || (0, uuid_1.v4)();
323
399
  const duration = options.duration || (options.startTime ? Date.now() - options.startTime : 0);
324
400
  const level = operation.status === 'success' ? 'info' : 'error';
325
401
  const logEntry = {
@@ -327,6 +403,7 @@ class UnnboundLogger {
327
403
  message: `SFTP ${operation.operation} ${operation.status} - ${operation.path}`,
328
404
  traceId,
329
405
  requestId,
406
+ deploymentId: this.deploymentId,
330
407
  duration,
331
408
  sftp: operation,
332
409
  };
@@ -338,8 +415,8 @@ class UnnboundLogger {
338
415
  * @param options - Additional logging options
339
416
  */
340
417
  dbQueryTransaction(query, options = {}) {
341
- const traceId = options.traceId || trace_context_1.traceContext.getTraceId() || (0, id_generator_1.generateUuid)();
342
- const requestId = options.requestId || (0, id_generator_1.generateUuid)();
418
+ const traceId = options.traceId || trace_context_1.traceContext.getTraceId() || (0, uuid_1.v4)();
419
+ const requestId = options.requestId || (0, uuid_1.v4)();
343
420
  const duration = options.duration || (options.startTime ? Date.now() - options.startTime : 0);
344
421
  const level = query.status === 'success' ? 'info' : 'error';
345
422
  const logEntry = {
@@ -347,6 +424,7 @@ class UnnboundLogger {
347
424
  message: `DB Query ${query.status} - ${query.vendor}`,
348
425
  traceId,
349
426
  requestId,
427
+ deploymentId: this.deploymentId,
350
428
  duration,
351
429
  db: query,
352
430
  };
@@ -0,0 +1,9 @@
1
+ interface HttpStatus {
2
+ message: string;
3
+ description: string;
4
+ }
5
+ export declare const httpStatusDetails: {
6
+ [key: number]: HttpStatus;
7
+ };
8
+ export declare function getStatusMessage(statusCode: number): string;
9
+ export {};
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.httpStatusDetails = void 0;
4
+ exports.getStatusMessage = getStatusMessage;
5
+ exports.httpStatusDetails = {
6
+ 100: { message: 'Continue', description: 'The server has received the request headers, and the client should proceed to send the request body' },
7
+ 101: { message: 'Switching Protocols', description: 'The requester has asked the server to switch protocols' },
8
+ 103: { message: 'Early Hints', description: 'Used with the Link header to allow the browser to start preloading resources while the server prepares a response' },
9
+ 200: { message: 'OK', description: 'The request is OK' },
10
+ 201: { message: 'Created', description: 'The request has been fulfilled, and a new resource is created' },
11
+ 202: { message: 'Accepted', description: 'The request has been accepted for processing, but the processing has not been completed' },
12
+ 203: { message: 'Non-Authoritative Information', description: 'The request has been successfully processed, but is returning information that may be from another source' },
13
+ 204: { message: 'No Content', description: 'The request has been successfully processed, but is not returning any content' },
14
+ 205: { message: 'Reset Content', description: 'The request has been successfully processed, but is not returning any content, and requires that the requester reset the document view' },
15
+ 206: { message: 'Partial Content', description: 'The server is delivering only part of the resource due to a range header sent by the client' },
16
+ 300: { message: 'Multiple Choices', description: 'A link list. The user can select a link and go to that location. Maximum five addresses' },
17
+ 301: { message: 'Moved Permanently', description: 'The requested page has moved to a new URL' },
18
+ 302: { message: 'Found', description: 'The requested page has moved temporarily to a new URL' },
19
+ 303: { message: 'See Other', description: 'The requested page can be found under a different URL' },
20
+ 304: { message: 'Not Modified', description: 'Indicates the requested page has not been modified since last requested' },
21
+ 307: { message: 'Temporary Redirect', description: 'The requested page has moved temporarily to a new URL' },
22
+ 308: { message: 'Permanent Redirect', description: 'The requested page has moved permanently to a new URL' },
23
+ 400: { message: 'Bad Request', description: 'The request cannot be fulfilled due to bad syntax' },
24
+ 401: { message: 'Unauthorized', description: 'The request was a legal request, but the server is refusing to respond to it. For use when authentication is possible but has failed or not yet been provided' },
25
+ 402: { message: 'Payment Required', description: 'Reserved for future use' },
26
+ 403: { message: 'Forbidden', description: 'The request was a legal request, but the server is refusing to respond to it' },
27
+ 404: { message: 'Not Found', description: 'The requested page could not be found but may be available again in the future' },
28
+ 405: { message: 'Method Not Allowed', description: 'A request was made of a page using a request method not supported by that page' },
29
+ 406: { message: 'Not Acceptable', description: 'The server can only generate a response that is not accepted by the client' },
30
+ 407: { message: 'Proxy Authentication Required', description: 'The client must first authenticate itself with the proxy' },
31
+ 408: { message: 'Request Timeout', description: 'The server timed out waiting for the request' },
32
+ 409: { message: 'Conflict', description: 'The request could not be completed because of a conflict in the request' },
33
+ 410: { message: 'Gone', description: 'The requested page is no longer available' },
34
+ 411: { message: 'Length Required', description: 'The "Content-Length" is not defined. The server will not accept the request without it' },
35
+ 412: { message: 'Precondition Failed', description: 'The precondition given in the request evaluated to false by the server' },
36
+ 413: { message: 'Request Too Large', description: 'The server will not accept the request, because the request entity is too large' },
37
+ 414: { message: 'Request-URI Too Long', description: 'The server will not accept the request, because the URI is too long. Occurs when you convert a POST request to a GET request with a long query information' },
38
+ 415: { message: 'Unsupported Media Type', description: 'The server will not accept the request, because the media type is not supported' },
39
+ 416: { message: 'Range Not Satisfiable', description: 'The client has asked for a portion of the file, but the server cannot supply that portion' },
40
+ 417: { message: 'Expectation Failed', description: 'The server cannot meet the requirements of the Expect request-header field' },
41
+ 500: { message: 'Internal Server Error', description: 'A generic error message, given when no more specific message is suitable' },
42
+ 501: { message: 'Not Implemented', description: 'The server either does not recognize the request method, or it lacks the ability to fulfill the request' },
43
+ 502: { message: 'Bad Gateway', description: 'The server was acting as a gateway or proxy and received an invalid response from the upstream server' },
44
+ 503: { message: 'Service Unavailable', description: 'The server is currently unavailable (overloaded or down)' },
45
+ 504: { message: 'Gateway Timeout', description: 'The server was acting as a gateway or proxy and did not receive a timely response from the upstream server' },
46
+ 505: { message: 'HTTP Version Not Supported', description: 'The server does not support the HTTP protocol version used in the request' },
47
+ 511: { message: 'Network Authentication Required', description: 'The client needs to authenticate to gain network access' },
48
+ };
49
+ function getStatusMessage(statusCode) {
50
+ const status = exports.httpStatusDetails[statusCode];
51
+ if (status) {
52
+ return `${status.message} - ${status.description}`;
53
+ }
54
+ return 'Unknown Status';
55
+ }
@@ -1,6 +1,19 @@
1
1
  /**
2
- * Utility functions for logging
2
+ * Generates the current timestamp in ISO format
3
+ * @returns ISO timestamp string
3
4
  */
5
+ export declare function generateTimestamp(): string;
6
+ /**
7
+ * Gets or creates a trace ID for a workflow
8
+ * @param workflowId - The workflow ID to get a trace ID for
9
+ * @returns A trace ID associated with the workflow
10
+ */
11
+ export declare function getTraceId(workflowId: string): string;
12
+ /**
13
+ * Clears a trace ID from the map
14
+ * @param workflowId - The workflow ID to clear
15
+ */
16
+ export declare function clearTraceId(workflowId: string): void;
4
17
  /**
5
18
  * Filters an object of headers, returning a new object with only the allowed headers.
6
19
  * @param headers The original headers object.
@@ -1,11 +1,44 @@
1
1
  "use strict";
2
- /**
3
- * Utility functions for logging
4
- */
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateTimestamp = generateTimestamp;
4
+ exports.getTraceId = getTraceId;
5
+ exports.clearTraceId = clearTraceId;
6
6
  exports.filterHeaders = filterHeaders;
7
7
  exports.safeJsonParse = safeJsonParse;
8
8
  exports.normalizeIp = normalizeIp;
9
+ /**
10
+ * Utility functions for logging
11
+ */
12
+ const uuid_1 = require("uuid");
13
+ /**
14
+ * Generates the current timestamp in ISO format
15
+ * @returns ISO timestamp string
16
+ */
17
+ function generateTimestamp() {
18
+ return new Date().toISOString();
19
+ }
20
+ /**
21
+ * Stores trace IDs by workflow ID for consistent tracking
22
+ */
23
+ const traceIdMap = new Map();
24
+ /**
25
+ * Gets or creates a trace ID for a workflow
26
+ * @param workflowId - The workflow ID to get a trace ID for
27
+ * @returns A trace ID associated with the workflow
28
+ */
29
+ function getTraceId(workflowId) {
30
+ if (!traceIdMap.has(workflowId)) {
31
+ traceIdMap.set(workflowId, (0, uuid_1.v4)());
32
+ }
33
+ return traceIdMap.get(workflowId);
34
+ }
35
+ /**
36
+ * Clears a trace ID from the map
37
+ * @param workflowId - The workflow ID to clear
38
+ */
39
+ function clearTraceId(workflowId) {
40
+ traceIdMap.delete(workflowId);
41
+ }
9
42
  // --- Header Allow-Listing ---
10
43
  const ALLOWED_HEADERS = new Set([
11
44
  'content-type',
@@ -1,6 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.withTrace = withTrace;
4
+ /**
5
+ * Utility function to wrap a function with trace context
6
+ */
4
7
  const uuid_1 = require("uuid");
5
8
  const trace_context_1 = require("./trace-context");
6
9
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unnbound-logger-sdk",
3
- "version": "1.1.3",
3
+ "version": "2.0.0",
4
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.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",