打包、拆分
This commit is contained in:
166
utils/logger.go
166
utils/logger.go
@@ -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
17
utils/network.go
Normal 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()
|
||||
}
|
||||
Reference in New Issue
Block a user