feat: implement Winston logging service
- Add LogEntry interface for structured log data - Create LoggerService with Winston integration - Support for console and file transports (app.log, error.log) - Implement UI log notification callbacks - Provide info, warn, error, and debug logging methods - Configure log rotation (10MB max, 5 files retained) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
6
src/main/models/logger.types.ts
Normal file
6
src/main/models/logger.types.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export interface LogEntry {
|
||||||
|
timestamp: string;
|
||||||
|
level: string;
|
||||||
|
message: string;
|
||||||
|
details?: any;
|
||||||
|
}
|
||||||
94
src/main/services/logger.service.ts
Normal file
94
src/main/services/logger.service.ts
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
import winston from 'winston';
|
||||||
|
import path from 'path';
|
||||||
|
import { app } from 'electron';
|
||||||
|
import { LogEntry } from '../models/logger.types';
|
||||||
|
|
||||||
|
export class LoggerService {
|
||||||
|
private static instance: winston.Logger | null = null;
|
||||||
|
private static uiLogCallbacks: Set<(logEntry: LogEntry) => void> = new Set();
|
||||||
|
|
||||||
|
static initialize(): winston.Logger {
|
||||||
|
if (this.instance) {
|
||||||
|
return this.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
const logDir = path.join(app.getPath('userData'), 'logs');
|
||||||
|
|
||||||
|
this.instance = winston.createLogger({
|
||||||
|
level: 'info',
|
||||||
|
format: winston.format.combine(
|
||||||
|
winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
|
||||||
|
winston.format.errors({ stack: true }),
|
||||||
|
winston.format.printf(({ level, message, timestamp, stack }) => {
|
||||||
|
if (stack) {
|
||||||
|
return `[${timestamp}] [${level.toUpperCase()}] ${message}\n${stack}`;
|
||||||
|
}
|
||||||
|
return `[${timestamp}] [${level.toUpperCase()}] ${message}`;
|
||||||
|
})
|
||||||
|
),
|
||||||
|
transports: [
|
||||||
|
new winston.transports.Console({
|
||||||
|
format: winston.format.combine(
|
||||||
|
winston.format.colorize(),
|
||||||
|
winston.format.simple()
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
new winston.transports.File({
|
||||||
|
filename: path.join(logDir, 'app.log'),
|
||||||
|
maxsize: 10 * 1024 * 1024,
|
||||||
|
maxFiles: 5,
|
||||||
|
}),
|
||||||
|
new winston.transports.File({
|
||||||
|
filename: path.join(logDir, 'error.log'),
|
||||||
|
level: 'error',
|
||||||
|
maxsize: 10 * 1024 * 1024,
|
||||||
|
maxFiles: 5,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
return this.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static onUILog(callback: (logEntry: LogEntry) => void): () => void {
|
||||||
|
this.uiLogCallbacks.add(callback);
|
||||||
|
return () => {
|
||||||
|
this.uiLogCallbacks.delete(callback);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static notifyUI(level: string, message: string, details?: any): void {
|
||||||
|
const logEntry: LogEntry = {
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
level,
|
||||||
|
message,
|
||||||
|
details,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.uiLogCallbacks.forEach((callback) => callback(logEntry));
|
||||||
|
}
|
||||||
|
|
||||||
|
static info(message: string, details?: any): void {
|
||||||
|
if (!this.instance) this.initialize();
|
||||||
|
this.instance!.info(message, details);
|
||||||
|
this.notifyUI('info', message, details);
|
||||||
|
}
|
||||||
|
|
||||||
|
static warn(message: string, details?: any): void {
|
||||||
|
if (!this.instance) this.initialize();
|
||||||
|
this.instance!.warning(message, details);
|
||||||
|
this.notifyUI('warn', message, details);
|
||||||
|
}
|
||||||
|
|
||||||
|
static error(message: string, details?: any): void {
|
||||||
|
if (!this.instance) this.initialize();
|
||||||
|
this.instance!.error(message, details);
|
||||||
|
this.notifyUI('error', message, details);
|
||||||
|
}
|
||||||
|
|
||||||
|
static debug(message: string, details?: any): void {
|
||||||
|
if (!this.instance) this.initialize();
|
||||||
|
this.instance!.debug(message, details);
|
||||||
|
this.notifyUI('debug', message, details);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user