// Package common 日志工具 package common import ( "fmt" "io" "os" "path/filepath" "sync" "time" "server/config" ) // 日志级别 const ( LevelDebug = iota LevelInfo LevelWarn LevelError ) var levelNames = map[int]string{ LevelDebug: "DEBUG", LevelInfo: "INFO", LevelWarn: "WARN", LevelError: "ERROR", } var levelValues = map[string]int{ "debug": LevelDebug, "info": LevelInfo, "warn": LevelWarn, "error": LevelError, } // Logger 日志记录器 type Logger struct { level int file *os.File htmlWriter *htmlLogWriter mu sync.Mutex console bool } var ( defaultLogger *Logger startCount int once sync.Once ) // InitLogger 初始化日志 func InitLogger() { once.Do(func() { cfg := config.AppConfig.Log level := levelValues[cfg.Level] // 创建日志目录 if err := os.MkdirAll(cfg.Dir, 0755); err != nil { fmt.Println("创建日志目录失败:", err) return } // 计算启动次数 startCount = getStartCount(cfg.Dir) // 创建日志文件 filename := fmt.Sprintf("%s-%d.html", time.Now().Format("2006-01-02"), startCount) logFilepath := filepath.Join(cfg.Dir, filename) file, err := os.OpenFile(logFilepath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) if err != nil { fmt.Println("创建日志文件失败:", err) return } htmlWriter := newHtmlLogWriter(file) defaultLogger = &Logger{ level: level, file: file, htmlWriter: htmlWriter, console: cfg.Console, } fmt.Printf("日志文件: %s\n", logFilepath) }) } // getStartCount 获取今日启动次数 func getStartCount(dir string) int { today := time.Now().Format("2006-01-02") pattern := filepath.Join(dir, today+"*.html") matches, _ := filepath.Glob(pattern) return len(matches) + 1 } // CloseLogger 关闭日志 func CloseLogger() { if defaultLogger != nil && defaultLogger.file != nil { defaultLogger.htmlWriter.writeFooter() defaultLogger.file.Close() } } func (l *Logger) log(level int, format string, args ...interface{}) { if l == nil || level < l.level { return } l.mu.Lock() defer l.mu.Unlock() msg := fmt.Sprintf(format, args...) timestamp := time.Now().Format("2006-01-02 15:04:05.000") levelName := levelNames[level] // 写入HTML文件 l.htmlWriter.writeLog(timestamp, levelName, msg) // 输出到控制台 if l.console { fmt.Printf("[%s] [%s] %s\n", timestamp, levelName, msg) } } // LogDebug 调试日志 func LogDebug(format string, args ...interface{}) { if defaultLogger != nil { defaultLogger.log(LevelDebug, format, args...) } } // LogInfo 信息日志 func LogInfo(format string, args ...interface{}) { if defaultLogger != nil { defaultLogger.log(LevelInfo, format, args...) } } // LogWarn 警告日志 func LogWarn(format string, args ...interface{}) { if defaultLogger != nil { defaultLogger.log(LevelWarn, format, args...) } } // LogError 错误日志 func LogError(format string, args ...interface{}) { if defaultLogger != nil { defaultLogger.log(LevelError, format, args...) } } // 简短别名 var ( Debug = LogDebug Info = LogInfo Warn = LogWarn ) // htmlLogWriter HTML日志写入器 type htmlLogWriter struct { writer io.Writer initialized bool } func newHtmlLogWriter(w io.Writer) *htmlLogWriter { hw := &htmlLogWriter{writer: w} hw.writeHeader() return hw } func (h *htmlLogWriter) writeHeader() { html := `