api-amr/debug_logger.ts

283 lines
7.9 KiB
TypeScript
Raw Normal View History

2025-06-04 19:15:02 +08:00
// debug_logger.ts - 调试日志模块
export enum LogLevel {
ERROR = 0,
WARN = 1,
INFO = 2,
DEBUG = 3,
TRACE = 4
}
export interface LogConfig {
level: LogLevel;
enableTimestamp: boolean;
enableColors: boolean;
enableFileOutput: boolean;
logFilePath?: string;
modules: {
[moduleName: string]: LogLevel;
};
}
const DEFAULT_CONFIG: LogConfig = {
level: LogLevel.INFO,
enableTimestamp: true,
enableColors: true,
enableFileOutput: false,
modules: {}
};
class DebugLogger {
private config: LogConfig;
private logFile?: Deno.FsFile;
constructor(config: Partial<LogConfig> = {}) {
this.config = { ...DEFAULT_CONFIG, ...config };
if (this.config.enableFileOutput && this.config.logFilePath) {
this.initLogFile();
}
}
private async initLogFile() {
try {
this.logFile = await Deno.open(this.config.logFilePath!, {
create: true,
write: true,
append: true
});
} catch (error) {
console.error(`Failed to open log file: ${error}`);
}
}
private getTimestamp(): string {
if (!this.config.enableTimestamp) return "";
return `[${new Date().toISOString()}] `;
}
private getColorCode(level: LogLevel): string {
if (!this.config.enableColors) return "";
switch (level) {
case LogLevel.ERROR: return "\x1b[31m"; // Red
case LogLevel.WARN: return "\x1b[33m"; // Yellow
case LogLevel.INFO: return "\x1b[36m"; // Cyan
case LogLevel.DEBUG: return "\x1b[32m"; // Green
case LogLevel.TRACE: return "\x1b[35m"; // Magenta
default: return "";
}
}
private getResetCode(): string {
return this.config.enableColors ? "\x1b[0m" : "";
}
private getLevelName(level: LogLevel): string {
switch (level) {
case LogLevel.ERROR: return "ERROR";
case LogLevel.WARN: return "WARN ";
case LogLevel.INFO: return "INFO ";
case LogLevel.DEBUG: return "DEBUG";
case LogLevel.TRACE: return "TRACE";
default: return "UNKNOWN";
}
}
private shouldLog(level: LogLevel, module?: string): boolean {
// 检查模块特定的日志级别
if (module && this.config.modules[module] !== undefined) {
return level <= this.config.modules[module];
}
// 使用全局日志级别
return level <= this.config.level;
}
private formatMessage(level: LogLevel, module: string, message: string, ...args: any[]): string {
const timestamp = this.getTimestamp();
const colorCode = this.getColorCode(level);
const resetCode = this.getResetCode();
const levelName = this.getLevelName(level);
const formattedArgs = args.length > 0 ? " " + args.map(arg =>
typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)
).join(" ") : "";
return `${timestamp}${colorCode}[${levelName}]${resetCode} [${module}] ${message}${formattedArgs}`;
}
private async writeLog(formattedMessage: string) {
// 输出到控制台
console.log(formattedMessage);
// 输出到文件
if (this.logFile) {
try {
const encoder = new TextEncoder();
await this.logFile.write(encoder.encode(formattedMessage + "\n"));
await this.logFile.sync();
} catch (error) {
console.error(`Failed to write to log file: ${error}`);
}
}
}
log(level: LogLevel, module: string, message: string, ...args: any[]) {
if (!this.shouldLog(level, module)) return;
const formattedMessage = this.formatMessage(level, module, message, ...args);
this.writeLog(formattedMessage);
}
error(module: string, message: string, ...args: any[]) {
this.log(LogLevel.ERROR, module, message, ...args);
}
warn(module: string, message: string, ...args: any[]) {
this.log(LogLevel.WARN, module, message, ...args);
}
info(module: string, message: string, ...args: any[]) {
this.log(LogLevel.INFO, module, message, ...args);
}
debug(module: string, message: string, ...args: any[]) {
this.log(LogLevel.DEBUG, module, message, ...args);
}
trace(module: string, message: string, ...args: any[]) {
this.log(LogLevel.TRACE, module, message, ...args);
}
// 设置模块特定的日志级别
setModuleLevel(module: string, level: LogLevel) {
this.config.modules[module] = level;
}
// 设置全局日志级别
setGlobalLevel(level: LogLevel) {
this.config.level = level;
}
// 获取当前配置
getConfig(): LogConfig {
return { ...this.config };
}
// 关闭日志文件
async close() {
if (this.logFile) {
await this.logFile.close();
}
}
}
// 创建全局调试器实例
export const debugLogger = new DebugLogger({
level: LogLevel.DEBUG,
enableTimestamp: true,
enableColors: true,
enableFileOutput: false,
logFilePath: "./debug.log",
modules: {
"DEVICE_SIMULATOR": LogLevel.ERROR,
"MODBUS": LogLevel.ERROR,
"MQTT": LogLevel.ERROR,
"REGISTER_CONFIG": LogLevel.ERROR,
"DEVICE_MANAGER": LogLevel.ERROR,
"SIMULATOR_MAIN": LogLevel.ERROR
}
});
// 便捷的模块日志器创建函数
export function createModuleLogger(moduleName: string) {
return {
error: (message: string, ...args: any[]) => debugLogger.error(moduleName, message, ...args),
warn: (message: string, ...args: any[]) => debugLogger.warn(moduleName, message, ...args),
info: (message: string, ...args: any[]) => debugLogger.info(moduleName, message, ...args),
debug: (message: string, ...args: any[]) => debugLogger.debug(moduleName, message, ...args),
trace: (message: string, ...args: any[]) => debugLogger.trace(moduleName, message, ...args)
};
}
// 性能监控工具
export class PerformanceMonitor {
private timers: Map<string, number> = new Map();
private logger = createModuleLogger("PERFORMANCE");
start(label: string) {
this.timers.set(label, performance.now());
this.logger.trace(`⏱️ Started timer: ${label}`);
}
end(label: string): number {
const startTime = this.timers.get(label);
if (!startTime) {
this.logger.trace(`⚠️ Timer not found: ${label}`);
return 0;
}
const duration = performance.now() - startTime;
this.timers.delete(label);
this.logger.trace(`⏱️ ${label}: ${duration.toFixed(2)}ms`);
return duration;
}
measure<T>(label: string, fn: () => T): T {
this.start(label);
try {
const result = fn();
this.end(label);
return result;
} catch (error) {
this.end(label);
this.logger.error(`❌ Error in ${label}:`, error);
throw error;
}
}
async measureAsync<T>(label: string, fn: () => Promise<T>): Promise<T> {
this.start(label);
try {
const result = await fn();
this.end(label);
return result;
} catch (error) {
this.end(label);
this.logger.error(`❌ Error in ${label}:`, error);
throw error;
}
}
}
export const perfMonitor = new PerformanceMonitor();
// 内存使用监控
export function logMemoryUsage(module: string) {
if (typeof Deno !== 'undefined' && Deno.memoryUsage) {
const memory = Deno.memoryUsage();
const logger = createModuleLogger(module);
logger.debug(`💾 Memory usage:`, {
rss: `${(memory.rss / 1024 / 1024).toFixed(2)}MB`,
heapTotal: `${(memory.heapTotal / 1024 / 1024).toFixed(2)}MB`,
heapUsed: `${(memory.heapUsed / 1024 / 1024).toFixed(2)}MB`,
external: `${(memory.external / 1024 / 1024).toFixed(2)}MB`
});
}
}
// 调试配置管理
export function setDebugLevel(level: LogLevel | string, module?: string) {
const logLevel = typeof level === 'string' ?
LogLevel[level.toUpperCase() as keyof typeof LogLevel] : level;
if (module) {
debugLogger.setModuleLevel(module, logLevel);
console.log(`🔧 Set debug level for ${module}: ${LogLevel[logLevel]}`);
} else {
debugLogger.setGlobalLevel(logLevel);
console.log(`🔧 Set global debug level: ${LogLevel[logLevel]}`);
}
}
// 调试工具已在上面导出