224 lines
4.5 KiB
Go
224 lines
4.5 KiB
Go
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...)
|
||
}
|
||
}
|