goProject/trunk/goutil/logUtil/impl-localfile/logger.go

224 lines
4.5 KiB
Go
Raw Normal View History

2025-01-06 16:01:02 +08:00
package impl_localfile
import (
"fmt"
"path/filepath"
"strconv"
"strings"
"sync"
"time"
"goutil/fileUtil"
"goutil/timeUtil"
)
const (
con_SEPERATOR = "\n------------------------------------------------------\n"
)
// Logger
// @description: 日志对象
type Logger struct {
logPath string
loggerMap map[levelType]*fileLog
bufPool *sync.Pool
// 压缩属性
// 上一次日志压缩的日期 时间戳
preCompressDate int64
// 压缩锁对象
compressLock sync.Mutex
}
// NewLogger
// @description: 构造日志对象
// parameter:
//
// @*Logger:
func NewLogger() *Logger {
log := &Logger{
logPath: "Log",
loggerMap: make(map[levelType]*fileLog, 4),
bufPool: &sync.Pool{
New: func() interface{} {
return &strings.Builder{}
},
},
}
// 初始化基础日志
for lv := range levels {
log.loggerMap[levelType(lv)] = newLog(log.logPath, levelType(lv))
}
return log
}
// log
// @description: 记录日志
// parameter:
//
// @receiver l:
// @logInfo:
// @lv:
// @ifIncludeHour:
//
// return:
func (l *Logger) log(logInfo string, lv levelType, ifIncludeHour bool) {
buf := l.bufPool.Get().(*strings.Builder)
defer l.bufPool.Put(buf)
buf.Reset()
// 组装所有需要写入的内容
// 获取当前时间
buf.WriteString(time.Now().Format("2006-01-02 15:04:05"))
buf.WriteString("---->\n")
buf.WriteString(logInfo)
// 加上最后的分隔符
buf.WriteString(con_SEPERATOR)
// 写入之前检查
l.checkCompress()
// 构造对象并添加到队列中
l.loggerMap[lv].msgChan <- newLogObject(buf.String(), lv, ifIncludeHour)
}
// SetLogPath
// @description: 设置文件路径
// parameter:
//
// @receiver l:
// @_logPath:
//
// return:
func (l *Logger) SetLogPath(_logPath string) {
l.logPath = _logPath
for _, lf := range l.loggerMap {
lf.SetLogPath(_logPath)
}
}
// checkCompress
// @description: 压缩
// parameter:
//
// @receiver l:
//
// return:
func (l *Logger) checkCompress() {
// 不用压缩,直接返回
if !l.preCompress() {
return
}
// 日志压缩
go l.doCompress()
}
// closeLogFile
// @description: 关闭日志文件
// parameter:
//
// @receiver l:
//
// return:
func (l *Logger) closeLogFile() {
// 需要压缩文件,关闭已经打开的文件
for _, lf := range l.loggerMap {
_ = lf.f.Close()
}
}
// preCompress 确定是否要压缩
func (l *Logger) preCompress() bool {
// 检查是否需要进行数据压缩
nowDate := timeUtil.GetDate(time.Now()).Unix()
if nowDate == l.preCompressDate {
return false
}
l.compressLock.Lock()
defer l.compressLock.Unlock()
// 上一次压缩的时间
if nowDate == l.preCompressDate {
return false
}
l.closeLogFile()
l.preCompressDate = nowDate
return true
}
// 日志压缩
func (l *Logger) doCompress() {
defer func() {
if r := recover(); r != nil {
// 将错误输出,而不是记录到文件,是因为可能导致死循环
fmt.Println(r)
}
}()
// 获取昨天的日期,并获取昨天对应的文件夹
yesterday := time.Now().AddDate(0, 0, -1)
dateString := timeUtil.Format(yesterday, "yyyy-MM-dd")
fileAbsoluteDirectory := filepath.Join(l.logPath, strconv.Itoa(yesterday.Year()), strconv.Itoa(int(yesterday.Month())))
// 判断是否已经存在压缩文件
compressFileName := fmt.Sprintf("%s.tar.gz", dateString)
compressAbsolutePath := filepath.Join(fileAbsoluteDirectory, compressFileName)
if exists, err := fileUtil.IsFileExists(compressAbsolutePath); err == nil && exists {
return
}
// 获取昨天的文件列表
fileList, err := fileUtil.GetFileList2(fileAbsoluteDirectory, dateString, con_FILE_SUFFIX)
if err != nil {
fmt.Printf("logUtil.compress.fileUtil.GetFileList2 err:%s\n", err)
return
}
if len(fileList) == 0 {
return
}
// 进行tar操作得到yyyy-MM-dd.tar
tarFileName := fmt.Sprintf("%s.tar", dateString)
tarAbsolutePath := filepath.Join(fileAbsoluteDirectory, tarFileName)
if err := fileUtil.Tar(fileList, tarAbsolutePath); err != nil {
fmt.Printf("logUtil.compress.fileUtil.Tar err:%s\n", err)
}
// 进行gzip操作得到yyyy-MM-dd.tar.gz
if err := fileUtil.Gzip(tarAbsolutePath, ""); err != nil {
fmt.Printf("logUtil.compress.fileUtil.Gzip err:%s\n", err)
}
// 删除原始文件
for _, item := range fileList {
_ = fileUtil.DeleteFile(item)
}
// 删除tar文件
_ = fileUtil.DeleteFile(tarAbsolutePath)
}
// getLog
// @description: 组装日志
// parameter:
//
// @format:
// @args:
//
// return:
//
// @string:
func getLog(format string, args ...interface{}) string {
if len(args) == 0 {
return format
} else {
return fmt.Sprintf(format, args...)
}
}