193 lines
4.4 KiB
Go
193 lines
4.4 KiB
Go
package loggerx
|
|
|
|
// author:黄新云
|
|
// lastTime:2023年6月30日21:28:04
|
|
// desc: 日志封装类
|
|
|
|
// 优化方向
|
|
// 可以写盘的时候添加缓存,但是有个难点就是如果采用缓存的方式必须保证这个是最后关闭的,如果不是则退出的时候会丢失日志(写在缓存里还没刷盘)
|
|
|
|
// TODO:自动清除过期日志
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
"sync"
|
|
|
|
// "sync_log/global"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// 需要实现io.Writer接口
|
|
type Logger struct {
|
|
file *os.File
|
|
fileName string
|
|
mu sync.Mutex
|
|
// channel string
|
|
}
|
|
|
|
func InitLogger(prefix string) *Logger {
|
|
l := &Logger{}
|
|
|
|
// 打开文件
|
|
err := l.createNewFile(true)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
log.SetOutput(l)
|
|
log.SetFlags(log.LstdFlags | log.Llongfile | log.Lmicroseconds) // log.Lshortfile | log.LUTC
|
|
|
|
// 保存Gin日志写入到文件+控制台
|
|
gin.DefaultWriter = io.MultiWriter(l, os.Stdout)
|
|
gin.DefaultErrorWriter = io.MultiWriter(l, os.Stdout)
|
|
|
|
// 赋值前缀
|
|
if prefix != "" {
|
|
log.SetPrefix(fmt.Sprintf("[%s]", prefix))
|
|
}
|
|
return l
|
|
}
|
|
|
|
// func (l *Logger) Channel(ch string) (r *Logger) {
|
|
// rr := l
|
|
// rr.channel = ch
|
|
// return rr
|
|
// }
|
|
|
|
// 超时删除
|
|
|
|
func (l *Logger) Write(b []byte) (n int, err error) {
|
|
|
|
if l.file == nil {
|
|
// 新建一个file连接
|
|
l.createNewFile(false)
|
|
}
|
|
if l.fileName != nowFileName() {
|
|
l.createNewFile(false)
|
|
}
|
|
|
|
n, err = l.file.Write(b)
|
|
if err == nil && n < len(b) {
|
|
err = io.ErrShortWrite
|
|
}
|
|
if err != nil {
|
|
// 强制更新
|
|
l.createNewFile(true)
|
|
}
|
|
|
|
return n, err
|
|
}
|
|
|
|
// 获取最新的文件名
|
|
func nowFileName() string {
|
|
// ioc, _ := time.LoadLocation("Asia/Shanghai")
|
|
// timeDir := fmt.Sprint(time.Now().In(ioc).Format("2006/01/02/15")) // 2006-01-02 15:04:05
|
|
timeDir := fmt.Sprint(time.Now().Local().Format("2006/01/02")) // 2006-01-02 15:04:05
|
|
path := "./log/" + timeDir + ".log"
|
|
// fmt.Println(filepath.Abs(path))
|
|
return path
|
|
}
|
|
|
|
// 新建文件
|
|
func (l *Logger) createNewFile(isMust bool) error {
|
|
l.mu.Lock()
|
|
defer l.mu.Unlock()
|
|
|
|
fileName := nowFileName()
|
|
|
|
if !isMust {
|
|
if l.file != nil && l.fileName == fileName {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
dir, _ := filepath.Split(fileName) // 识别目录与文件
|
|
os.MkdirAll(dir, os.ModePerm) // 创建多层目录,如果存在不会报错
|
|
|
|
// 打开该文件,如果不存在则创建
|
|
file, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
|
|
if err != nil {
|
|
// 打开失败,尝试创建
|
|
fmt.Println("打开日志文件失败")
|
|
return err
|
|
}
|
|
// 关闭原来的文件
|
|
if l.file != nil {
|
|
l.closeFile()
|
|
}
|
|
l.file = file
|
|
l.fileName = fileName
|
|
return nil
|
|
}
|
|
|
|
// 关闭文件
|
|
func (l *Logger) closeFile() error {
|
|
l.file.Sync()
|
|
return l.file.Close()
|
|
}
|
|
|
|
func (l *Logger) Info(ctx context.Context, v ...any) {
|
|
l.logger(ctx, "info", v...)
|
|
}
|
|
|
|
func (l *Logger) Infof(ctx context.Context, format string, v ...any) {
|
|
s := fmt.Sprintf(format, v...)
|
|
l.logger(ctx, "info", s)
|
|
}
|
|
|
|
func (l *Logger) Error(ctx context.Context, v ...any) {
|
|
l.logger(ctx, "error", v...)
|
|
}
|
|
|
|
func (l *Logger) Errorf(ctx context.Context, format string, v ...any) {
|
|
s := fmt.Sprintf(format, v...)
|
|
l.logger(ctx, "error", s)
|
|
}
|
|
|
|
// 添加固定的内容
|
|
// func (l *Logger) ContextWithFields(ctx context.Context, v ...any) {
|
|
// l.logger(ctx, "add", v...)
|
|
// }
|
|
// func (l *Logger) Field(key,val string) {
|
|
// l.logger(nil, "add", key,val)
|
|
// }
|
|
|
|
func (l *Logger) logger(ctx context.Context, action string, v ...any) {
|
|
pc, file, line, _ := runtime.Caller(2)
|
|
// fmt.Println("runtime.Caller", pc, file, line, ok)
|
|
|
|
funcName := runtime.FuncForPC(pc).Name()
|
|
funcName = filepath.Ext(funcName)
|
|
funcName = strings.TrimPrefix(funcName, ".")
|
|
|
|
by, _ := json.Marshal(v)
|
|
|
|
nowTime := time.Now().Local().Format("20060102 15:04:05.000000")
|
|
|
|
traceId, _ := ctx.Value("trace_id").(string)
|
|
|
|
writeStr := "[" + action + "]" + nowTime + " " + file + ":" + fmt.Sprintf("%d", line) + " " + funcName + " gid:" + getGID() + " " + traceId + " @data@: " + string(by) + "\n\n"
|
|
|
|
l.Write([]byte(writeStr))
|
|
|
|
// log.Println("" + string(by))
|
|
}
|
|
|
|
func getGID() string {
|
|
b := make([]byte, 64)
|
|
b = b[:runtime.Stack(b, false)]
|
|
b = bytes.TrimPrefix(b, []byte("goroutine "))
|
|
b = b[:bytes.IndexByte(b, ' ')]
|
|
return string(b)
|
|
}
|