Refactor logging in hooks, services, and routes to use centralized logger
- Replaced console.log and console.error statements with logger.info and logger.error in new-hook.ts, SDKAgent.ts, SessionManager.ts, and SessionRoutes.ts for consistent logging. - Introduced log file creation and management in logger.ts, ensuring logs are saved to a file with a date-based naming convention. - Enhanced error handling in logger to prevent crashes if log file operations fail.
This commit is contained in:
+52
-4
@@ -4,6 +4,8 @@
|
||||
*/
|
||||
|
||||
import { SettingsDefaultsManager } from '../shared/SettingsDefaultsManager.js';
|
||||
import { appendFileSync, existsSync, mkdirSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
export enum LogLevel {
|
||||
DEBUG = 0,
|
||||
@@ -25,19 +27,55 @@ interface LogContext {
|
||||
class Logger {
|
||||
private level: LogLevel | null = null;
|
||||
private useColor: boolean;
|
||||
private logFilePath: string | null = null;
|
||||
|
||||
constructor() {
|
||||
// Disable colors when output is not a TTY (e.g., PM2 logs)
|
||||
this.useColor = process.stdout.isTTY ?? false;
|
||||
this.initializeLogFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazy-load log level from settings (breaks circular dependency with SettingsDefaultsManager)
|
||||
* Initialize log file path and ensure directory exists
|
||||
*/
|
||||
private initializeLogFile(): void {
|
||||
try {
|
||||
// Get data directory from settings
|
||||
const dataDir = SettingsDefaultsManager.get('CLAUDE_MEM_DATA_DIR');
|
||||
const logsDir = join(dataDir, 'logs');
|
||||
|
||||
// Ensure logs directory exists
|
||||
if (!existsSync(logsDir)) {
|
||||
mkdirSync(logsDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Create log file path with date
|
||||
const date = new Date().toISOString().split('T')[0];
|
||||
this.logFilePath = join(logsDir, `claude-mem-${date}.log`);
|
||||
} catch (error) {
|
||||
// If log file initialization fails, just log to console
|
||||
console.error('[LOGGER] Failed to initialize log file:', error);
|
||||
this.logFilePath = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazy-load log level from settings file (not hardcoded defaults!)
|
||||
*/
|
||||
private getLevel(): LogLevel {
|
||||
if (this.level === null) {
|
||||
const envLevel = SettingsDefaultsManager.get('CLAUDE_MEM_LOG_LEVEL').toUpperCase();
|
||||
this.level = LogLevel[envLevel as keyof typeof LogLevel] ?? LogLevel.INFO;
|
||||
try {
|
||||
// Load settings from file to get user's actual log level
|
||||
const dataDir = SettingsDefaultsManager.get('CLAUDE_MEM_DATA_DIR');
|
||||
const settingsPath = join(dataDir, 'settings.json');
|
||||
const settings = SettingsDefaultsManager.loadFromFile(settingsPath);
|
||||
const envLevel = settings.CLAUDE_MEM_LOG_LEVEL.toUpperCase();
|
||||
this.level = LogLevel[envLevel as keyof typeof LogLevel] ?? LogLevel.INFO;
|
||||
} catch (error) {
|
||||
// Fallback to INFO if settings can't be loaded
|
||||
console.error('[LOGGER] Failed to load settings, using INFO level:', error);
|
||||
this.level = LogLevel.INFO;
|
||||
}
|
||||
}
|
||||
return this.level;
|
||||
}
|
||||
@@ -219,12 +257,22 @@ class Logger {
|
||||
|
||||
const logLine = `[${timestamp}] [${levelStr}] [${componentStr}] ${correlationStr}${message}${contextStr}${dataStr}`;
|
||||
|
||||
// Output to appropriate stream
|
||||
// Output to console
|
||||
if (level === LogLevel.ERROR) {
|
||||
console.error(logLine);
|
||||
} else {
|
||||
console.log(logLine);
|
||||
}
|
||||
|
||||
// Output to log file
|
||||
if (this.logFilePath) {
|
||||
try {
|
||||
appendFileSync(this.logFilePath, logLine + '\n', 'utf8');
|
||||
} catch (error) {
|
||||
// If file write fails, just continue (don't crash)
|
||||
console.error('[LOGGER] Failed to write to log file:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Public logging methods
|
||||
|
||||
Reference in New Issue
Block a user