* Internal method to log a message with the specified level
(level: LogLevel, message: string, ...args: unknown[])
| 226 | * Internal method to log a message with the specified level |
| 227 | */ |
| 228 | private log(level: LogLevel, message: string, ...args: unknown[]) { |
| 229 | if (!this.shouldLog(level)) return |
| 230 | |
| 231 | const timestamp = new Date().toISOString() |
| 232 | const formattedArgs = this.formatArgs(args) |
| 233 | |
| 234 | const reqCtx = getRequestContext() |
| 235 | const effectiveMetadata = reqCtx |
| 236 | ? { |
| 237 | requestId: reqCtx.requestId, |
| 238 | method: reqCtx.method, |
| 239 | path: reqCtx.path, |
| 240 | ...this.metadata, |
| 241 | } |
| 242 | : this.metadata |
| 243 | const metadataEntries = Object.entries(effectiveMetadata).filter(([_, v]) => v !== undefined) |
| 244 | const metadataStr = |
| 245 | metadataEntries.length > 0 |
| 246 | ? ` {${metadataEntries.map(([k, v]) => `${k}=${v}`).join(' ')}}` |
| 247 | : '' |
| 248 | |
| 249 | if (this.config.colorize) { |
| 250 | let levelColor: (text: string) => string |
| 251 | const moduleColor = chalk.cyan |
| 252 | const timestampColor = chalk.gray |
| 253 | |
| 254 | switch (level) { |
| 255 | case LogLevel.DEBUG: |
| 256 | levelColor = chalk.blue |
| 257 | break |
| 258 | case LogLevel.INFO: |
| 259 | levelColor = chalk.green |
| 260 | break |
| 261 | case LogLevel.WARN: |
| 262 | levelColor = chalk.yellow |
| 263 | break |
| 264 | case LogLevel.ERROR: |
| 265 | levelColor = chalk.red |
| 266 | break |
| 267 | } |
| 268 | |
| 269 | const coloredMeta = metadataStr ? ` ${chalk.magenta(metadataStr.trim())}` : '' |
| 270 | const coloredPrefix = `${timestampColor(`[${timestamp}]`)} ${levelColor(`[${level}]`)} ${moduleColor(`[${this.module}]`)}${coloredMeta}` |
| 271 | |
| 272 | if (level === LogLevel.ERROR) { |
| 273 | console.error(coloredPrefix, message, ...formattedArgs) |
| 274 | } else { |
| 275 | console.log(coloredPrefix, message, ...formattedArgs) |
| 276 | } |
| 277 | } else { |
| 278 | // Structured JSON for production — CloudWatch Log Insights auto-parses JSON lines |
| 279 | const entry: Record<string, unknown> = { |
| 280 | timestamp, |
| 281 | level, |
| 282 | module: this.module, |
| 283 | message, |
| 284 | } |
| 285 | for (const [k, v] of metadataEntries) { |
no test coverage detected