优化日志

This commit is contained in:
huangxiaolei
2022-12-04 16:23:15 +08:00
parent b613262d28
commit 65a2e3e6e8

View File

@@ -8,6 +8,7 @@ import (
"path" "path"
"runtime" "runtime"
"strconv" "strconv"
"strings"
"time" "time"
) )
@@ -25,144 +26,141 @@ const (
NEITHER int = 4 NEITHER int = 4
) )
var LOG *Logger = nil
type Logger struct {
level int
method int
trackLine bool
file *os.File
logInfoChan chan *LogInfo
}
type LogInfo struct {
logLevel int
msg string
param []any
fileInfo string
funcInfo string
lineInfo int
goroutineId string
}
// 日志配置
type Config struct { type Config struct {
Level string `toml:"level"` Level string `toml:"level"`
Method string `toml:"method"` Method string `toml:"method"`
TrackLine bool `toml:"track_line"` TrackLine bool `toml:"track_line"`
} }
var LOG *Logger = nil
type Logger struct {
Level int
Method int
TrackLine bool
File *os.File
LogInfoChan chan *LogInfo
}
type LogInfo struct {
Level int
Msg string
Param []any
FileName string
FuncName string
Line int
GoroutineId string
Stack string
}
func InitLogger(name string, cfg Config) { func InitLogger(name string, cfg Config) {
log.SetFlags(0) log.SetFlags(0)
LOG = new(Logger) LOG = new(Logger)
LOG.level = getLevelInt(cfg.Level) LOG.Level = getLevelInt(cfg.Level)
LOG.method = getMethodInt(cfg.Method) LOG.Method = getMethodInt(cfg.Method)
LOG.trackLine = cfg.TrackLine LOG.TrackLine = cfg.TrackLine
LOG.logInfoChan = make(chan *LogInfo, 1000) LOG.LogInfoChan = make(chan *LogInfo, 1000)
if LOG.method == FILE || LOG.method == BOTH { if LOG.Method == FILE || LOG.Method == BOTH {
file, err := os.OpenFile("./"+name+".log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) file, err := os.OpenFile("./"+name+".log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil { if err != nil {
info := fmt.Sprintf("open log file error: %v\n", err) info := fmt.Sprintf("open log file error: %v\n", err)
panic(info) panic(info)
} }
LOG.file = file LOG.File = file
} }
go LOG.doLog() go LOG.doLog()
} }
var GREEN = string([]byte{27, 91, 51, 50, 109})
var WHITE = string([]byte{27, 91, 51, 55, 109})
var YELLOW = string([]byte{27, 91, 51, 51, 109})
var RED = string([]byte{27, 91, 51, 49, 109})
var BLUE = string([]byte{27, 91, 51, 52, 109})
var MAGENTA = string([]byte{27, 91, 51, 53, 109})
var CYAN = string([]byte{27, 91, 51, 54, 109})
var RESET = string([]byte{27, 91, 48, 109})
func (l *Logger) doLog() { func (l *Logger) doLog() {
for { for {
logInfo := <-l.logInfoChan logInfo := <-l.LogInfoChan
timeNow := time.Now() timeNow := time.Now()
timeNowStr := timeNow.Format("2006-01-02 15:04:05.000") timeNowStr := timeNow.Format("2006-01-02 15:04:05.000")
logHeader := "[" + timeNowStr + "]" + " " + logHeader := CYAN + "[" + timeNowStr + "]" + RESET + " "
"[" + l.getLevelStr(logInfo.logLevel) + "]" + " " if logInfo.Level == DEBUG {
if l.trackLine { logHeader += BLUE + "[" + l.getLevelStr(logInfo.Level) + "]" + RESET + " "
logHeader += "[" + } else if logInfo.Level == INFO {
"line:" + logInfo.fileInfo + ":" + strconv.FormatInt(int64(logInfo.lineInfo), 10) + logHeader += GREEN + "[" + l.getLevelStr(logInfo.Level) + "]" + RESET + " "
" func:" + logInfo.funcInfo + } else if logInfo.Level == ERROR {
" goroutine:" + logInfo.goroutineId + logHeader += RED + "[" + l.getLevelStr(logInfo.Level) + "]" + RESET + " "
"]" + " "
} }
logStr := logHeader + fmt.Sprintf(logInfo.msg, logInfo.param...) + "\n" if l.TrackLine {
red := string([]byte{27, 91, 51, 49, 109}) logHeader += MAGENTA + "[" +
green := string([]byte{27, 91, 51, 50, 109}) logInfo.FileName + ":" + strconv.Itoa(logInfo.Line) + " " +
reset := string([]byte{27, 91, 48, 109}) logInfo.FuncName + "()" + " " +
if l.method == CONSOLE { "goroutine:" + logInfo.GoroutineId +
if logInfo.logLevel == ERROR { "]" + RESET + " "
log.Print(red, logStr, reset) }
} else if logInfo.logLevel == INFO { logStr := logHeader + fmt.Sprintf(logInfo.Msg, logInfo.Param...) + "\n"
log.Print(green, logStr, reset) if logInfo.Level == ERROR {
} else { logStr += logInfo.Stack
log.Print(logStr) }
} if l.Method == CONSOLE {
} else if l.method == FILE { log.Print(logStr)
_, _ = l.file.WriteString(logStr) } else if l.Method == FILE {
} else if l.method == BOTH { _, _ = l.File.WriteString(logStr)
if logInfo.logLevel == ERROR { } else if l.Method == BOTH {
log.Print(red, logStr, reset) log.Print(logStr)
} else if logInfo.logLevel == INFO { _, _ = l.File.WriteString(logStr)
log.Print(green, logStr, reset)
} else {
log.Print(logStr)
}
_, _ = l.file.WriteString(logStr)
} }
} }
} }
func (l *Logger) Debug(msg string, param ...any) { func (l *Logger) Debug(msg string, param ...any) {
if l.level > DEBUG { if l.Level > DEBUG {
return return
} }
logInfo := new(LogInfo) logInfo := new(LogInfo)
logInfo.logLevel = DEBUG logInfo.Level = DEBUG
logInfo.msg = msg logInfo.Msg = msg
logInfo.param = param logInfo.Param = param
if l.trackLine { if l.TrackLine {
fileInfo, funcInfo, lineInfo := l.getLineInfo() logInfo.FileName, logInfo.Line, logInfo.FuncName = l.getLineFunc()
logInfo.fileInfo = fileInfo logInfo.GoroutineId = l.getGoroutineId()
logInfo.funcInfo = funcInfo logInfo.Stack = l.Stack()
logInfo.lineInfo = lineInfo
logInfo.goroutineId = l.getGoroutineId()
} }
l.logInfoChan <- logInfo l.LogInfoChan <- logInfo
} }
func (l *Logger) Info(msg string, param ...any) { func (l *Logger) Info(msg string, param ...any) {
if l.level > INFO { if l.Level > INFO {
return return
} }
logInfo := new(LogInfo) logInfo := new(LogInfo)
logInfo.logLevel = INFO logInfo.Level = INFO
logInfo.msg = msg logInfo.Msg = msg
logInfo.param = param logInfo.Param = param
if l.trackLine { if l.TrackLine {
fileInfo, funcInfo, lineInfo := l.getLineInfo() logInfo.FileName, logInfo.Line, logInfo.FuncName = l.getLineFunc()
logInfo.fileInfo = fileInfo logInfo.GoroutineId = l.getGoroutineId()
logInfo.funcInfo = funcInfo logInfo.Stack = l.Stack()
logInfo.lineInfo = lineInfo
logInfo.goroutineId = l.getGoroutineId()
} }
l.logInfoChan <- logInfo l.LogInfoChan <- logInfo
} }
func (l *Logger) Error(msg string, param ...any) { func (l *Logger) Error(msg string, param ...any) {
if l.level > ERROR { if l.Level > ERROR {
return return
} }
logInfo := new(LogInfo) logInfo := new(LogInfo)
logInfo.logLevel = ERROR logInfo.Level = ERROR
logInfo.msg = msg logInfo.Msg = msg
logInfo.param = param logInfo.Param = param
if l.trackLine { if l.TrackLine {
fileInfo, funcInfo, lineInfo := l.getLineInfo() logInfo.FileName, logInfo.Line, logInfo.FuncName = l.getLineFunc()
logInfo.fileInfo = fileInfo logInfo.GoroutineId = l.getGoroutineId()
logInfo.funcInfo = funcInfo logInfo.Stack = l.Stack()
logInfo.lineInfo = lineInfo
logInfo.goroutineId = l.getGoroutineId()
} }
l.logInfoChan <- logInfo l.LogInfoChan <- logInfo
} }
func getLevelInt(level string) (ret int) { func getLevelInt(level string) (ret int) {
@@ -206,20 +204,49 @@ func getMethodInt(method string) (ret int) {
} }
func (l *Logger) getGoroutineId() (goroutineId string) { func (l *Logger) getGoroutineId() (goroutineId string) {
staticInfo := make([]byte, 32) buf := make([]byte, 32)
runtime.Stack(staticInfo, false) runtime.Stack(buf, false)
staticInfo = bytes.TrimPrefix(staticInfo, []byte("goroutine ")) buf = bytes.TrimPrefix(buf, []byte("goroutine "))
staticInfo = staticInfo[:bytes.IndexByte(staticInfo, ' ')] buf = buf[:bytes.IndexByte(buf, ' ')]
goroutineId = string(staticInfo) goroutineId = string(buf)
return goroutineId return goroutineId
} }
func (l *Logger) getLineInfo() (fileName string, funcName string, lineNo int) { func (l *Logger) getLineFunc() (fileName string, line int, funcName string) {
pc, file, line, ok := runtime.Caller(2) var pc uintptr
if ok { var file string
fileName = path.Base(file) var ok bool
funcName = path.Base(runtime.FuncForPC(pc).Name()) pc, file, line, ok = runtime.Caller(2)
lineNo = line if !ok {
return "???", -1, "???"
}
fileName = path.Base(file)
funcName = runtime.FuncForPC(pc).Name()
split := strings.Split(funcName, ".")
if len(split) != 0 {
funcName = split[len(split)-1]
}
return fileName, line, funcName
}
func (l *Logger) Stack() string {
buf := make([]byte, 1024)
for {
n := runtime.Stack(buf, false)
if n < len(buf) {
return string(buf[:n])
}
buf = make([]byte, 2*len(buf))
}
}
func (l *Logger) StackAll() string {
buf := make([]byte, 1024*16)
for {
n := runtime.Stack(buf, true)
if n < len(buf) {
return string(buf[:n])
}
buf = make([]byte, 2*len(buf))
} }
return
} }