打包、拆分

This commit is contained in:
2025-07-03 12:49:49 +08:00
parent fb3918124d
commit cb79e11f9b
7 changed files with 439 additions and 125 deletions

View File

@@ -1,93 +1,121 @@
package utils
import (
"fmt"
"log"
"os"
"sync"
"path/filepath"
"time"
)
// DailyFileWriter 日志文件写入器
type DailyFileWriter struct {
currentFile *os.File
mu sync.Mutex
logDir string
frequency string
currentDate string
currentSlot int
logger *log.Logger
nodeID string
Dir string
Freq string
Prefix string
File *os.File
Current string
Logger *log.Logger
}
func NewDailyFileWriter(logDir, frequency string, logger *log.Logger, nodeID string) *DailyFileWriter {
return &DailyFileWriter{
logDir: logDir,
frequency: frequency,
logger: logger,
nodeID: nodeID,
// 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) Write(p []byte) (n int, err error) {
w.mu.Lock()
defer w.mu.Unlock()
func (w *DailyFileWriter) rotate() {
filename := w.getLogFileName()
filePath := filepath.Join(w.Dir, filename)
now := time.Now()
if w.needRotate(now) {
if err := w.rotateFile(now); err != nil {
w.logger.Printf("❌❌ 日志文件切换失败: %v", err)
return 0, err
// 如果已经打开了相同的文件,则不需要重新打开
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)
}
}
if w.currentFile == nil {
if err := w.rotateFile(now); err != nil {
return 0, err
}
}
return w.currentFile.Write(p)
}
func (w *DailyFileWriter) needRotate(now time.Time) bool {
currentDate := now.Format("2006-01-02")
if w.frequency == "daily" {
return w.currentDate != currentDate
} else if w.frequency == "10min" {
currentSlot := (now.Hour()*60 + now.Minute()) / 10
return w.currentDate != currentDate || w.currentSlot != currentSlot
}
return false
}
func (w *DailyFileWriter) rotateFile(now time.Time) error {
if w.currentFile != nil {
w.currentFile.Close()
}
dateStr := now.Format("2006-01-02")
var slotStr string
if w.frequency == "10min" {
slot := (now.Hour()*60 + now.Minute()) / 10
slotStr = fmt.Sprintf("%03d", slot)
} else {
slotStr = "000"
}
if err := os.MkdirAll(w.logDir, 0755); err != nil {
return fmt.Errorf("创建日志目录失败: %w", err)
}
filename := fmt.Sprintf("%s/xk-websocket-%s-%s.log", w.logDir, dateStr, slotStr)
file, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
// 打开文件(如果文件不存在则创建)
file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
return fmt.Errorf("打开日志文件失败: %w", err)
// 如果打开文件失败,尝试使用系统临时目录作为备选
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.currentFile = file
w.currentDate = dateStr
if w.frequency == "10min" {
w.currentSlot = (now.Hour()*60 + now.Minute()) / 10
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
}

17
utils/network.go Normal file
View File

@@ -0,0 +1,17 @@
package utils
import (
"net"
)
// GetOutboundIP 获取本机的出口IP地址
func GetOutboundIP() string {
conn, err := net.Dial("udp", "8.8.8.8:80")
if err != nil {
return "127.0.0.1"
}
defer conn.Close()
localAddr := conn.LocalAddr().(*net.UDPAddr)
return localAddr.IP.String()
}