unnbound-logger-sdk 3.0.1 → 3.0.3
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/dist/types.d.ts +3 -1
- package/package.json +1 -1
- package/dist/http.d.ts +0 -0
- package/dist/http.js +0 -1
- package/dist/sftp.d.ts +0 -10
- package/dist/sftp.js +0 -13
- package/dist/unnbound-logger.d.ts +0 -114
- package/dist/unnbound-logger.js +0 -475
- package/dist/utils/http-status-messages.d.ts +0 -9
- package/dist/utils/http-status-messages.js +0 -160
- package/dist/utils/logger-utils.d.ts +0 -34
- package/dist/utils/logger-utils.js +0 -96
- package/dist/utils/trace-context.d.ts +0 -10
- package/dist/utils/trace-context.js +0 -23
- package/dist/utils/with-trace.d.ts +0 -7
- package/dist/utils/with-trace.js +0 -20
package/dist/types.d.ts
CHANGED
|
@@ -43,7 +43,7 @@ export interface HttpLog extends LogTransaction<'http'> {
|
|
|
43
43
|
};
|
|
44
44
|
};
|
|
45
45
|
}
|
|
46
|
-
export type SftpOperation = 'connect' | 'upload' | 'download' | 'list' | 'delete' | 'rename' | 'stat' | 'exists' | 'realPath' | 'get' | 'put' | 'cwd' | 'mkdir' | 'rmdir' | 'chmod' | 'append' | 'uploadDir' | 'downloadDir' | '
|
|
46
|
+
export type SftpOperation = 'connect' | 'upload' | 'download' | 'list' | 'delete' | 'rename' | 'stat' | 'exists' | 'realPath' | 'get' | 'put' | 'cwd' | 'mkdir' | 'rmdir' | 'chmod' | 'append' | 'uploadDir' | 'downloadDir' | 'close';
|
|
47
47
|
export interface SftpPayload {
|
|
48
48
|
host: string;
|
|
49
49
|
operation: SftpOperation;
|
|
@@ -51,6 +51,8 @@ export interface SftpPayload {
|
|
|
51
51
|
bytes?: number;
|
|
52
52
|
destinationPath?: string;
|
|
53
53
|
files?: number;
|
|
54
|
+
content?: string;
|
|
55
|
+
exists?: string | false;
|
|
54
56
|
}
|
|
55
57
|
export interface SftpLog extends LogTransaction<'sftp'> {
|
|
56
58
|
sftp: SftpPayload;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "unnbound-logger-sdk",
|
|
3
3
|
"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.",
|
|
4
|
-
"version": "3.0.
|
|
4
|
+
"version": "3.0.3",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"keywords": [
|
package/dist/http.d.ts
DELETED
|
File without changes
|
package/dist/http.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";
|
package/dist/sftp.d.ts
DELETED
package/dist/sftp.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.buildSftpPayload = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* Builds a SFTP payload
|
|
6
|
-
* @param payload - SFTP payload
|
|
7
|
-
* @returns The SFTP payload
|
|
8
|
-
*/
|
|
9
|
-
const buildSftpPayload = (payload) => ({
|
|
10
|
-
type: 'sftp',
|
|
11
|
-
sftp: payload,
|
|
12
|
-
});
|
|
13
|
-
exports.buildSftpPayload = buildSftpPayload;
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Core logger implementation
|
|
3
|
-
*/
|
|
4
|
-
import pino from 'pino';
|
|
5
|
-
import { LogLevel, LoggerOptions, GeneralLogOptions, HttpRequestLogOptions, HttpResponseLogOptions, DbQueryTransactionLogOptions, Log, HttpRequestLog, HttpResponseLog, DbQueryTransactionLog } from './types';
|
|
6
|
-
import { Request, Response, NextFunction } from 'express';
|
|
7
|
-
import { InternalAxiosRequestConfig } from 'axios';
|
|
8
|
-
declare module 'axios' {
|
|
9
|
-
interface InternalAxiosRequestConfig {
|
|
10
|
-
metadata?: {
|
|
11
|
-
startTime: number;
|
|
12
|
-
requestId?: string;
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
export declare const logger: pino.Logger;
|
|
17
|
-
/**
|
|
18
|
-
* UnnboundLogger provides typed, structured logging using Pino
|
|
19
|
-
*/
|
|
20
|
-
export declare class UnnboundLogger {
|
|
21
|
-
private logger;
|
|
22
|
-
private workflowId;
|
|
23
|
-
private workflowUrl;
|
|
24
|
-
private serviceId;
|
|
25
|
-
private deploymentId;
|
|
26
|
-
private traceHeaderKey;
|
|
27
|
-
private ignoreTraceRoutes;
|
|
28
|
-
private ignoreAxiosTraceRoutes;
|
|
29
|
-
/**
|
|
30
|
-
* Creates a new UnnboundLogger instance
|
|
31
|
-
* @param options - Configuration options for the logger
|
|
32
|
-
*/
|
|
33
|
-
constructor(options?: LoggerOptions);
|
|
34
|
-
/**
|
|
35
|
-
* Checks if a path matches any of the ignore patterns
|
|
36
|
-
* @param path - The path to check
|
|
37
|
-
* @param patterns - Array of glob patterns to match against
|
|
38
|
-
* @returns boolean indicating if the path should be ignored
|
|
39
|
-
*/
|
|
40
|
-
private shouldIgnorePath;
|
|
41
|
-
/**
|
|
42
|
-
* Logs a general message
|
|
43
|
-
* @param level - Log level
|
|
44
|
-
* @param message - Log message
|
|
45
|
-
* @param options - Additional logging options
|
|
46
|
-
*/
|
|
47
|
-
log(level: LogLevel, message: string | Error | Record<string, unknown>, options?: GeneralLogOptions): Log;
|
|
48
|
-
/**
|
|
49
|
-
* Logs an error message
|
|
50
|
-
* @param message - Error message or object
|
|
51
|
-
* @param options - Additional logging options
|
|
52
|
-
*/
|
|
53
|
-
error(message: string | Error | Record<string, unknown>, options?: GeneralLogOptions): Log;
|
|
54
|
-
/**
|
|
55
|
-
* Logs a warning message
|
|
56
|
-
* @param message - Warning message
|
|
57
|
-
* @param options - Additional logging options
|
|
58
|
-
*/
|
|
59
|
-
warn(message: string | Error | Record<string, unknown>, options?: GeneralLogOptions): Log;
|
|
60
|
-
/**
|
|
61
|
-
* Logs an info message
|
|
62
|
-
* @param message - Info message
|
|
63
|
-
* @param options - Additional logging options
|
|
64
|
-
*/
|
|
65
|
-
info(message: string | Error | Record<string, unknown>, options?: GeneralLogOptions): Log;
|
|
66
|
-
/**
|
|
67
|
-
* Logs a debug message
|
|
68
|
-
* @param message - Debug message
|
|
69
|
-
* @param options - Additional logging options
|
|
70
|
-
*/
|
|
71
|
-
debug(message: string | Error | Record<string, unknown>, options?: GeneralLogOptions): Log;
|
|
72
|
-
/**
|
|
73
|
-
* Constructs the full URL from request information
|
|
74
|
-
* @param req - Express request object
|
|
75
|
-
* @returns Full URL string
|
|
76
|
-
*/
|
|
77
|
-
private constructFullUrl;
|
|
78
|
-
/**
|
|
79
|
-
* Logs an HTTP request
|
|
80
|
-
* @param req - Express request object
|
|
81
|
-
* @param options - Additional logging options
|
|
82
|
-
* @returns The request ID for correlating with the response
|
|
83
|
-
*/
|
|
84
|
-
httpRequest(req: Request, options?: HttpRequestLogOptions): HttpRequestLog;
|
|
85
|
-
/**
|
|
86
|
-
* Logs an HTTP response
|
|
87
|
-
* @param res - Express response object
|
|
88
|
-
* @param req - Express request object
|
|
89
|
-
* @param options - Additional logging options
|
|
90
|
-
*/
|
|
91
|
-
httpResponse(res: Response, req: Request, options?: HttpResponseLogOptions): HttpResponseLog;
|
|
92
|
-
/**
|
|
93
|
-
* Logs a database query transaction
|
|
94
|
-
* @param query - Database query details
|
|
95
|
-
* @param options - Additional logging options
|
|
96
|
-
*/
|
|
97
|
-
dbQueryTransaction(query: {
|
|
98
|
-
instance: string;
|
|
99
|
-
vendor: 'postgres' | 'mysql' | 'mssql' | 'mongodb';
|
|
100
|
-
query?: string;
|
|
101
|
-
status: 'success' | 'failure';
|
|
102
|
-
rowsReturned?: number;
|
|
103
|
-
rowsAffected?: number;
|
|
104
|
-
}, options?: DbQueryTransactionLogOptions): DbQueryTransactionLog;
|
|
105
|
-
traceMiddleware: (req: Request, res: Response, next: NextFunction) => void;
|
|
106
|
-
axiosTraceMiddleware: {
|
|
107
|
-
onFulfilled: (config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig;
|
|
108
|
-
onRejected: (error: any) => any;
|
|
109
|
-
};
|
|
110
|
-
axiosResponseInterceptor: {
|
|
111
|
-
onFulfilled: (response: any) => any;
|
|
112
|
-
onRejected: (error: any) => any;
|
|
113
|
-
};
|
|
114
|
-
}
|
package/dist/unnbound-logger.js
DELETED
|
@@ -1,475 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.UnnboundLogger = exports.logger = void 0;
|
|
7
|
-
/**
|
|
8
|
-
* Core logger implementation
|
|
9
|
-
*/
|
|
10
|
-
const pino_1 = __importDefault(require("pino"));
|
|
11
|
-
const logger_utils_1 = require("./utils/logger-utils");
|
|
12
|
-
const uuid_1 = require("uuid");
|
|
13
|
-
const trace_context_1 = require("./utils/trace-context");
|
|
14
|
-
const axios_1 = require("axios");
|
|
15
|
-
const http_status_messages_1 = require("./utils/http-status-messages");
|
|
16
|
-
const storage_1 = require("./storage");
|
|
17
|
-
exports.logger = (0, pino_1.default)({
|
|
18
|
-
level: process.env.LOG_LEVEL ?? 'info',
|
|
19
|
-
base: {
|
|
20
|
-
environment: process.env.ENVIRONMENT,
|
|
21
|
-
workflowId: process.env.UNNBOUND_WORKFLOW_ID,
|
|
22
|
-
workflowUrl: process.env.UNNBOUND_WORKFLOW_URL,
|
|
23
|
-
serviceId: process.env.UNNBOUND_SERVICE_ID,
|
|
24
|
-
deploymentId: process.env.UNNBOUND_DEPLOYMENT_ID,
|
|
25
|
-
},
|
|
26
|
-
mixin: () => {
|
|
27
|
-
console.log('storage', storage_1.storage.getStore());
|
|
28
|
-
return storage_1.storage.getStore() ?? {};
|
|
29
|
-
},
|
|
30
|
-
serializers: {
|
|
31
|
-
req: pino_1.default.stdSerializers.req,
|
|
32
|
-
res: pino_1.default.stdSerializers.res,
|
|
33
|
-
err: pino_1.default.stdSerializers.err,
|
|
34
|
-
},
|
|
35
|
-
// Let CloudWatch handle timestamps
|
|
36
|
-
timestamp: false,
|
|
37
|
-
// Change message field from 'msg' to 'messages'
|
|
38
|
-
messageKey: 'messages',
|
|
39
|
-
formatters: {
|
|
40
|
-
level: (level) => ({ level }),
|
|
41
|
-
},
|
|
42
|
-
});
|
|
43
|
-
/**
|
|
44
|
-
* UnnboundLogger provides typed, structured logging using Pino
|
|
45
|
-
*/
|
|
46
|
-
class UnnboundLogger {
|
|
47
|
-
/**
|
|
48
|
-
* Creates a new UnnboundLogger instance
|
|
49
|
-
* @param options - Configuration options for the logger
|
|
50
|
-
*/
|
|
51
|
-
constructor(options = {}) {
|
|
52
|
-
// Trace middleware
|
|
53
|
-
this.traceMiddleware = (req, res, next) => {
|
|
54
|
-
// Check if the route should be ignored
|
|
55
|
-
if (this.shouldIgnorePath(req.path, this.ignoreTraceRoutes)) {
|
|
56
|
-
return next();
|
|
57
|
-
}
|
|
58
|
-
const traceId = req.header(this.traceHeaderKey) || (0, uuid_1.v4)();
|
|
59
|
-
res.setHeader(this.traceHeaderKey, traceId);
|
|
60
|
-
trace_context_1.traceContext.run(traceId, () => {
|
|
61
|
-
// Log the incoming request
|
|
62
|
-
const reqLog = this.httpRequest(req, { traceId });
|
|
63
|
-
// Capture response body for logging
|
|
64
|
-
const originalSend = res.send;
|
|
65
|
-
res.send = function (body) {
|
|
66
|
-
res.locals.body = body;
|
|
67
|
-
return originalSend.call(this, body);
|
|
68
|
-
};
|
|
69
|
-
// Log the response when it finishes
|
|
70
|
-
res.on('finish', () => {
|
|
71
|
-
this.httpResponse(res, req, { requestId: reqLog.requestId, traceId });
|
|
72
|
-
});
|
|
73
|
-
next();
|
|
74
|
-
});
|
|
75
|
-
};
|
|
76
|
-
// Axios trace middleware
|
|
77
|
-
this.axiosTraceMiddleware = {
|
|
78
|
-
onFulfilled: (config) => {
|
|
79
|
-
// Check if the URL should be ignored
|
|
80
|
-
if (config.url && this.shouldIgnorePath(config.url, this.ignoreAxiosTraceRoutes)) {
|
|
81
|
-
return config;
|
|
82
|
-
}
|
|
83
|
-
const traceId = trace_context_1.traceContext.getTraceId();
|
|
84
|
-
if (traceId) {
|
|
85
|
-
const headers = new axios_1.AxiosHeaders(config.headers);
|
|
86
|
-
headers.set(this.traceHeaderKey, traceId);
|
|
87
|
-
config.headers = headers;
|
|
88
|
-
}
|
|
89
|
-
// Store request start time and generate requestId for duration calculation and correlation
|
|
90
|
-
const startTime = Date.now();
|
|
91
|
-
const requestId = (0, uuid_1.v4)();
|
|
92
|
-
config.metadata = { startTime, requestId };
|
|
93
|
-
// Log the outgoing request using proper httpRequest method
|
|
94
|
-
const mockReq = {
|
|
95
|
-
method: config.method?.toUpperCase() || 'UNKNOWN',
|
|
96
|
-
url: `${config.baseURL || ''}${config.url}`,
|
|
97
|
-
originalUrl: `${config.baseURL || ''}${config.url}`,
|
|
98
|
-
headers: config.headers || {},
|
|
99
|
-
body: (0, logger_utils_1.safeJsonParse)(config.data),
|
|
100
|
-
ip: 'outgoing', // Mark as outgoing request
|
|
101
|
-
protocol: 'https', // Default for outgoing
|
|
102
|
-
secure: true,
|
|
103
|
-
get: () => undefined, // Mock get method for constructFullUrl
|
|
104
|
-
};
|
|
105
|
-
this.httpRequest(mockReq, {
|
|
106
|
-
traceId,
|
|
107
|
-
requestId,
|
|
108
|
-
startTime,
|
|
109
|
-
});
|
|
110
|
-
return config;
|
|
111
|
-
},
|
|
112
|
-
onRejected: (error) => {
|
|
113
|
-
return Promise.reject(error);
|
|
114
|
-
},
|
|
115
|
-
};
|
|
116
|
-
// Axios response interceptor (should be used separately)
|
|
117
|
-
this.axiosResponseInterceptor = {
|
|
118
|
-
onFulfilled: (response) => {
|
|
119
|
-
// Check if the URL should be ignored
|
|
120
|
-
const url = `${response.config?.baseURL || ''}${response.config?.url}`;
|
|
121
|
-
if (url && this.shouldIgnorePath(url, this.ignoreAxiosTraceRoutes)) {
|
|
122
|
-
return response;
|
|
123
|
-
}
|
|
124
|
-
// Calculate duration
|
|
125
|
-
const startTime = response.config.metadata?.startTime || Date.now();
|
|
126
|
-
const requestId = response.config.metadata?.requestId;
|
|
127
|
-
const duration = Date.now() - startTime;
|
|
128
|
-
// Log the successful response using proper httpResponse method
|
|
129
|
-
const mockReq = {
|
|
130
|
-
method: response.config.method?.toUpperCase() || 'UNKNOWN',
|
|
131
|
-
url: `${response.config.baseURL || ''}${response.config.url}`,
|
|
132
|
-
originalUrl: `${response.config.baseURL || ''}${response.config.url}`,
|
|
133
|
-
ip: 'outgoing', // Mark as outgoing request
|
|
134
|
-
protocol: 'https', // Default for outgoing
|
|
135
|
-
secure: true,
|
|
136
|
-
get: () => undefined, // Mock get method for constructFullUrl
|
|
137
|
-
};
|
|
138
|
-
const mockRes = {
|
|
139
|
-
statusCode: response.status,
|
|
140
|
-
locals: {
|
|
141
|
-
body: (0, logger_utils_1.safeJsonParse)(response.data),
|
|
142
|
-
startTime: startTime,
|
|
143
|
-
traceId: trace_context_1.traceContext.getTraceId(),
|
|
144
|
-
requestId: requestId,
|
|
145
|
-
},
|
|
146
|
-
getHeaders: () => response.headers || {},
|
|
147
|
-
};
|
|
148
|
-
this.httpResponse(mockRes, mockReq, {
|
|
149
|
-
requestId,
|
|
150
|
-
duration,
|
|
151
|
-
traceId: trace_context_1.traceContext.getTraceId(),
|
|
152
|
-
});
|
|
153
|
-
return response;
|
|
154
|
-
},
|
|
155
|
-
onRejected: (error) => {
|
|
156
|
-
// Check if the URL should be ignored
|
|
157
|
-
const url = `${error.config?.baseURL || ''}${error.config?.url}`;
|
|
158
|
-
if (url && this.shouldIgnorePath(url, this.ignoreAxiosTraceRoutes)) {
|
|
159
|
-
return Promise.reject(error);
|
|
160
|
-
}
|
|
161
|
-
// Calculate duration for error responses
|
|
162
|
-
const startTime = error.config?.metadata?.startTime || Date.now();
|
|
163
|
-
const requestId = error.config?.metadata?.requestId;
|
|
164
|
-
const duration = Date.now() - startTime;
|
|
165
|
-
// Log the error response using proper httpResponse method
|
|
166
|
-
if (error.response) {
|
|
167
|
-
const mockReq = {
|
|
168
|
-
method: error.config?.method?.toUpperCase() || 'UNKNOWN',
|
|
169
|
-
url: `${error.config?.baseURL || ''}${error.config?.url}`,
|
|
170
|
-
originalUrl: `${error.config?.baseURL || ''}${error.config?.url}`,
|
|
171
|
-
ip: 'outgoing', // Mark as outgoing request
|
|
172
|
-
protocol: 'https', // Default for outgoing
|
|
173
|
-
secure: true,
|
|
174
|
-
get: () => undefined, // Mock get method for constructFullUrl
|
|
175
|
-
};
|
|
176
|
-
const mockRes = {
|
|
177
|
-
statusCode: error.response.status,
|
|
178
|
-
locals: {
|
|
179
|
-
body: (0, logger_utils_1.safeJsonParse)(error.response.data),
|
|
180
|
-
startTime: startTime,
|
|
181
|
-
traceId: trace_context_1.traceContext.getTraceId(),
|
|
182
|
-
requestId: requestId,
|
|
183
|
-
},
|
|
184
|
-
getHeaders: () => error.response.headers || {},
|
|
185
|
-
};
|
|
186
|
-
this.httpResponse(mockRes, mockReq, {
|
|
187
|
-
requestId,
|
|
188
|
-
duration,
|
|
189
|
-
traceId: trace_context_1.traceContext.getTraceId(),
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
// For network errors without response, log as general error
|
|
194
|
-
this.error('HTTP Request Failed', {
|
|
195
|
-
context: {
|
|
196
|
-
reason: 'No response received',
|
|
197
|
-
method: error.config?.method?.toUpperCase() || 'UNKNOWN',
|
|
198
|
-
url: `${error.config?.baseURL || ''}${error.config?.url}`,
|
|
199
|
-
},
|
|
200
|
-
error: error.message,
|
|
201
|
-
requestId,
|
|
202
|
-
traceId: trace_context_1.traceContext.getTraceId(),
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
return Promise.reject(error);
|
|
206
|
-
},
|
|
207
|
-
};
|
|
208
|
-
this.workflowId = process.env.UNNBOUND_WORKFLOW_ID || '';
|
|
209
|
-
this.workflowUrl = process.env.UNNBOUND_WORKFLOW_URL || '';
|
|
210
|
-
this.serviceId = process.env.UNNBOUND_SERVICE_ID || '';
|
|
211
|
-
this.deploymentId = process.env.UNNBOUND_DEPLOYMENT_ID || '';
|
|
212
|
-
this.traceHeaderKey = options.traceHeaderKey || 'unnbound-trace-id';
|
|
213
|
-
this.ignoreTraceRoutes = options.ignoreTraceRoutes || [];
|
|
214
|
-
this.ignoreAxiosTraceRoutes = options.ignoreAxiosTraceRoutes || [];
|
|
215
|
-
// Create Pino logger
|
|
216
|
-
this.logger = (0, pino_1.default)({
|
|
217
|
-
level: 'info',
|
|
218
|
-
base: {
|
|
219
|
-
// Disable all default base fields (pid, hostname) and add our own
|
|
220
|
-
workflowId: this.workflowId,
|
|
221
|
-
serviceId: this.serviceId,
|
|
222
|
-
deploymentId: this.deploymentId,
|
|
223
|
-
},
|
|
224
|
-
// Let CloudWatch handle timestamps
|
|
225
|
-
timestamp: false,
|
|
226
|
-
// Change message field from 'msg' to 'messages'
|
|
227
|
-
messageKey: 'messages',
|
|
228
|
-
formatters: {
|
|
229
|
-
level: (level) => ({ level }),
|
|
230
|
-
},
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
/**
|
|
234
|
-
* Checks if a path matches any of the ignore patterns
|
|
235
|
-
* @param path - The path to check
|
|
236
|
-
* @param patterns - Array of glob patterns to match against
|
|
237
|
-
* @returns boolean indicating if the path should be ignored
|
|
238
|
-
*/
|
|
239
|
-
shouldIgnorePath(path, patterns) {
|
|
240
|
-
return patterns.some((pattern) => {
|
|
241
|
-
// Convert glob pattern to regex
|
|
242
|
-
const regexPattern = pattern
|
|
243
|
-
.replace(/\./g, '\\.') // Escape dots
|
|
244
|
-
.replace(/\*/g, '.*') // Convert * to .*
|
|
245
|
-
.replace(/\?/g, '.'); // Convert ? to .
|
|
246
|
-
const regex = new RegExp(`^${regexPattern}$`);
|
|
247
|
-
return regex.test(path);
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
/**
|
|
251
|
-
* Logs a general message
|
|
252
|
-
* @param level - Log level
|
|
253
|
-
* @param message - Log message
|
|
254
|
-
* @param options - Additional logging options
|
|
255
|
-
*/
|
|
256
|
-
log(level, message, options = {}) {
|
|
257
|
-
const logId = (0, uuid_1.v4)();
|
|
258
|
-
const traceId = options.traceId || trace_context_1.traceContext.getTraceId() || (0, uuid_1.v4)();
|
|
259
|
-
const requestId = options.requestId || (0, uuid_1.v4)();
|
|
260
|
-
let logEntry;
|
|
261
|
-
const { traceId: optionTraceId, requestId: optionRequestId, level: optionLevel, ...restOptions } = options;
|
|
262
|
-
// If restOptions has any properties, we'll add them to data later
|
|
263
|
-
const hasRestOptions = Object.keys(restOptions).length > 0;
|
|
264
|
-
const baseEntry = {
|
|
265
|
-
logId,
|
|
266
|
-
type: 'general',
|
|
267
|
-
workflowId: this.workflowId,
|
|
268
|
-
serviceId: this.serviceId,
|
|
269
|
-
traceId,
|
|
270
|
-
requestId,
|
|
271
|
-
deploymentId: this.deploymentId,
|
|
272
|
-
};
|
|
273
|
-
if (message instanceof Error) {
|
|
274
|
-
logEntry = {
|
|
275
|
-
...baseEntry,
|
|
276
|
-
message: message.name,
|
|
277
|
-
error: message,
|
|
278
|
-
...(hasRestOptions && { data: restOptions }),
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
else if (typeof message === 'string') {
|
|
282
|
-
logEntry = {
|
|
283
|
-
...baseEntry,
|
|
284
|
-
message,
|
|
285
|
-
...(hasRestOptions && { data: restOptions }),
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
|
-
else {
|
|
289
|
-
// If message is an object, wrap it in a 'data' key
|
|
290
|
-
const messageObj = message;
|
|
291
|
-
logEntry = {
|
|
292
|
-
...baseEntry,
|
|
293
|
-
message: 'Structured log data',
|
|
294
|
-
data: hasRestOptions ? { ...messageObj, ...restOptions } : messageObj,
|
|
295
|
-
};
|
|
296
|
-
}
|
|
297
|
-
// Separate the message from the log data and explicitly exclude any level field
|
|
298
|
-
const { message: logMessage, level: excludedLevel, ...logData } = logEntry;
|
|
299
|
-
this.logger[level](logData, logMessage);
|
|
300
|
-
return logEntry;
|
|
301
|
-
}
|
|
302
|
-
/**
|
|
303
|
-
* Logs an error message
|
|
304
|
-
* @param message - Error message or object
|
|
305
|
-
* @param options - Additional logging options
|
|
306
|
-
*/
|
|
307
|
-
error(message, options = {}) {
|
|
308
|
-
return this.log('error', message, options);
|
|
309
|
-
}
|
|
310
|
-
/**
|
|
311
|
-
* Logs a warning message
|
|
312
|
-
* @param message - Warning message
|
|
313
|
-
* @param options - Additional logging options
|
|
314
|
-
*/
|
|
315
|
-
warn(message, options = {}) {
|
|
316
|
-
return this.log('warn', message, options);
|
|
317
|
-
}
|
|
318
|
-
/**
|
|
319
|
-
* Logs an info message
|
|
320
|
-
* @param message - Info message
|
|
321
|
-
* @param options - Additional logging options
|
|
322
|
-
*/
|
|
323
|
-
info(message, options = {}) {
|
|
324
|
-
return this.log('info', message, options);
|
|
325
|
-
}
|
|
326
|
-
/**
|
|
327
|
-
* Logs a debug message
|
|
328
|
-
* @param message - Debug message
|
|
329
|
-
* @param options - Additional logging options
|
|
330
|
-
*/
|
|
331
|
-
debug(message, options = {}) {
|
|
332
|
-
return this.log('debug', message, options);
|
|
333
|
-
}
|
|
334
|
-
/**
|
|
335
|
-
* Constructs the full URL from request information
|
|
336
|
-
* @param req - Express request object
|
|
337
|
-
* @returns Full URL string
|
|
338
|
-
*/
|
|
339
|
-
constructFullUrl(req) {
|
|
340
|
-
// If the URL is already absolute, return it directly
|
|
341
|
-
const reqUrl = req.originalUrl || req.url;
|
|
342
|
-
if (reqUrl?.startsWith('http://') || reqUrl?.startsWith('https://')) {
|
|
343
|
-
return reqUrl;
|
|
344
|
-
}
|
|
345
|
-
// Check if we have a workflow URL configured (preferred method)
|
|
346
|
-
if (this.workflowUrl) {
|
|
347
|
-
// Use workflow URL as the base URL
|
|
348
|
-
return `${this.workflowUrl.replace(/\/$/, '')}${reqUrl}`;
|
|
349
|
-
}
|
|
350
|
-
// Fallback to constructing from request info for incoming requests
|
|
351
|
-
const protocol = req.protocol || (req.secure ? 'https' : 'http');
|
|
352
|
-
const host = req.get('host') || req.get('x-forwarded-host') || 'localhost';
|
|
353
|
-
return `${protocol}://${host}${reqUrl}`;
|
|
354
|
-
}
|
|
355
|
-
/**
|
|
356
|
-
* Logs an HTTP request
|
|
357
|
-
* @param req - Express request object
|
|
358
|
-
* @param options - Additional logging options
|
|
359
|
-
* @returns The request ID for correlating with the response
|
|
360
|
-
*/
|
|
361
|
-
httpRequest(req, options = {}) {
|
|
362
|
-
const logId = (0, uuid_1.v4)();
|
|
363
|
-
const traceId = options.traceId || trace_context_1.traceContext.getTraceId() || (0, uuid_1.v4)();
|
|
364
|
-
const requestId = options.requestId || (0, uuid_1.v4)();
|
|
365
|
-
const startTime = options.startTime || Date.now();
|
|
366
|
-
// Store request metadata in res.locals for later use
|
|
367
|
-
if (req.res) {
|
|
368
|
-
req.res.locals.requestId = requestId;
|
|
369
|
-
req.res.locals.startTime = startTime;
|
|
370
|
-
req.res.locals.traceId = traceId;
|
|
371
|
-
req.res.locals.workflowId = this.workflowId;
|
|
372
|
-
req.res.locals.workflowUrl = this.workflowUrl;
|
|
373
|
-
req.res.locals.serviceId = this.serviceId;
|
|
374
|
-
}
|
|
375
|
-
const logEntry = {
|
|
376
|
-
logId,
|
|
377
|
-
type: 'httpRequest',
|
|
378
|
-
message: req.ip === 'outgoing' ? 'Outgoing HTTP Request' : 'Incoming HTTP Request',
|
|
379
|
-
workflowId: this.workflowId,
|
|
380
|
-
serviceId: this.serviceId,
|
|
381
|
-
traceId,
|
|
382
|
-
requestId,
|
|
383
|
-
deploymentId: this.deploymentId,
|
|
384
|
-
duration: 0, // Will be updated in response
|
|
385
|
-
httpRequest: {
|
|
386
|
-
url: this.constructFullUrl(req),
|
|
387
|
-
method: req.method,
|
|
388
|
-
headers: (0, logger_utils_1.filterHeaders)(req.headers),
|
|
389
|
-
ip: (0, logger_utils_1.normalizeIp)(req.ip),
|
|
390
|
-
body: (0, logger_utils_1.safeJsonParse)(req.body),
|
|
391
|
-
},
|
|
392
|
-
};
|
|
393
|
-
const { message: logMessage, ...logData } = logEntry;
|
|
394
|
-
this.logger[options.level || 'info'](logData, logMessage);
|
|
395
|
-
return logEntry;
|
|
396
|
-
}
|
|
397
|
-
/**
|
|
398
|
-
* Logs an HTTP response
|
|
399
|
-
* @param res - Express response object
|
|
400
|
-
* @param req - Express request object
|
|
401
|
-
* @param options - Additional logging options
|
|
402
|
-
*/
|
|
403
|
-
httpResponse(res, req, options = {}) {
|
|
404
|
-
const logId = (0, uuid_1.v4)();
|
|
405
|
-
const requestId = res.locals.requestId || options.requestId || (0, uuid_1.v4)();
|
|
406
|
-
const startTime = res.locals.startTime || options.startTime || Date.now();
|
|
407
|
-
const workflowId = res.locals.workflowId || this.workflowId;
|
|
408
|
-
const serviceId = res.locals.serviceId || this.serviceId;
|
|
409
|
-
const traceId = res.locals.traceId || options.traceId || trace_context_1.traceContext.getTraceId() || (0, uuid_1.v4)();
|
|
410
|
-
const duration = options.duration || Date.now() - startTime;
|
|
411
|
-
// Determine log level based on status code
|
|
412
|
-
let level = options.level || 'info';
|
|
413
|
-
if (!options.level) {
|
|
414
|
-
if (res.statusCode >= 400) {
|
|
415
|
-
level = 'error';
|
|
416
|
-
}
|
|
417
|
-
else {
|
|
418
|
-
level = 'info';
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
const logEntry = {
|
|
422
|
-
logId,
|
|
423
|
-
type: 'httpResponse',
|
|
424
|
-
message: (0, http_status_messages_1.getStatusMessage)(res.statusCode),
|
|
425
|
-
workflowId: workflowId || '',
|
|
426
|
-
serviceId: serviceId || '',
|
|
427
|
-
traceId,
|
|
428
|
-
requestId,
|
|
429
|
-
deploymentId: this.deploymentId,
|
|
430
|
-
duration,
|
|
431
|
-
httpResponse: {
|
|
432
|
-
url: this.constructFullUrl(req),
|
|
433
|
-
method: req.method,
|
|
434
|
-
headers: (0, logger_utils_1.filterHeaders)(res.getHeaders()),
|
|
435
|
-
ip: (0, logger_utils_1.normalizeIp)(req.ip),
|
|
436
|
-
status: res.statusCode,
|
|
437
|
-
body: (0, logger_utils_1.safeJsonParse)(res.locals.body),
|
|
438
|
-
},
|
|
439
|
-
};
|
|
440
|
-
const { message: logMessage, ...logData } = logEntry;
|
|
441
|
-
this.logger[level](logData, logMessage);
|
|
442
|
-
return logEntry;
|
|
443
|
-
}
|
|
444
|
-
/**
|
|
445
|
-
* Logs a database query transaction
|
|
446
|
-
* @param query - Database query details
|
|
447
|
-
* @param options - Additional logging options
|
|
448
|
-
*/
|
|
449
|
-
dbQueryTransaction(query, options = {}) {
|
|
450
|
-
const logId = (0, uuid_1.v4)();
|
|
451
|
-
const traceId = options.traceId || trace_context_1.traceContext.getTraceId() || (0, uuid_1.v4)();
|
|
452
|
-
const requestId = options.requestId || (0, uuid_1.v4)();
|
|
453
|
-
const duration = options.duration || (options.startTime ? Date.now() - options.startTime : 0);
|
|
454
|
-
const level = query.status === 'success' ? 'info' : 'error';
|
|
455
|
-
const logEntry = {
|
|
456
|
-
logId,
|
|
457
|
-
type: 'dbQueryTransaction',
|
|
458
|
-
message: `DB Query ${query.status} - ${query.vendor}`,
|
|
459
|
-
workflowId: this.workflowId,
|
|
460
|
-
serviceId: this.serviceId,
|
|
461
|
-
traceId,
|
|
462
|
-
requestId,
|
|
463
|
-
deploymentId: this.deploymentId,
|
|
464
|
-
duration,
|
|
465
|
-
db: query,
|
|
466
|
-
};
|
|
467
|
-
const { message: logMessage, ...logData } = logEntry;
|
|
468
|
-
this.logger[level](logData, logMessage);
|
|
469
|
-
return logEntry;
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
exports.UnnboundLogger = UnnboundLogger;
|
|
473
|
-
process.on('uncaughtException', (err, origin) => {
|
|
474
|
-
exports.logger.error({ err, origin }, `Uncaught exception.`);
|
|
475
|
-
});
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.httpStatusDetails = void 0;
|
|
4
|
-
exports.getStatusMessage = getStatusMessage;
|
|
5
|
-
exports.httpStatusDetails = {
|
|
6
|
-
100: {
|
|
7
|
-
message: 'Continue',
|
|
8
|
-
description: 'The server has received the request headers, and the client should proceed to send the request body',
|
|
9
|
-
},
|
|
10
|
-
101: {
|
|
11
|
-
message: 'Switching Protocols',
|
|
12
|
-
description: 'The requester has asked the server to switch protocols',
|
|
13
|
-
},
|
|
14
|
-
103: {
|
|
15
|
-
message: 'Early Hints',
|
|
16
|
-
description: 'Used with the Link header to allow the browser to start preloading resources while the server prepares a response',
|
|
17
|
-
},
|
|
18
|
-
200: { message: 'OK', description: 'The request is OK' },
|
|
19
|
-
201: {
|
|
20
|
-
message: 'Created',
|
|
21
|
-
description: 'The request has been fulfilled, and a new resource is created',
|
|
22
|
-
},
|
|
23
|
-
202: {
|
|
24
|
-
message: 'Accepted',
|
|
25
|
-
description: 'The request has been accepted for processing, but the processing has not been completed',
|
|
26
|
-
},
|
|
27
|
-
203: {
|
|
28
|
-
message: 'Non-Authoritative Information',
|
|
29
|
-
description: 'The request has been successfully processed, but is returning information that may be from another source',
|
|
30
|
-
},
|
|
31
|
-
204: {
|
|
32
|
-
message: 'No Content',
|
|
33
|
-
description: 'The request has been successfully processed, but is not returning any content',
|
|
34
|
-
},
|
|
35
|
-
205: {
|
|
36
|
-
message: 'Reset Content',
|
|
37
|
-
description: 'The request has been successfully processed, but is not returning any content, and requires that the requester reset the document view',
|
|
38
|
-
},
|
|
39
|
-
206: {
|
|
40
|
-
message: 'Partial Content',
|
|
41
|
-
description: 'The server is delivering only part of the resource due to a range header sent by the client',
|
|
42
|
-
},
|
|
43
|
-
300: {
|
|
44
|
-
message: 'Multiple Choices',
|
|
45
|
-
description: 'A link list. The user can select a link and go to that location. Maximum five addresses',
|
|
46
|
-
},
|
|
47
|
-
301: { message: 'Moved Permanently', description: 'The requested page has moved to a new URL' },
|
|
48
|
-
302: { message: 'Found', description: 'The requested page has moved temporarily to a new URL' },
|
|
49
|
-
303: {
|
|
50
|
-
message: 'See Other',
|
|
51
|
-
description: 'The requested page can be found under a different URL',
|
|
52
|
-
},
|
|
53
|
-
304: {
|
|
54
|
-
message: 'Not Modified',
|
|
55
|
-
description: 'Indicates the requested page has not been modified since last requested',
|
|
56
|
-
},
|
|
57
|
-
307: {
|
|
58
|
-
message: 'Temporary Redirect',
|
|
59
|
-
description: 'The requested page has moved temporarily to a new URL',
|
|
60
|
-
},
|
|
61
|
-
308: {
|
|
62
|
-
message: 'Permanent Redirect',
|
|
63
|
-
description: 'The requested page has moved permanently to a new URL',
|
|
64
|
-
},
|
|
65
|
-
400: { message: 'Bad Request', description: 'The request cannot be fulfilled due to bad syntax' },
|
|
66
|
-
401: {
|
|
67
|
-
message: 'Unauthorized',
|
|
68
|
-
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',
|
|
69
|
-
},
|
|
70
|
-
402: { message: 'Payment Required', description: 'Reserved for future use' },
|
|
71
|
-
403: {
|
|
72
|
-
message: 'Forbidden',
|
|
73
|
-
description: 'The request was a legal request, but the server is refusing to respond to it',
|
|
74
|
-
},
|
|
75
|
-
404: {
|
|
76
|
-
message: 'Not Found',
|
|
77
|
-
description: 'The requested page could not be found but may be available again in the future',
|
|
78
|
-
},
|
|
79
|
-
405: {
|
|
80
|
-
message: 'Method Not Allowed',
|
|
81
|
-
description: 'A request was made of a page using a request method not supported by that page',
|
|
82
|
-
},
|
|
83
|
-
406: {
|
|
84
|
-
message: 'Not Acceptable',
|
|
85
|
-
description: 'The server can only generate a response that is not accepted by the client',
|
|
86
|
-
},
|
|
87
|
-
407: {
|
|
88
|
-
message: 'Proxy Authentication Required',
|
|
89
|
-
description: 'The client must first authenticate itself with the proxy',
|
|
90
|
-
},
|
|
91
|
-
408: { message: 'Request Timeout', description: 'The server timed out waiting for the request' },
|
|
92
|
-
409: {
|
|
93
|
-
message: 'Conflict',
|
|
94
|
-
description: 'The request could not be completed because of a conflict in the request',
|
|
95
|
-
},
|
|
96
|
-
410: { message: 'Gone', description: 'The requested page is no longer available' },
|
|
97
|
-
411: {
|
|
98
|
-
message: 'Length Required',
|
|
99
|
-
description: 'The "Content-Length" is not defined. The server will not accept the request without it',
|
|
100
|
-
},
|
|
101
|
-
412: {
|
|
102
|
-
message: 'Precondition Failed',
|
|
103
|
-
description: 'The precondition given in the request evaluated to false by the server',
|
|
104
|
-
},
|
|
105
|
-
413: {
|
|
106
|
-
message: 'Request Too Large',
|
|
107
|
-
description: 'The server will not accept the request, because the request entity is too large',
|
|
108
|
-
},
|
|
109
|
-
414: {
|
|
110
|
-
message: 'Request-URI Too Long',
|
|
111
|
-
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',
|
|
112
|
-
},
|
|
113
|
-
415: {
|
|
114
|
-
message: 'Unsupported Media Type',
|
|
115
|
-
description: 'The server will not accept the request, because the media type is not supported',
|
|
116
|
-
},
|
|
117
|
-
416: {
|
|
118
|
-
message: 'Range Not Satisfiable',
|
|
119
|
-
description: 'The client has asked for a portion of the file, but the server cannot supply that portion',
|
|
120
|
-
},
|
|
121
|
-
417: {
|
|
122
|
-
message: 'Expectation Failed',
|
|
123
|
-
description: 'The server cannot meet the requirements of the Expect request-header field',
|
|
124
|
-
},
|
|
125
|
-
500: {
|
|
126
|
-
message: 'Internal Server Error',
|
|
127
|
-
description: 'A generic error message, given when no more specific message is suitable',
|
|
128
|
-
},
|
|
129
|
-
501: {
|
|
130
|
-
message: 'Not Implemented',
|
|
131
|
-
description: 'The server either does not recognize the request method, or it lacks the ability to fulfill the request',
|
|
132
|
-
},
|
|
133
|
-
502: {
|
|
134
|
-
message: 'Bad Gateway',
|
|
135
|
-
description: 'The server was acting as a gateway or proxy and received an invalid response from the upstream server',
|
|
136
|
-
},
|
|
137
|
-
503: {
|
|
138
|
-
message: 'Service Unavailable',
|
|
139
|
-
description: 'The server is currently unavailable (overloaded or down)',
|
|
140
|
-
},
|
|
141
|
-
504: {
|
|
142
|
-
message: 'Gateway Timeout',
|
|
143
|
-
description: 'The server was acting as a gateway or proxy and did not receive a timely response from the upstream server',
|
|
144
|
-
},
|
|
145
|
-
505: {
|
|
146
|
-
message: 'HTTP Version Not Supported',
|
|
147
|
-
description: 'The server does not support the HTTP protocol version used in the request',
|
|
148
|
-
},
|
|
149
|
-
511: {
|
|
150
|
-
message: 'Network Authentication Required',
|
|
151
|
-
description: 'The client needs to authenticate to gain network access',
|
|
152
|
-
},
|
|
153
|
-
};
|
|
154
|
-
function getStatusMessage(statusCode) {
|
|
155
|
-
const status = exports.httpStatusDetails[statusCode];
|
|
156
|
-
if (status) {
|
|
157
|
-
return `${statusCode} ${status.message} - ${status.description}`;
|
|
158
|
-
}
|
|
159
|
-
return `${statusCode} Unknown Status`;
|
|
160
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generates the current timestamp in ISO format
|
|
3
|
-
* @returns ISO timestamp string
|
|
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;
|
|
17
|
-
/**
|
|
18
|
-
* Filters an object of headers, returning a new object with only the allowed headers.
|
|
19
|
-
* @param headers The original headers object.
|
|
20
|
-
* @returns A new object containing only the headers from the allow-list.
|
|
21
|
-
*/
|
|
22
|
-
export declare function filterHeaders(headers?: Record<string, any>): Record<string, string>;
|
|
23
|
-
/**
|
|
24
|
-
* Safely parses JSON strings, returning the original data if parsing fails or if it's not a string.
|
|
25
|
-
* @param data The data to potentially parse as JSON.
|
|
26
|
-
* @returns Parsed JSON object or the original data.
|
|
27
|
-
*/
|
|
28
|
-
export declare function safeJsonParse(data: any): any;
|
|
29
|
-
/**
|
|
30
|
-
* Normalizes IP addresses by removing IPv6 mapping prefix for IPv4 addresses.
|
|
31
|
-
* @param ip The IP address to normalize.
|
|
32
|
-
* @returns Normalized IP address string.
|
|
33
|
-
*/
|
|
34
|
-
export declare function normalizeIp(ip: string | undefined): string | undefined;
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateTimestamp = generateTimestamp;
|
|
4
|
-
exports.getTraceId = getTraceId;
|
|
5
|
-
exports.clearTraceId = clearTraceId;
|
|
6
|
-
exports.filterHeaders = filterHeaders;
|
|
7
|
-
exports.safeJsonParse = safeJsonParse;
|
|
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
|
-
}
|
|
42
|
-
// --- Header Allow-Listing ---
|
|
43
|
-
const ALLOWED_HEADERS = new Set([
|
|
44
|
-
'content-type',
|
|
45
|
-
'accept',
|
|
46
|
-
'user-agent',
|
|
47
|
-
'host',
|
|
48
|
-
'x-forwarded-for',
|
|
49
|
-
'x-request-id',
|
|
50
|
-
'content-length',
|
|
51
|
-
'cache-control',
|
|
52
|
-
]);
|
|
53
|
-
/**
|
|
54
|
-
* Filters an object of headers, returning a new object with only the allowed headers.
|
|
55
|
-
* @param headers The original headers object.
|
|
56
|
-
* @returns A new object containing only the headers from the allow-list.
|
|
57
|
-
*/
|
|
58
|
-
function filterHeaders(headers) {
|
|
59
|
-
const filtered = {};
|
|
60
|
-
for (const key in headers) {
|
|
61
|
-
if (ALLOWED_HEADERS.has(key.toLowerCase())) {
|
|
62
|
-
filtered[key] = String(headers[key]);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return filtered;
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Safely parses JSON strings, returning the original data if parsing fails or if it's not a string.
|
|
69
|
-
* @param data The data to potentially parse as JSON.
|
|
70
|
-
* @returns Parsed JSON object or the original data.
|
|
71
|
-
*/
|
|
72
|
-
function safeJsonParse(data) {
|
|
73
|
-
if (typeof data === 'string') {
|
|
74
|
-
try {
|
|
75
|
-
return JSON.parse(data);
|
|
76
|
-
}
|
|
77
|
-
catch {
|
|
78
|
-
return data;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
return data;
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Normalizes IP addresses by removing IPv6 mapping prefix for IPv4 addresses.
|
|
85
|
-
* @param ip The IP address to normalize.
|
|
86
|
-
* @returns Normalized IP address string.
|
|
87
|
-
*/
|
|
88
|
-
function normalizeIp(ip) {
|
|
89
|
-
if (!ip)
|
|
90
|
-
return ip;
|
|
91
|
-
// Remove IPv4-mapped IPv6 prefix (::ffff:) to get clean IPv4 address
|
|
92
|
-
if (ip.startsWith('::ffff:')) {
|
|
93
|
-
return ip.substring(7);
|
|
94
|
-
}
|
|
95
|
-
return ip;
|
|
96
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
declare class TraceContextManager {
|
|
2
|
-
private static instance;
|
|
3
|
-
private storage;
|
|
4
|
-
private constructor();
|
|
5
|
-
static getInstance(): TraceContextManager;
|
|
6
|
-
run<T>(traceId: string, callback: () => T): T;
|
|
7
|
-
getTraceId(): string | undefined;
|
|
8
|
-
}
|
|
9
|
-
export declare const traceContext: TraceContextManager;
|
|
10
|
-
export {};
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.traceContext = void 0;
|
|
4
|
-
const async_hooks_1 = require("async_hooks");
|
|
5
|
-
class TraceContextManager {
|
|
6
|
-
constructor() {
|
|
7
|
-
this.storage = new async_hooks_1.AsyncLocalStorage();
|
|
8
|
-
}
|
|
9
|
-
static getInstance() {
|
|
10
|
-
if (!TraceContextManager.instance) {
|
|
11
|
-
TraceContextManager.instance = new TraceContextManager();
|
|
12
|
-
}
|
|
13
|
-
return TraceContextManager.instance;
|
|
14
|
-
}
|
|
15
|
-
run(traceId, callback) {
|
|
16
|
-
return this.storage.run({ traceId }, callback);
|
|
17
|
-
}
|
|
18
|
-
getTraceId() {
|
|
19
|
-
const context = this.storage.getStore();
|
|
20
|
-
return context?.traceId;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
exports.traceContext = TraceContextManager.getInstance();
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Higher-order function that wraps a function with trace context
|
|
3
|
-
* @param fn - Function to wrap with trace context
|
|
4
|
-
* @param traceId - Optional trace ID to use (will generate new one if not provided)
|
|
5
|
-
* @returns Wrapped function that maintains trace context
|
|
6
|
-
*/
|
|
7
|
-
export declare function withTrace<T extends (...args: any[]) => any>(fn: T, traceId?: string): T;
|
package/dist/utils/with-trace.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.withTrace = withTrace;
|
|
4
|
-
/**
|
|
5
|
-
* Utility function to wrap a function with trace context
|
|
6
|
-
*/
|
|
7
|
-
const uuid_1 = require("uuid");
|
|
8
|
-
const trace_context_1 = require("./trace-context");
|
|
9
|
-
/**
|
|
10
|
-
* Higher-order function that wraps a function with trace context
|
|
11
|
-
* @param fn - Function to wrap with trace context
|
|
12
|
-
* @param traceId - Optional trace ID to use (will generate new one if not provided)
|
|
13
|
-
* @returns Wrapped function that maintains trace context
|
|
14
|
-
*/
|
|
15
|
-
function withTrace(fn, traceId) {
|
|
16
|
-
const id = traceId || (0, uuid_1.v4)();
|
|
17
|
-
return ((...args) => {
|
|
18
|
-
return trace_context_1.traceContext.run(id, () => fn(...args));
|
|
19
|
-
});
|
|
20
|
-
}
|