goProject/trunk/goutil/logUtil/impl-localfile/logger.go
皮蛋13361098506 1b77f62820 初始化项目
2025-01-06 16:01:02 +08:00

224 lines
4.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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...)
}
}