This commit is contained in:
WJQSERVER 2024-10-03 10:39:53 +08:00
parent 51d84f0fc3
commit e4713d0f50
6 changed files with 120 additions and 17 deletions

View file

@ -1,5 +1,10 @@
# 更新日志 # 更新日志
24w08a
---
- CHANGE: 同步更新logger模块与golang-temp项目定义的开发规范保持一致
- ADD: 新增日志翻转功能
v1.1.1 v1.1.1
--- ---
- CHANGE: 修改部分代码与golang-temp项目定义的开发规范保持一致 - CHANGE: 修改部分代码与golang-temp项目定义的开发规范保持一致

View file

@ -1 +1 @@
24w07b 24w08a

View file

@ -11,6 +11,7 @@ type Config struct {
Host string `yaml:"host"` Host string `yaml:"host"`
SizeLimit int `yaml:"sizelimit"` SizeLimit int `yaml:"sizelimit"`
LogFilePath string `yaml:"logfilepath"` LogFilePath string `yaml:"logfilepath"`
MaxLogSize int `yaml:"maxlogsize"`
CORSOrigin bool `yaml:"CorsAllowOrigins"` CORSOrigin bool `yaml:"CorsAllowOrigins"`
Auth bool `yaml:"auth"` Auth bool `yaml:"auth"`
AuthToken string `yaml:"authtoken"` AuthToken string `yaml:"authtoken"`

View file

@ -2,6 +2,7 @@ port: 8080
host: "127.0.0.1" host: "127.0.0.1"
sizelimit: 131072000 # 125MB sizelimit: 131072000 # 125MB
logfilepath: "/data/ghproxy/log/ghproxy.log" logfilepath: "/data/ghproxy/log/ghproxy.log"
maxlogsize: 25 #MB
CorsAllowOrigins: true CorsAllowOrigins: true
auth: false auth: false
authtoken: "test" authtoken: "test"

View file

@ -1,30 +1,40 @@
// logger/logger.go
package logger package logger
import ( import (
"archive/tar"
"compress/gzip"
"fmt" "fmt"
"io"
"log" "log"
"os" "os"
"path/filepath"
"sync"
"time" "time"
) )
var ( var (
logFile *os.File logw = Logw
logger *log.Logger logFile *os.File
logChannel = make(chan string, 100) // 创建一个缓冲通道 logger *log.Logger
quitChannel = make(chan struct{}) // 用于通知退出 logChannel = make(chan string, 100)
quitChannel = make(chan struct{})
logFileMutex sync.Mutex // 保护 logFile 的互斥锁
) )
// Init 初始化日志记录器,接受日志文件路径作为参数 // Init 初始化日志记录器,接受日志文件路径作为参数
func Init(logFilePath string) error { func Init(logFilePath string, maxLogsize int) error {
logFileMutex.Lock()
defer logFileMutex.Unlock()
var err error var err error
logFile, err = os.OpenFile(logFilePath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) logFile, err = os.OpenFile(logFilePath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
if err != nil { if err != nil {
return err return err
} }
logger = log.New(logFile, "", 0) // 不使用默认前缀 logger = log.New(logFile, "", 0)
go logWorker() // 启动 goroutine 处理日志 go logWorker()
go monitorLogSize(logFilePath, maxLogsize)
return nil return nil
} }
@ -34,30 +44,116 @@ func logWorker() {
select { select {
case msg := <-logChannel: case msg := <-logChannel:
timestamp := time.Now().Format("02/Jan/2006:15:04:05 -0700") timestamp := time.Now().Format("02/Jan/2006:15:04:05 -0700")
logger.Println(timestamp + " - " + msg) // 写入日志 logger.Println(timestamp + " - " + msg)
case <-quitChannel: case <-quitChannel:
return // 退出 goroutine return
} }
} }
} }
// Log 直接记录日志的函数 // Log 直接记录日志的函数
func Log(customMessage string) { func Log(customMessage string) {
logChannel <- customMessage // 将日志消息发送到通道 logChannel <- customMessage
} }
// Logw 用于格式化日志记录 // Logw 用于格式化日志记录
func Logw(format string, args ...interface{}) { func Logw(format string, args ...interface{}) {
message := fmt.Sprintf(format, args...) // 格式化消息 message := fmt.Sprintf(format, args...)
Log(message) // 记录日志 Log(message)
} }
// Close 关闭日志文件 // Close 关闭日志文件
func Close() { func Close() {
logFileMutex.Lock()
defer logFileMutex.Unlock()
if logFile != nil { if logFile != nil {
quitChannel <- struct{}{} // 通知日志 goroutine 退出 quitChannel <- struct{}{}
if err := logFile.Close(); err != nil { if err := logFile.Close(); err != nil {
Log("Error closing log file: " + err.Error()) // 记录关闭日志时的错误 fmt.Printf("Error closing log file: %v", err)
} }
} }
} }
func monitorLogSize(logFilePath string, maxLogsize int) {
var maxLogsizeBytes int64 = int64(maxLogsize) * 1024 * 1024 // 最大日志文件大小单位为MB
for {
time.Sleep(600 * time.Second) // 每10分钟检查一次
logFileMutex.Lock()
info, err := logFile.Stat()
logFileMutex.Unlock()
if err == nil && info.Size() > maxLogsizeBytes {
if err := rotateLogFile(logFilePath); err != nil {
logw("Log Rotation Failed: %s", err)
}
}
}
}
func rotateLogFile(logFilePath string) error {
logFileMutex.Lock()
defer logFileMutex.Unlock()
if logFile != nil {
if err := logFile.Close(); err != nil {
logw("Error closing log file for rotation: %v", err)
}
}
// 打开当前日志文件
logFile, err := os.Open(logFilePath)
if err != nil {
return fmt.Errorf("failed to open log file: %s, error: %w", logFilePath, err)
}
defer logFile.Close()
newLogFilePath := logFilePath + "-" + time.Now().Format("20060102-150405") + ".tar.gz"
outFile, err := os.Create(newLogFilePath)
if err != nil {
return fmt.Errorf("failed to create gz file: %s, error: %w", newLogFilePath, err)
}
defer outFile.Close()
gzWriter, err := gzip.NewWriterLevel(outFile, gzip.BestCompression)
if err != nil {
return fmt.Errorf("failed to create gz writer: %w", err)
}
defer gzWriter.Close()
tarWriter := tar.NewWriter(gzWriter)
defer tarWriter.Close()
logFileStat, err := logFile.Stat()
if err != nil {
return fmt.Errorf("failed to stat log file: %s, error: %w", logFilePath, err)
}
logFileHeader := &tar.Header{
Name: filepath.Base(logFilePath),
Size: logFileStat.Size(),
Mode: 0644,
ModTime: logFileStat.ModTime(),
}
if err := tarWriter.WriteHeader(logFileHeader); err != nil {
return fmt.Errorf("failed to write log file header: %s, error: %w", logFilePath, err)
}
if _, err := io.Copy(tarWriter, logFile); err != nil {
return fmt.Errorf("failed to copy log file: %s, error: %w", logFilePath, err)
}
if err := os.Truncate(logFilePath, 0); err != nil {
return fmt.Errorf("failed to truncate log file: %s, error: %w", logFilePath, err)
}
// 重新打开日志文件
logFile, err = os.OpenFile(logFilePath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
return fmt.Errorf("failed to reopen log file: %s, error: %w", logFilePath, err)
}
logger.SetOutput(logFile)
return nil
}

View file

@ -42,7 +42,7 @@ func loadConfig() {
func setupLogger() { func setupLogger() {
// 初始化日志模块 // 初始化日志模块
var err error var err error
err = logger.Init(cfg.LogFilePath) // 传递日志文件路径 err = logger.Init(cfg.LogFilePath, cfg.MaxLogSize) // 传递日志文件路径
if err != nil { if err != nil {
log.Fatalf("Failed to initialize logger: %v", err) log.Fatalf("Failed to initialize logger: %v", err)
} }