Harden support logging and debug setup
This commit is contained in:
@@ -3,6 +3,9 @@ import path from "node:path";
|
||||
|
||||
type AuditLevel = "INFO" | "WARN" | "ERROR";
|
||||
|
||||
const AUDIT_LOG_MAX_FILE_BYTES = Number(process.env.RD_AUDIT_LOG_MAX_BYTES || 10 * 1024 * 1024);
|
||||
const AUDIT_LOG_RETENTION_DAYS = Number(process.env.RD_AUDIT_LOG_RETENTION_DAYS || 30);
|
||||
|
||||
let auditLogPath: string | null = null;
|
||||
|
||||
function sanitizeFieldValue(value: unknown): string {
|
||||
@@ -32,10 +35,46 @@ function formatFields(fields?: Record<string, unknown>): string {
|
||||
return parts.length > 0 ? ` | ${parts.join(" | ")}` : "";
|
||||
}
|
||||
|
||||
function rotateIfNeeded(filePath: string): void {
|
||||
try {
|
||||
const stat = fs.statSync(filePath);
|
||||
if (stat.size < AUDIT_LOG_MAX_FILE_BYTES) {
|
||||
return;
|
||||
}
|
||||
const backup = `${filePath}.old`;
|
||||
try {
|
||||
fs.rmSync(backup, { force: true });
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
fs.renameSync(filePath, backup);
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
function cleanupOldBackup(filePath: string): void {
|
||||
const backup = `${filePath}.old`;
|
||||
try {
|
||||
const stat = fs.statSync(backup);
|
||||
const cutoff = Date.now() - AUDIT_LOG_RETENTION_DAYS * 24 * 60 * 60 * 1000;
|
||||
if (stat.mtimeMs < cutoff) {
|
||||
fs.rmSync(backup, { force: true });
|
||||
}
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
export function initAuditLog(baseDir: string): void {
|
||||
auditLogPath = path.join(baseDir, "audit.log");
|
||||
try {
|
||||
fs.mkdirSync(path.dirname(auditLogPath), { recursive: true });
|
||||
cleanupOldBackup(auditLogPath);
|
||||
if (!fs.existsSync(auditLogPath)) {
|
||||
fs.writeFileSync(auditLogPath, "", "utf8");
|
||||
}
|
||||
rotateIfNeeded(auditLogPath);
|
||||
if (!fs.existsSync(auditLogPath)) {
|
||||
fs.writeFileSync(auditLogPath, "", "utf8");
|
||||
}
|
||||
@@ -50,6 +89,10 @@ export function logAuditEvent(level: AuditLevel, message: string, fields?: Recor
|
||||
return;
|
||||
}
|
||||
try {
|
||||
rotateIfNeeded(auditLogPath);
|
||||
if (!fs.existsSync(auditLogPath)) {
|
||||
fs.writeFileSync(auditLogPath, "", "utf8");
|
||||
}
|
||||
fs.appendFileSync(
|
||||
auditLogPath,
|
||||
`${new Date().toISOString()} [${level}] ${message}${formatFields(fields)}\n`,
|
||||
|
||||
Reference in New Issue
Block a user