2023-11-28 18:29:30 +08:00
|
|
|
|
package gologger
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"os"
|
|
|
|
|
"path/filepath"
|
2025-06-06 11:07:04 +08:00
|
|
|
|
"regexp"
|
|
|
|
|
"strconv"
|
|
|
|
|
"time"
|
2023-11-28 18:29:30 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type FileAppender struct {
|
2025-06-06 11:07:04 +08:00
|
|
|
|
formatter LogFormatter
|
|
|
|
|
filePath string
|
|
|
|
|
lchan chan LogEvent
|
|
|
|
|
file *os.File
|
|
|
|
|
stopChan chan struct{}
|
|
|
|
|
// 新增滚动相关字段
|
|
|
|
|
EnableRolling bool
|
|
|
|
|
MaxSize int64 // 文件最大大小(字节)
|
|
|
|
|
MaxAge int64 // 文件最大时间(秒)
|
|
|
|
|
currentFileSize int64 // 当前文件大小
|
|
|
|
|
createdAt int64 // 文件创建时间戳
|
2024-09-21 14:25:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Close implements LoggerAppender.
|
|
|
|
|
func (f *FileAppender) Close() {
|
|
|
|
|
//send stop signal
|
|
|
|
|
f.stopChan <- struct{}{}
|
2023-11-28 18:29:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (f *FileAppender) GetName() string {
|
|
|
|
|
return "FileAppender:" + f.filePath
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-13 23:05:42 +08:00
|
|
|
|
func (f *FileAppender) start() {
|
|
|
|
|
f.lchan = make(chan LogEvent, 10)
|
2024-09-21 14:25:45 +08:00
|
|
|
|
f.stopChan = make(chan struct{})
|
2023-11-28 18:29:30 +08:00
|
|
|
|
if f.file == nil || int(f.file.Fd()) == -1 {
|
|
|
|
|
dirName := filepath.Dir(f.filePath)
|
|
|
|
|
_, err := os.Stat(dirName)
|
|
|
|
|
if err != nil && os.IsNotExist(err) {
|
|
|
|
|
os.MkdirAll(dirName, 0755)
|
|
|
|
|
}
|
|
|
|
|
f.file, _ = os.OpenFile(f.filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
2025-06-06 11:07:04 +08:00
|
|
|
|
|
|
|
|
|
// 获取当前文件大小
|
|
|
|
|
if stat, err := f.file.Stat(); err == nil {
|
|
|
|
|
f.currentFileSize = stat.Size()
|
|
|
|
|
}
|
|
|
|
|
// 记录文件创建时间
|
|
|
|
|
f.createdAt = time.Now().Unix()
|
2023-11-28 18:29:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-12-13 23:05:42 +08:00
|
|
|
|
go func() {
|
2023-12-13 23:07:32 +08:00
|
|
|
|
defer f.file.Close()
|
2023-12-13 23:05:42 +08:00
|
|
|
|
for {
|
2024-09-21 14:25:45 +08:00
|
|
|
|
select {
|
|
|
|
|
case <-f.stopChan:
|
|
|
|
|
return
|
|
|
|
|
case logEvent := <-f.lchan:
|
2025-06-06 11:07:04 +08:00
|
|
|
|
// 检查日志滚动
|
|
|
|
|
if f.EnableRolling {
|
|
|
|
|
f.checkAndRoll(logEvent)
|
|
|
|
|
}
|
|
|
|
|
logMsg := f.formatter(logEvent)
|
2024-09-21 14:25:45 +08:00
|
|
|
|
f.file.WriteString(logMsg)
|
|
|
|
|
}
|
2023-12-13 23:05:42 +08:00
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
}
|
2025-06-06 11:07:04 +08:00
|
|
|
|
|
|
|
|
|
// 新增日志滚动方法
|
|
|
|
|
func (f *FileAppender) checkAndRoll(logEvent LogEvent) {
|
|
|
|
|
// 按大小滚动
|
|
|
|
|
if f.MaxSize > 0 && f.currentFileSize >= f.MaxSize {
|
|
|
|
|
f.rollFile(logEvent)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 按时间滚动
|
|
|
|
|
if f.MaxAge > 0 && time.Now().Unix()-f.createdAt >= f.MaxAge {
|
|
|
|
|
f.rollFile(logEvent)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 日志文件滚动
|
|
|
|
|
func (f *FileAppender) rollFile(logEvent LogEvent) {
|
|
|
|
|
// 关闭当前文件
|
|
|
|
|
f.file.Close()
|
|
|
|
|
|
|
|
|
|
// 重命名旧文件
|
|
|
|
|
timestamp := time.Now().Format("20060102150405")
|
|
|
|
|
newPath := f.filePath + "." + timestamp
|
|
|
|
|
os.Rename(f.filePath, newPath)
|
|
|
|
|
|
|
|
|
|
// 创建新文件
|
|
|
|
|
f.file, _ = os.OpenFile(f.filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
|
|
|
|
|
|
|
|
|
// 重置状态
|
|
|
|
|
f.currentFileSize = 0
|
|
|
|
|
f.createdAt = time.Now().Unix()
|
|
|
|
|
|
|
|
|
|
// 重新写入当前日志
|
|
|
|
|
logMsg := format(logEvent)
|
|
|
|
|
f.file.WriteString(logMsg)
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-13 23:05:42 +08:00
|
|
|
|
func (f *FileAppender) Append(logEvent LogEvent) {
|
2023-11-28 18:29:30 +08:00
|
|
|
|
|
2023-12-13 23:05:42 +08:00
|
|
|
|
f.lchan <- logEvent
|
2023-11-28 18:29:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-12-13 23:05:42 +08:00
|
|
|
|
func makeFileAppender(appenderConfig LogAppenderConfig) *LoggerAppender {
|
2023-11-28 18:29:30 +08:00
|
|
|
|
var logfile interface{}
|
|
|
|
|
var ok bool
|
|
|
|
|
logfile, ok = appenderConfig.Options["file"]
|
|
|
|
|
if !ok {
|
|
|
|
|
logfile = "default.log"
|
|
|
|
|
}
|
2025-06-06 11:07:04 +08:00
|
|
|
|
|
|
|
|
|
// 新增滚动配置参数
|
|
|
|
|
rollingEnabled := false
|
|
|
|
|
if enable, ok := appenderConfig.Options["enableRolling"].(bool); ok {
|
|
|
|
|
rollingEnabled = enable
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
maxSize := int64(0)
|
|
|
|
|
if size, ok := appenderConfig.Options["maxSize"].(int64); ok {
|
|
|
|
|
maxSize = size * 1024 * 1024 // 将兆转换为字节
|
|
|
|
|
} else if sizeStr, ok := appenderConfig.Options["maxSize"].(string); ok {
|
|
|
|
|
// 解析带单位的大小配置(支持KB, MB, GB)
|
|
|
|
|
var re = regexp.MustCompile(`(?i)^(\d+)([kmg]b)?$`)
|
|
|
|
|
matches := re.FindStringSubmatch(sizeStr)
|
|
|
|
|
if len(matches) > 0 {
|
|
|
|
|
num, _ := strconv.ParseInt(matches[1], 10, 64)
|
|
|
|
|
unit := ""
|
|
|
|
|
if len(matches) > 2 {
|
|
|
|
|
unit = matches[2]
|
|
|
|
|
}
|
|
|
|
|
switch unit {
|
|
|
|
|
case "KB", "kb":
|
|
|
|
|
maxSize = num * 1024
|
|
|
|
|
case "MB", "mb":
|
|
|
|
|
maxSize = num * 1024 * 1024
|
|
|
|
|
case "GB", "gb":
|
|
|
|
|
maxSize = num * 1024 * 1024 * 1024
|
|
|
|
|
default:
|
|
|
|
|
maxSize = num * 1024 * 1024 // 默认按MB处理
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
maxAge := int64(0)
|
|
|
|
|
if ageStr, ok := appenderConfig.Options["maxAge"].(string); ok {
|
|
|
|
|
// 解析带单位的时间配置
|
|
|
|
|
re := regexp.MustCompile(`^\d+[hd]?$`)
|
|
|
|
|
if re.MatchString(ageStr) {
|
|
|
|
|
// 提取数字部分和单位
|
|
|
|
|
numStr := ""
|
|
|
|
|
unit := ""
|
|
|
|
|
for _, c := range ageStr {
|
|
|
|
|
if c >= '0' && c <= '9' {
|
|
|
|
|
numStr += string(c)
|
|
|
|
|
} else {
|
|
|
|
|
unit = string(c)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
num, _ := strconv.ParseInt(numStr, 10, 64)
|
|
|
|
|
switch unit {
|
|
|
|
|
case "h":
|
|
|
|
|
maxAge = num * 3600 // 小时转秒
|
|
|
|
|
default:
|
|
|
|
|
maxAge = num * 86400 // 默认按天转秒
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if ageInt, ok := appenderConfig.Options["maxAge"].(int64); ok {
|
|
|
|
|
maxAge = ageInt
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-28 18:29:30 +08:00
|
|
|
|
var ret LoggerAppender = &FileAppender{
|
2025-06-06 11:07:04 +08:00
|
|
|
|
formatter: SelectFormatter(appenderConfig.Formatter),
|
|
|
|
|
filePath: logfile.(string),
|
|
|
|
|
EnableRolling: rollingEnabled,
|
|
|
|
|
MaxSize: maxSize,
|
|
|
|
|
MaxAge: maxAge,
|
2023-11-28 18:29:30 +08:00
|
|
|
|
}
|
2023-12-13 23:05:42 +08:00
|
|
|
|
|
|
|
|
|
ret.(*FileAppender).start()
|
|
|
|
|
|
|
|
|
|
return &ret
|
2023-11-28 18:29:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
|
RegistAppender("file", makeFileAppender)
|
|
|
|
|
}
|