const path = require('path'); const { logsDir } = require('./paths'); const { appendJsonLine } = require('./fs'); const SECRET_PATTERNS = ['token', 'secret', 'password', 'authorization']; function sanitizeValue(value) { if (Array.isArray(value)) { return value.map(sanitizeValue); } if (!value || typeof value !== 'object') { return value; } return Object.fromEntries( Object.entries(value).map(([key, entryValue]) => { const lower = key.toLowerCase(); if (SECRET_PATTERNS.some((pattern) => lower.includes(pattern))) { return [key, '[redacted]']; } return [key, sanitizeValue(entryValue)]; }) ); } function dayString(timestamp) { return timestamp.slice(0, 10); } async function log(entry) { const timestamp = new Date().toISOString(); const logEntry = { timestamp, level: entry.level || 'info', service: entry.service, node_id: entry.node_id || null, tenant_id: entry.tenant_id || null, request_id: entry.request_id || null, correlation_id: entry.correlation_id || null, action: entry.action || 'unknown', result: entry.result || 'unknown', metadata: sanitizeValue(entry.metadata || {}), }; await appendJsonLine(path.join(logsDir, dayString(timestamp), `${logEntry.service}.ndjson`), logEntry); process.stdout.write(`${JSON.stringify(logEntry)}\n`); return logEntry; } function createLogger(baseFields) { return { info(action, result, metadata) { return log({ ...baseFields, level: 'info', action, result, metadata }); }, warn(action, result, metadata) { return log({ ...baseFields, level: 'warn', action, result, metadata }); }, error(action, result, metadata) { return log({ ...baseFields, level: 'error', action, result, metadata }); }, }; } module.exports = { log, createLogger, };