timonel 3.1.1 → 3.1.2
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/CHANGELOG.md +7 -0
- package/README.md +323 -695
- package/dist/cli.js +275 -15
- package/dist/index.d.ts +5 -1
- package/dist/index.js +12 -0
- package/dist/lib/helm.d.ts +471 -0
- package/dist/lib/helm.js +483 -0
- package/dist/lib/helmChartWriter.d.ts +157 -0
- package/dist/lib/helmChartWriter.js +171 -1
- package/dist/lib/policy/configurationLoader.d.ts +132 -0
- package/dist/lib/policy/configurationLoader.js +132 -0
- package/dist/lib/policy/errorContextGenerator.d.ts +89 -0
- package/dist/lib/policy/errorContextGenerator.js +99 -2
- package/dist/lib/policy/errors.d.ts +35 -0
- package/dist/lib/policy/errors.js +36 -0
- package/dist/lib/policy/index.d.ts +9 -0
- package/dist/lib/policy/index.js +16 -0
- package/dist/lib/policy/parallelExecutor.d.ts +90 -0
- package/dist/lib/policy/parallelExecutor.js +86 -3
- package/dist/lib/policy/pluginLoader.d.ts +92 -0
- package/dist/lib/policy/pluginLoader.js +92 -1
- package/dist/lib/policy/pluginRegistry.d.ts +54 -0
- package/dist/lib/policy/pluginRegistry.js +56 -0
- package/dist/lib/policy/policyEngine.d.ts +137 -0
- package/dist/lib/policy/policyEngine.js +191 -5
- package/dist/lib/policy/resultAggregator.d.ts +46 -0
- package/dist/lib/policy/resultAggregator.js +69 -1
- package/dist/lib/policy/resultFormatter.d.ts +88 -0
- package/dist/lib/policy/resultFormatter.js +101 -0
- package/dist/lib/policy/types.d.ts +136 -0
- package/dist/lib/policy/types.js +8 -0
- package/dist/lib/policy/validationCache.d.ts +146 -0
- package/dist/lib/policy/validationCache.js +142 -6
- package/dist/lib/resources/baseResourceProvider.d.ts +45 -0
- package/dist/lib/resources/baseResourceProvider.js +48 -1
- package/dist/lib/resources/cloud/aws/awsResources.d.ts +192 -0
- package/dist/lib/resources/cloud/aws/awsResources.js +163 -1
- package/dist/lib/resources/cloud/aws/karpenterResources.d.ts +131 -0
- package/dist/lib/resources/cloud/aws/karpenterResources.js +77 -0
- package/dist/lib/rutter.d.ts +381 -3
- package/dist/lib/rutter.js +439 -28
- package/dist/lib/security.d.ts +123 -0
- package/dist/lib/security.js +162 -4
- package/dist/lib/templates/flexible-subchart.d.ts +52 -0
- package/dist/lib/templates/flexible-subchart.js +70 -0
- package/dist/lib/templates/umbrella-chart.d.ts +27 -0
- package/dist/lib/templates/umbrella-chart.js +89 -0
- package/dist/lib/types.d.ts +26 -0
- package/dist/lib/umbrella.d.ts +23 -0
- package/dist/lib/umbrella.js +23 -0
- package/dist/lib/umbrellaRutter.d.ts +75 -0
- package/dist/lib/umbrellaRutter.js +82 -2
- package/dist/lib/utils/envVarsLoader.d.ts +49 -0
- package/dist/lib/utils/envVarsLoader.js +53 -0
- package/dist/lib/utils/helmConstructSerializer.d.ts +17 -0
- package/dist/lib/utils/helmConstructSerializer.js +22 -0
- package/dist/lib/utils/helmControlStructures.d.ts +194 -0
- package/dist/lib/utils/helmControlStructures.js +180 -0
- package/dist/lib/utils/helmHelpers/envHelpers.d.ts +13 -0
- package/dist/lib/utils/helmHelpers/envHelpers.js +13 -0
- package/dist/lib/utils/helmHelpers/gitopsHelpers.d.ts +13 -0
- package/dist/lib/utils/helmHelpers/gitopsHelpers.js +13 -0
- package/dist/lib/utils/helmHelpers/index.d.ts +74 -0
- package/dist/lib/utils/helmHelpers/index.js +85 -1
- package/dist/lib/utils/helmHelpers/observabilityHelpers.d.ts +13 -0
- package/dist/lib/utils/helmHelpers/observabilityHelpers.js +13 -0
- package/dist/lib/utils/helmHelpers/types.d.ts +23 -0
- package/dist/lib/utils/helmHelpers/types.js +4 -0
- package/dist/lib/utils/helmHelpers/validationHelpers.d.ts +13 -0
- package/dist/lib/utils/helmHelpers/validationHelpers.js +13 -0
- package/dist/lib/utils/helmHelpers.d.ts +62 -0
- package/dist/lib/utils/helmHelpers.js +77 -0
- package/dist/lib/utils/helmYamlSerializer.d.ts +77 -0
- package/dist/lib/utils/helmYamlSerializer.js +398 -21
- package/dist/lib/utils/logger.d.ts +153 -0
- package/dist/lib/utils/logger.js +170 -2
- package/dist/lib/utils/valuesRef.d.ts +181 -50
- package/dist/lib/utils/valuesRef.js +168 -170
- package/dist/lib/validation/inputValidator.d.ts +45 -0
- package/dist/lib/validation/inputValidator.js +67 -2
- package/dist/types/index.d.ts +34 -0
- package/dist/types/index.js +3 -0
- package/package.json +31 -38
|
@@ -1,49 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview High-performance structured logging system for Timonel using Pino
|
|
3
|
+
* Provides centralized, type-safe logging with performance optimizations and security features
|
|
4
|
+
* @since 2.10.3
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Standard log levels following syslog conventions
|
|
8
|
+
* @since 2.10.3
|
|
9
|
+
*/
|
|
1
10
|
export declare enum LogLevel {
|
|
11
|
+
/** System is unusable - immediate action required */
|
|
2
12
|
FATAL = 60,
|
|
13
|
+
/** Error conditions that need immediate attention */
|
|
3
14
|
ERROR = 50,
|
|
15
|
+
/** Warning conditions that should be monitored */
|
|
4
16
|
WARN = 40,
|
|
17
|
+
/** General informational messages */
|
|
5
18
|
INFO = 30,
|
|
19
|
+
/** Debug information for troubleshooting */
|
|
6
20
|
DEBUG = 20,
|
|
21
|
+
/** Detailed trace information */
|
|
7
22
|
TRACE = 10
|
|
8
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Configuration options for the logging system
|
|
26
|
+
* @since 2.10.3
|
|
27
|
+
*/
|
|
9
28
|
export interface LoggerConfig {
|
|
29
|
+
/** Minimum log level to output */
|
|
10
30
|
level: LogLevel;
|
|
31
|
+
/** Whether to suppress all log output */
|
|
11
32
|
silent: boolean;
|
|
33
|
+
/** Service name for structured logging */
|
|
12
34
|
service: string;
|
|
35
|
+
/** Environment (development, staging, production) */
|
|
13
36
|
environment: string;
|
|
37
|
+
/** Whether to enable pretty printing in development */
|
|
14
38
|
prettyPrint: boolean;
|
|
39
|
+
/** Additional base fields to include in all logs */
|
|
15
40
|
base?: Record<string, unknown>;
|
|
16
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Contextual information to include with log entries
|
|
44
|
+
* @since 2.10.3
|
|
45
|
+
*/
|
|
17
46
|
export interface LogContext {
|
|
47
|
+
/** Unique identifier for request tracing */
|
|
18
48
|
correlationId?: string;
|
|
49
|
+
/** User identifier for audit trails */
|
|
19
50
|
userId?: string;
|
|
51
|
+
/** Operation being performed */
|
|
20
52
|
operation?: string;
|
|
53
|
+
/** Component or module name */
|
|
21
54
|
component?: string;
|
|
55
|
+
/** Chart or resource name */
|
|
22
56
|
chartName?: string;
|
|
57
|
+
/** Additional structured data */
|
|
23
58
|
[key: string]: unknown;
|
|
24
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* High-performance structured logger implementation using Pino
|
|
62
|
+
* Provides type-safe logging with security features and performance optimization
|
|
63
|
+
* @since 2.10.3
|
|
64
|
+
*/
|
|
25
65
|
export declare class TimonelLogger {
|
|
26
66
|
private readonly logger;
|
|
27
67
|
private readonly config;
|
|
28
68
|
private static readonly SENSITIVE_FIELDS;
|
|
29
69
|
constructor(config?: Partial<LoggerConfig>);
|
|
70
|
+
/**
|
|
71
|
+
* Maps internal log levels to Pino log levels
|
|
72
|
+
* @param level - Internal log level
|
|
73
|
+
* @returns Pino-compatible log level string
|
|
74
|
+
* @since 2.10.3
|
|
75
|
+
*/
|
|
30
76
|
private mapLogLevel;
|
|
77
|
+
/**
|
|
78
|
+
* Safe request serializer that removes sensitive data
|
|
79
|
+
* @param req - HTTP request object
|
|
80
|
+
* @returns Sanitized request data
|
|
81
|
+
* @since 2.10.3
|
|
82
|
+
*/
|
|
31
83
|
private requestSerializer;
|
|
84
|
+
/**
|
|
85
|
+
* Safe response serializer
|
|
86
|
+
* @param res - HTTP response object
|
|
87
|
+
* @returns Sanitized response data
|
|
88
|
+
* @since 2.10.3
|
|
89
|
+
*/
|
|
32
90
|
private responseSerializer;
|
|
91
|
+
/**
|
|
92
|
+
* Log a fatal error - system is unusable
|
|
93
|
+
* @param message - Log message
|
|
94
|
+
* @param context - Additional context data
|
|
95
|
+
* @since 2.10.3
|
|
96
|
+
*/
|
|
33
97
|
fatal(message: string, context?: LogContext): void;
|
|
98
|
+
/**
|
|
99
|
+
* Log an error that needs immediate attention
|
|
100
|
+
* @param message - Log message
|
|
101
|
+
* @param context - Additional context data
|
|
102
|
+
* @since 2.10.3
|
|
103
|
+
*/
|
|
34
104
|
error(message: string, context?: LogContext): void;
|
|
105
|
+
/**
|
|
106
|
+
* Log a warning condition
|
|
107
|
+
* @param message - Log message
|
|
108
|
+
* @param context - Additional context data
|
|
109
|
+
* @since 2.10.3
|
|
110
|
+
*/
|
|
35
111
|
warn(message: string, context?: LogContext): void;
|
|
112
|
+
/**
|
|
113
|
+
* Log general informational message
|
|
114
|
+
* @param message - Log message
|
|
115
|
+
* @param context - Additional context data
|
|
116
|
+
* @since 2.10.3
|
|
117
|
+
*/
|
|
36
118
|
info(message: string, context?: LogContext): void;
|
|
119
|
+
/**
|
|
120
|
+
* Log debug information
|
|
121
|
+
* @param message - Log message
|
|
122
|
+
* @param context - Additional context data
|
|
123
|
+
* @since 2.10.3
|
|
124
|
+
*/
|
|
37
125
|
debug(message: string, context?: LogContext): void;
|
|
126
|
+
/**
|
|
127
|
+
* Log detailed trace information
|
|
128
|
+
* @param message - Log message
|
|
129
|
+
* @param context - Additional context data
|
|
130
|
+
* @since 2.10.3
|
|
131
|
+
*/
|
|
38
132
|
trace(message: string, context?: LogContext): void;
|
|
133
|
+
/**
|
|
134
|
+
* Internal logging method with security sanitization
|
|
135
|
+
* @param level - Log level
|
|
136
|
+
* @param message - Log message
|
|
137
|
+
* @param context - Additional context data
|
|
138
|
+
* @since 2.10.3
|
|
139
|
+
*/
|
|
39
140
|
private log;
|
|
141
|
+
/**
|
|
142
|
+
* Sanitizes context object to prevent data leaks
|
|
143
|
+
* @param context - Context object to sanitize
|
|
144
|
+
* @returns Sanitized context object
|
|
145
|
+
* @since 2.10.3
|
|
146
|
+
*/
|
|
40
147
|
private sanitizeContext;
|
|
148
|
+
/**
|
|
149
|
+
* Sanitizes nested objects with depth limiting
|
|
150
|
+
* @param obj - Object to sanitize
|
|
151
|
+
* @param depth - Maximum recursion depth
|
|
152
|
+
* @returns Sanitized object
|
|
153
|
+
* @since 2.10.3
|
|
154
|
+
*/
|
|
41
155
|
private sanitizeNestedObject;
|
|
156
|
+
/**
|
|
157
|
+
* Creates a child logger with additional context
|
|
158
|
+
* This is highly optimized in Pino for performance
|
|
159
|
+
* @param context - Additional context to bind to child logger
|
|
160
|
+
* @returns New logger instance with bound context
|
|
161
|
+
* @since 2.10.3
|
|
162
|
+
*/
|
|
42
163
|
child(context: LogContext): TimonelLogger;
|
|
164
|
+
/**
|
|
165
|
+
* Measures operation duration for performance monitoring
|
|
166
|
+
* @param operation - Operation name
|
|
167
|
+
* @returns Function to call when operation completes
|
|
168
|
+
* @since 2.10.3
|
|
169
|
+
*/
|
|
43
170
|
time(operation: string): () => void;
|
|
171
|
+
/**
|
|
172
|
+
* Updates the log level at runtime
|
|
173
|
+
* @param level - New log level
|
|
174
|
+
* @since 2.10.3
|
|
175
|
+
*/
|
|
44
176
|
setLevel(level: LogLevel): void;
|
|
177
|
+
/**
|
|
178
|
+
* Enables or disables silent mode
|
|
179
|
+
* @param silent - Whether to suppress all output
|
|
180
|
+
* @since 2.10.3
|
|
181
|
+
*/
|
|
45
182
|
setSilent(silent: boolean): void;
|
|
183
|
+
/**
|
|
184
|
+
* Flushes any pending log entries (important for async logging)
|
|
185
|
+
* @since 2.10.3
|
|
186
|
+
*/
|
|
46
187
|
flush(): Promise<void>;
|
|
47
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* Global logger instance for the Timonel application
|
|
191
|
+
* Configured based on environment variables
|
|
192
|
+
* @since 2.10.3
|
|
193
|
+
*/
|
|
48
194
|
export declare const logger: TimonelLogger;
|
|
195
|
+
/**
|
|
196
|
+
* Factory function for creating component-specific loggers
|
|
197
|
+
* @param component - Component name
|
|
198
|
+
* @param additionalConfig - Additional configuration
|
|
199
|
+
* @returns Configured logger instance
|
|
200
|
+
* @since 2.10.3
|
|
201
|
+
*/
|
|
49
202
|
export declare function createLogger(component: string, additionalConfig?: Partial<LoggerConfig>): TimonelLogger;
|
package/dist/lib/utils/logger.js
CHANGED
|
@@ -1,14 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview High-performance structured logging system for Timonel using Pino
|
|
3
|
+
* Provides centralized, type-safe logging with performance optimizations and security features
|
|
4
|
+
* @since 2.10.3
|
|
5
|
+
*/
|
|
1
6
|
import pino from 'pino';
|
|
2
7
|
import { SecurityUtils } from '../security.js';
|
|
8
|
+
/**
|
|
9
|
+
* Standard log levels following syslog conventions
|
|
10
|
+
* @since 2.10.3
|
|
11
|
+
*/
|
|
3
12
|
export var LogLevel;
|
|
4
13
|
(function (LogLevel) {
|
|
14
|
+
/** System is unusable - immediate action required */
|
|
5
15
|
LogLevel[LogLevel["FATAL"] = 60] = "FATAL";
|
|
16
|
+
/** Error conditions that need immediate attention */
|
|
6
17
|
LogLevel[LogLevel["ERROR"] = 50] = "ERROR";
|
|
18
|
+
/** Warning conditions that should be monitored */
|
|
7
19
|
LogLevel[LogLevel["WARN"] = 40] = "WARN";
|
|
20
|
+
/** General informational messages */
|
|
8
21
|
LogLevel[LogLevel["INFO"] = 30] = "INFO";
|
|
22
|
+
/** Debug information for troubleshooting */
|
|
9
23
|
LogLevel[LogLevel["DEBUG"] = 20] = "DEBUG";
|
|
24
|
+
/** Detailed trace information */
|
|
10
25
|
LogLevel[LogLevel["TRACE"] = 10] = "TRACE";
|
|
11
26
|
})(LogLevel || (LogLevel = {}));
|
|
27
|
+
/**
|
|
28
|
+
* High-performance structured logger implementation using Pino
|
|
29
|
+
* Provides type-safe logging with security features and performance optimization
|
|
30
|
+
* @since 2.10.3
|
|
31
|
+
*/
|
|
12
32
|
export class TimonelLogger {
|
|
13
33
|
constructor(config = {}) {
|
|
14
34
|
this.config = {
|
|
@@ -28,8 +48,10 @@ export class TimonelLogger {
|
|
|
28
48
|
...this.config.base,
|
|
29
49
|
},
|
|
30
50
|
timestamp: pino.stdTimeFunctions.isoTime,
|
|
51
|
+
// Security: redact sensitive fields (CWE-532 prevention)
|
|
31
52
|
redact: {
|
|
32
53
|
paths: [
|
|
54
|
+
// Generic secrets
|
|
33
55
|
'password',
|
|
34
56
|
'passphrase',
|
|
35
57
|
'secret',
|
|
@@ -70,6 +92,7 @@ export class TimonelLogger {
|
|
|
70
92
|
'pem',
|
|
71
93
|
'p12',
|
|
72
94
|
'pfx',
|
|
95
|
+
// Nested (one level)
|
|
73
96
|
'*.password',
|
|
74
97
|
'*.passphrase',
|
|
75
98
|
'*.secret',
|
|
@@ -110,6 +133,7 @@ export class TimonelLogger {
|
|
|
110
133
|
'*.pem',
|
|
111
134
|
'*.p12',
|
|
112
135
|
'*.pfx',
|
|
136
|
+
// HTTP specifics (request/response shapes)
|
|
113
137
|
'req.headers.authorization',
|
|
114
138
|
'req.headers.cookie',
|
|
115
139
|
'req.headers.cookies',
|
|
@@ -119,6 +143,7 @@ export class TimonelLogger {
|
|
|
119
143
|
'req.headers["x-auth-token"]',
|
|
120
144
|
'res.headers["set-cookie"]',
|
|
121
145
|
'res.headers["authorization"]',
|
|
146
|
+
// Common payload locations
|
|
122
147
|
'body.password',
|
|
123
148
|
'body.token',
|
|
124
149
|
'body.apiKey',
|
|
@@ -128,6 +153,7 @@ export class TimonelLogger {
|
|
|
128
153
|
'query.token',
|
|
129
154
|
'query.apiKey',
|
|
130
155
|
'query.secret',
|
|
156
|
+
// Configuration objects
|
|
131
157
|
'config.password',
|
|
132
158
|
'config.secret',
|
|
133
159
|
'config.clientSecret',
|
|
@@ -137,12 +163,15 @@ export class TimonelLogger {
|
|
|
137
163
|
censor: '[REDACTED]',
|
|
138
164
|
},
|
|
139
165
|
serializers: {
|
|
166
|
+
// Optimized error serialization
|
|
140
167
|
err: pino.stdSerializers.err,
|
|
141
168
|
error: pino.stdSerializers.err,
|
|
169
|
+
// Custom serializers for security
|
|
142
170
|
req: this.requestSerializer,
|
|
143
171
|
res: this.responseSerializer,
|
|
144
172
|
},
|
|
145
173
|
};
|
|
174
|
+
// Pretty printing for development
|
|
146
175
|
if (this.config.prettyPrint && this.config.environment === 'development') {
|
|
147
176
|
this.logger = pino({
|
|
148
177
|
...pinoOptions,
|
|
@@ -161,6 +190,12 @@ export class TimonelLogger {
|
|
|
161
190
|
this.logger = pino(pinoOptions);
|
|
162
191
|
}
|
|
163
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* Maps internal log levels to Pino log levels
|
|
195
|
+
* @param level - Internal log level
|
|
196
|
+
* @returns Pino-compatible log level string
|
|
197
|
+
* @since 2.10.3
|
|
198
|
+
*/
|
|
164
199
|
mapLogLevel(level) {
|
|
165
200
|
switch (level) {
|
|
166
201
|
case LogLevel.FATAL:
|
|
@@ -179,6 +214,12 @@ export class TimonelLogger {
|
|
|
179
214
|
return 'info';
|
|
180
215
|
}
|
|
181
216
|
}
|
|
217
|
+
/**
|
|
218
|
+
* Safe request serializer that removes sensitive data
|
|
219
|
+
* @param req - HTTP request object
|
|
220
|
+
* @returns Sanitized request data
|
|
221
|
+
* @since 2.10.3
|
|
222
|
+
*/
|
|
182
223
|
requestSerializer(req) {
|
|
183
224
|
try {
|
|
184
225
|
if (!req || typeof req !== 'object')
|
|
@@ -190,6 +231,7 @@ export class TimonelLogger {
|
|
|
190
231
|
headers: {
|
|
191
232
|
'user-agent': request.headers?.['user-agent'],
|
|
192
233
|
'content-type': request.headers?.['content-type'],
|
|
234
|
+
// Exclude sensitive headers
|
|
193
235
|
},
|
|
194
236
|
remoteAddress: request.remoteAddress,
|
|
195
237
|
remotePort: request.remotePort,
|
|
@@ -199,6 +241,12 @@ export class TimonelLogger {
|
|
|
199
241
|
return {};
|
|
200
242
|
}
|
|
201
243
|
}
|
|
244
|
+
/**
|
|
245
|
+
* Safe response serializer
|
|
246
|
+
* @param res - HTTP response object
|
|
247
|
+
* @returns Sanitized response data
|
|
248
|
+
* @since 2.10.3
|
|
249
|
+
*/
|
|
202
250
|
responseSerializer(res) {
|
|
203
251
|
if (!res || typeof res !== 'object')
|
|
204
252
|
return {};
|
|
@@ -211,34 +259,81 @@ export class TimonelLogger {
|
|
|
211
259
|
},
|
|
212
260
|
};
|
|
213
261
|
}
|
|
262
|
+
/**
|
|
263
|
+
* Log a fatal error - system is unusable
|
|
264
|
+
* @param message - Log message
|
|
265
|
+
* @param context - Additional context data
|
|
266
|
+
* @since 2.10.3
|
|
267
|
+
*/
|
|
214
268
|
fatal(message, context) {
|
|
215
269
|
this.log(LogLevel.FATAL, message, context);
|
|
216
270
|
}
|
|
271
|
+
/**
|
|
272
|
+
* Log an error that needs immediate attention
|
|
273
|
+
* @param message - Log message
|
|
274
|
+
* @param context - Additional context data
|
|
275
|
+
* @since 2.10.3
|
|
276
|
+
*/
|
|
217
277
|
error(message, context) {
|
|
218
278
|
this.log(LogLevel.ERROR, message, context);
|
|
219
279
|
}
|
|
280
|
+
/**
|
|
281
|
+
* Log a warning condition
|
|
282
|
+
* @param message - Log message
|
|
283
|
+
* @param context - Additional context data
|
|
284
|
+
* @since 2.10.3
|
|
285
|
+
*/
|
|
220
286
|
warn(message, context) {
|
|
221
287
|
this.log(LogLevel.WARN, message, context);
|
|
222
288
|
}
|
|
289
|
+
/**
|
|
290
|
+
* Log general informational message
|
|
291
|
+
* @param message - Log message
|
|
292
|
+
* @param context - Additional context data
|
|
293
|
+
* @since 2.10.3
|
|
294
|
+
*/
|
|
223
295
|
info(message, context) {
|
|
224
296
|
this.log(LogLevel.INFO, message, context);
|
|
225
297
|
}
|
|
298
|
+
/**
|
|
299
|
+
* Log debug information
|
|
300
|
+
* @param message - Log message
|
|
301
|
+
* @param context - Additional context data
|
|
302
|
+
* @since 2.10.3
|
|
303
|
+
*/
|
|
226
304
|
debug(message, context) {
|
|
227
305
|
this.log(LogLevel.DEBUG, message, context);
|
|
228
306
|
}
|
|
307
|
+
/**
|
|
308
|
+
* Log detailed trace information
|
|
309
|
+
* @param message - Log message
|
|
310
|
+
* @param context - Additional context data
|
|
311
|
+
* @since 2.10.3
|
|
312
|
+
*/
|
|
229
313
|
trace(message, context) {
|
|
230
314
|
this.log(LogLevel.TRACE, message, context);
|
|
231
315
|
}
|
|
316
|
+
/**
|
|
317
|
+
* Internal logging method with security sanitization
|
|
318
|
+
* @param level - Log level
|
|
319
|
+
* @param message - Log message
|
|
320
|
+
* @param context - Additional context data
|
|
321
|
+
* @since 2.10.3
|
|
322
|
+
*/
|
|
232
323
|
log(level, message, context) {
|
|
233
324
|
if (this.config.silent || level < this.config.level) {
|
|
234
325
|
return;
|
|
235
326
|
}
|
|
327
|
+
// Sanitize message for security
|
|
236
328
|
const sanitizedMessage = SecurityUtils.sanitizeLogMessage(message);
|
|
329
|
+
// Sanitize and structure context
|
|
237
330
|
const sanitizedContext = context ? this.sanitizeContext(context) : {};
|
|
331
|
+
// Add performance timing if available
|
|
238
332
|
const logEntry = {
|
|
239
333
|
...sanitizedContext,
|
|
240
334
|
timestamp: new Date().toISOString(),
|
|
241
335
|
};
|
|
336
|
+
// Use appropriate Pino logging method
|
|
242
337
|
switch (level) {
|
|
243
338
|
case LogLevel.FATAL:
|
|
244
339
|
this.logger.fatal(logEntry, sanitizedMessage);
|
|
@@ -260,20 +355,32 @@ export class TimonelLogger {
|
|
|
260
355
|
break;
|
|
261
356
|
}
|
|
262
357
|
}
|
|
358
|
+
/**
|
|
359
|
+
* Sanitizes context object to prevent data leaks
|
|
360
|
+
* @param context - Context object to sanitize
|
|
361
|
+
* @returns Sanitized context object
|
|
362
|
+
* @since 2.10.3
|
|
363
|
+
*/
|
|
263
364
|
sanitizeContext(context) {
|
|
264
365
|
try {
|
|
265
366
|
const sanitized = {};
|
|
266
367
|
for (const [key, value] of Object.entries(context)) {
|
|
267
368
|
if (TimonelLogger.SENSITIVE_FIELDS.has(key.toLowerCase())) {
|
|
369
|
+
// eslint-disable-next-line security/detect-object-injection -- Safe: key from Object.entries
|
|
268
370
|
sanitized[key] = '[REDACTED]';
|
|
269
371
|
}
|
|
270
372
|
else if (typeof value === 'string') {
|
|
373
|
+
// Safe assignment - key comes from Object.entries
|
|
374
|
+
// eslint-disable-next-line security/detect-object-injection -- Safe: key from Object.entries
|
|
271
375
|
sanitized[key] = SecurityUtils.sanitizeLogMessage(value);
|
|
272
376
|
}
|
|
273
377
|
else if (value && typeof value === 'object') {
|
|
378
|
+
// Recursively sanitize nested objects (limited depth)
|
|
379
|
+
// eslint-disable-next-line security/detect-object-injection -- Safe: key from Object.entries
|
|
274
380
|
sanitized[key] = this.sanitizeNestedObject(value, 2);
|
|
275
381
|
}
|
|
276
382
|
else {
|
|
383
|
+
// eslint-disable-next-line security/detect-object-injection -- Safe: key from Object.entries
|
|
277
384
|
sanitized[key] = value;
|
|
278
385
|
}
|
|
279
386
|
}
|
|
@@ -283,6 +390,13 @@ export class TimonelLogger {
|
|
|
283
390
|
return {};
|
|
284
391
|
}
|
|
285
392
|
}
|
|
393
|
+
/**
|
|
394
|
+
* Sanitizes nested objects with depth limiting
|
|
395
|
+
* @param obj - Object to sanitize
|
|
396
|
+
* @param depth - Maximum recursion depth
|
|
397
|
+
* @returns Sanitized object
|
|
398
|
+
* @since 2.10.3
|
|
399
|
+
*/
|
|
286
400
|
sanitizeNestedObject(obj, depth) {
|
|
287
401
|
try {
|
|
288
402
|
if (depth <= 0 || !obj || typeof obj !== 'object') {
|
|
@@ -291,12 +405,16 @@ export class TimonelLogger {
|
|
|
291
405
|
const sanitized = {};
|
|
292
406
|
for (const [key, value] of Object.entries(obj)) {
|
|
293
407
|
if (typeof value === 'string') {
|
|
408
|
+
// Safe assignment - key comes from Object.entries
|
|
409
|
+
// eslint-disable-next-line security/detect-object-injection
|
|
294
410
|
sanitized[key] = SecurityUtils.sanitizeLogMessage(value);
|
|
295
411
|
}
|
|
296
412
|
else if (value && typeof value === 'object') {
|
|
413
|
+
// eslint-disable-next-line security/detect-object-injection
|
|
297
414
|
sanitized[key] = this.sanitizeNestedObject(value, depth - 1);
|
|
298
415
|
}
|
|
299
416
|
else {
|
|
417
|
+
// eslint-disable-next-line security/detect-object-injection
|
|
300
418
|
sanitized[key] = value;
|
|
301
419
|
}
|
|
302
420
|
}
|
|
@@ -306,9 +424,19 @@ export class TimonelLogger {
|
|
|
306
424
|
return obj;
|
|
307
425
|
}
|
|
308
426
|
}
|
|
427
|
+
/**
|
|
428
|
+
* Creates a child logger with additional context
|
|
429
|
+
* This is highly optimized in Pino for performance
|
|
430
|
+
* @param context - Additional context to bind to child logger
|
|
431
|
+
* @returns New logger instance with bound context
|
|
432
|
+
* @since 2.10.3
|
|
433
|
+
*/
|
|
309
434
|
child(context) {
|
|
310
435
|
const sanitizedContext = this.sanitizeContext(context);
|
|
436
|
+
// Create a new logger instance with the same config
|
|
311
437
|
const childLogger = new TimonelLogger(this.config);
|
|
438
|
+
// Replace the internal logger with a Pino child logger using Object.defineProperty
|
|
439
|
+
// This is type-safe and prevents accidental modification
|
|
312
440
|
Object.defineProperty(childLogger, 'logger', {
|
|
313
441
|
value: this.logger.child(sanitizedContext),
|
|
314
442
|
writable: false,
|
|
@@ -317,24 +445,41 @@ export class TimonelLogger {
|
|
|
317
445
|
});
|
|
318
446
|
return childLogger;
|
|
319
447
|
}
|
|
448
|
+
/**
|
|
449
|
+
* Measures operation duration for performance monitoring
|
|
450
|
+
* @param operation - Operation name
|
|
451
|
+
* @returns Function to call when operation completes
|
|
452
|
+
* @since 2.10.3
|
|
453
|
+
*/
|
|
320
454
|
time(operation) {
|
|
321
455
|
const start = process.hrtime.bigint();
|
|
322
456
|
return () => {
|
|
323
457
|
const end = process.hrtime.bigint();
|
|
324
|
-
const duration = Number(end - start) / 1000000;
|
|
458
|
+
const duration = Number(end - start) / 1000000; // Convert to milliseconds
|
|
325
459
|
this.info('Operation completed', {
|
|
326
460
|
operation: SecurityUtils.sanitizeLogMessage(operation),
|
|
327
|
-
duration_ms: Math.round(duration * 100) / 100,
|
|
461
|
+
duration_ms: Math.round(duration * 100) / 100, // Round to 2 decimal places
|
|
328
462
|
performance: 'timing',
|
|
329
463
|
});
|
|
330
464
|
};
|
|
331
465
|
}
|
|
466
|
+
/**
|
|
467
|
+
* Updates the log level at runtime
|
|
468
|
+
* @param level - New log level
|
|
469
|
+
* @since 2.10.3
|
|
470
|
+
*/
|
|
332
471
|
setLevel(level) {
|
|
333
472
|
this.config.level = level;
|
|
334
473
|
this.logger.level = this.mapLogLevel(level);
|
|
335
474
|
}
|
|
475
|
+
/**
|
|
476
|
+
* Enables or disables silent mode
|
|
477
|
+
* @param silent - Whether to suppress all output
|
|
478
|
+
* @since 2.10.3
|
|
479
|
+
*/
|
|
336
480
|
setSilent(silent) {
|
|
337
481
|
this.config.silent = silent;
|
|
482
|
+
// Pino doesn't have a direct silent property, we need to enable/disable the logger
|
|
338
483
|
if (silent) {
|
|
339
484
|
this.logger.level = 'silent';
|
|
340
485
|
}
|
|
@@ -342,6 +487,10 @@ export class TimonelLogger {
|
|
|
342
487
|
this.logger.level = this.mapLogLevel(this.config.level);
|
|
343
488
|
}
|
|
344
489
|
}
|
|
490
|
+
/**
|
|
491
|
+
* Flushes any pending log entries (important for async logging)
|
|
492
|
+
* @since 2.10.3
|
|
493
|
+
*/
|
|
345
494
|
async flush() {
|
|
346
495
|
return new Promise((resolve) => {
|
|
347
496
|
if (typeof this.logger.flush === 'function') {
|
|
@@ -353,6 +502,7 @@ export class TimonelLogger {
|
|
|
353
502
|
});
|
|
354
503
|
}
|
|
355
504
|
}
|
|
505
|
+
// Performance-optimized sensitive field detection using Set for O(1) lookups
|
|
356
506
|
TimonelLogger.SENSITIVE_FIELDS = new Set([
|
|
357
507
|
'password',
|
|
358
508
|
'passphrase',
|
|
@@ -395,12 +545,24 @@ TimonelLogger.SENSITIVE_FIELDS = new Set([
|
|
|
395
545
|
'p12',
|
|
396
546
|
'pfx',
|
|
397
547
|
]);
|
|
548
|
+
/**
|
|
549
|
+
* Global logger instance for the Timonel application
|
|
550
|
+
* Configured based on environment variables
|
|
551
|
+
* @since 2.10.3
|
|
552
|
+
*/
|
|
398
553
|
export const logger = new TimonelLogger({
|
|
399
554
|
level: getLogLevelFromEnv(),
|
|
400
555
|
silent: process.env.TIMONEL_SILENT === 'true',
|
|
401
556
|
service: 'timonel',
|
|
402
557
|
environment: process.env.NODE_ENV || 'development',
|
|
403
558
|
});
|
|
559
|
+
/**
|
|
560
|
+
* Factory function for creating component-specific loggers
|
|
561
|
+
* @param component - Component name
|
|
562
|
+
* @param additionalConfig - Additional configuration
|
|
563
|
+
* @returns Configured logger instance
|
|
564
|
+
* @since 2.10.3
|
|
565
|
+
*/
|
|
404
566
|
export function createLogger(component, additionalConfig) {
|
|
405
567
|
return new TimonelLogger({
|
|
406
568
|
...additionalConfig,
|
|
@@ -411,6 +573,11 @@ export function createLogger(component, additionalConfig) {
|
|
|
411
573
|
},
|
|
412
574
|
});
|
|
413
575
|
}
|
|
576
|
+
/**
|
|
577
|
+
* Gets log level from environment variables
|
|
578
|
+
* @returns Log level based on environment
|
|
579
|
+
* @since 2.10.3
|
|
580
|
+
*/
|
|
414
581
|
function getLogLevelFromEnv() {
|
|
415
582
|
const envLevel = process.env.LOG_LEVEL?.toUpperCase();
|
|
416
583
|
switch (envLevel) {
|
|
@@ -428,6 +595,7 @@ function getLogLevelFromEnv() {
|
|
|
428
595
|
case 'TRACE':
|
|
429
596
|
return LogLevel.TRACE;
|
|
430
597
|
default:
|
|
598
|
+
// Default to INFO in production, DEBUG in development
|
|
431
599
|
return process.env.NODE_ENV === 'production' ? LogLevel.INFO : LogLevel.DEBUG;
|
|
432
600
|
}
|
|
433
601
|
}
|