Files
skipper/shared/logs.js
2026-04-05 15:28:04 +02:00

72 lines
1.8 KiB
JavaScript

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,
};