import fs from 'node:fs'; import path from 'node:path'; import pino, { type Logger } from 'pino'; import type { AppConfig } from './config.js'; const LOG_RETENTION_DAYS = 7; function cleanupExpiredLogs(logsDir: string) { if (!fs.existsSync(logsDir)) { return; } const expiryTime = Date.now() - LOG_RETENTION_DAYS * 24 * 60 * 60 * 1000; for (const entry of fs.readdirSync(logsDir, { withFileTypes: true })) { if (!entry.isFile() || !entry.name.startsWith('server.log')) { continue; } const fullPath = path.join(logsDir, entry.name); const stats = fs.statSync(fullPath); if (stats.mtimeMs < expiryTime) { fs.rmSync(fullPath, { force: true }); } } } export function createLogger(config: AppConfig): Logger { fs.mkdirSync(config.logsDir, { recursive: true }); cleanupExpiredLogs(config.logsDir); const transport = pino.transport({ targets: [ { target: 'pino-roll', level: config.logLevel, options: { file: path.join(config.logsDir, 'server.log'), mkdir: true, size: '10m', frequency: 'daily', dateFormat: 'yyyy-MM-dd', }, }, { target: 'pino/file', level: config.logLevel, options: { destination: 1, }, }, ], }); return pino( { level: config.logLevel, timestamp: pino.stdTimeFunctions.isoTime, base: undefined, }, transport, ); }