mirror of
https://github.com/FlourishingWorld/hk4e.git
synced 2026-02-04 16:02:26 +08:00
优化日志
This commit is contained in:
@@ -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
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user