211 lines
4.4 KiB
Go
211 lines
4.4 KiB
Go
// 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 := `<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>应用日志</title>
|
|
<style>
|
|
body { font-family: Consolas, monospace; background: #1e1e1e; color: #d4d4d4; padding: 20px; }
|
|
.log { margin: 2px 0; padding: 4px 8px; border-radius: 3px; }
|
|
.DEBUG { background: #2d2d2d; color: #9cdcfe; }
|
|
.INFO { background: #1e3a1e; color: #4ec9b0; }
|
|
.WARN { background: #3a3a1e; color: #dcdcaa; }
|
|
.ERROR { background: #3a1e1e; color: #f14c4c; }
|
|
.time { color: #808080; }
|
|
.level { font-weight: bold; width: 60px; display: inline-block; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h2>应用日志 - ` + time.Now().Format("2006-01-02") + `</h2>
|
|
<div id="logs">
|
|
`
|
|
h.writer.Write([]byte(html))
|
|
h.initialized = true
|
|
}
|
|
|
|
func (h *htmlLogWriter) writeLog(timestamp, level, msg string) {
|
|
html := fmt.Sprintf(`<div class="log %s"><span class="time">[%s]</span> <span class="level">[%s]</span> %s</div>
|
|
`, level, timestamp, level, msg)
|
|
h.writer.Write([]byte(html))
|
|
}
|
|
|
|
func (h *htmlLogWriter) writeFooter() {
|
|
html := `</div>
|
|
</body>
|
|
</html>`
|
|
h.writer.Write([]byte(html))
|
|
}
|