Files
2025-07-03 12:49:49 +08:00

122 lines
3.0 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package utils
import (
"log"
"os"
"path/filepath"
"time"
)
// DailyFileWriter 日志文件写入器
type DailyFileWriter struct {
Dir string
Freq string
Prefix string
File *os.File
Current string
Logger *log.Logger
}
// NewDailyFileWriter 创建每日日志写入器
func NewDailyFileWriter(dir, freq string, logger *log.Logger, prefix string) *DailyFileWriter {
writer := &DailyFileWriter{
Dir: dir,
Freq: freq,
Prefix: prefix,
Logger: logger,
}
writer.rotate()
return writer
}
func (w *DailyFileWriter) getLogFileName() string {
baseName := w.Prefix + "-"
switch w.Freq {
case "daily":
return baseName + time.Now().Format("2006-01-02") + ".log"
case "hourly":
return baseName + time.Now().Format("2006-01-02-15") + ".log"
default: // 默认按分钟(适合开发)
return baseName + time.Now().Format("2006-01-02-15-04") + ".log"
}
}
func (w *DailyFileWriter) rotate() {
filename := w.getLogFileName()
filePath := filepath.Join(w.Dir, filename)
// 如果已经打开了相同的文件,则不需要重新打开
if w.Current == filePath {
return
}
// 关闭当前文件(如果存在)
if w.File != nil {
w.File.Close()
}
// 确保目录存在(双重保障)
if err := os.MkdirAll(w.Dir, 0755); err != nil {
// 如果创建目录失败,尝试使用备用目录
if w.Dir != "logs" {
w.Logger.Printf("⚠️ 无法创建日志目录 %s尝试使用备用目录: %v", w.Dir, err)
w.Dir = "logs"
if err := os.MkdirAll(w.Dir, 0755); err != nil {
w.Logger.Fatalf("❌ 无法创建备用日志目录: %v", err)
}
} else {
w.Logger.Fatalf("❌ 无法创建日志目录: %v", err)
}
}
// 打开文件(如果文件不存在则创建)
file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
// 如果打开文件失败,尝试使用系统临时目录作为备选
fallbackPath := filepath.Join(os.TempDir(), "xk-websocket-logs", filename)
w.Logger.Printf("⚠️ 无法打开日志文件 %s尝试备选路径: %s (%v)", filePath, fallbackPath, err)
// 确保备选目录存在
if err := os.MkdirAll(filepath.Dir(fallbackPath), 0755); err != nil {
w.Logger.Fatalf("❌ 无法创建备选日志目录: %v", err)
}
file, err = os.OpenFile(fallbackPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
w.Logger.Fatalf("❌ 无法打开备选日志文件: %v", err)
}
}
w.File = file
w.Current = filePath
}
// Write 实现io.Writer接口
func (w *DailyFileWriter) Write(p []byte) (n int, err error) {
// 检查是否需要轮转日志
needRotate := false
switch w.Freq {
case "daily":
needRotate = time.Now().Day() != time.Now().Add(-time.Second).Day()
case "hourly":
needRotate = time.Now().Hour() != time.Now().Add(-time.Second).Hour()
default: // 每分钟轮转(开发模式)
needRotate = true
}
if needRotate {
w.rotate()
}
return w.File.Write(p)
}
// Close 关闭日志文件
func (w *DailyFileWriter) Close() error {
if w.File != nil {
return w.File.Close()
}
return nil
}