mirror of
https://github.com/FlourishingWorld/hk4e.git
synced 2026-02-04 17:22:27 +08:00
327 lines
7.0 KiB
Go
327 lines
7.0 KiB
Go
package logger
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"path"
|
|
"runtime"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"hk4e/common/config"
|
|
)
|
|
|
|
const (
|
|
DEBUG = iota
|
|
INFO
|
|
WARN
|
|
ERROR
|
|
)
|
|
|
|
const (
|
|
CONSOLE = iota
|
|
FILE
|
|
BOTH
|
|
NEITHER
|
|
)
|
|
|
|
var (
|
|
GREEN = string([]byte{27, 91, 51, 50, 109})
|
|
WHITE = string([]byte{27, 91, 51, 55, 109})
|
|
YELLOW = string([]byte{27, 91, 51, 51, 109})
|
|
RED = string([]byte{27, 91, 51, 49, 109})
|
|
BLUE = string([]byte{27, 91, 51, 52, 109})
|
|
MAGENTA = string([]byte{27, 91, 51, 53, 109})
|
|
CYAN = string([]byte{27, 91, 51, 54, 109})
|
|
RESET = string([]byte{27, 91, 48, 109})
|
|
ALL_COLOR = []string{GREEN, WHITE, YELLOW, RED, BLUE, MAGENTA, CYAN, RESET}
|
|
)
|
|
|
|
var LOG *Logger = nil
|
|
|
|
type Logger struct {
|
|
AppName string
|
|
Level int
|
|
Mode int
|
|
Track bool
|
|
MaxSize int32
|
|
File *os.File
|
|
LogInfoChan chan *LogInfo
|
|
}
|
|
|
|
type LogInfo struct {
|
|
Level int
|
|
Msg string
|
|
FileName string
|
|
FuncName string
|
|
Line int
|
|
GoroutineId string
|
|
ThreadId string
|
|
}
|
|
|
|
func InitLogger(appName string) {
|
|
log.SetFlags(0)
|
|
LOG = new(Logger)
|
|
LOG.AppName = appName
|
|
LOG.Level = LOG.getLevelInt(config.GetConfig().Logger.Level)
|
|
LOG.Mode = LOG.getModeInt(config.GetConfig().Logger.Mode)
|
|
LOG.Track = config.GetConfig().Logger.Track
|
|
LOG.MaxSize = config.GetConfig().Logger.MaxSize
|
|
LOG.LogInfoChan = make(chan *LogInfo, 1000)
|
|
LOG.File = nil
|
|
go LOG.doLog()
|
|
}
|
|
|
|
func CloseLogger() {
|
|
// 等待所有日志打印完毕
|
|
for {
|
|
if len(LOG.LogInfoChan) == 0 {
|
|
break
|
|
}
|
|
time.Sleep(time.Millisecond * 100)
|
|
}
|
|
}
|
|
|
|
func (l *Logger) doLog() {
|
|
for {
|
|
logInfo := <-l.LogInfoChan
|
|
timeNow := time.Now()
|
|
timeNowStr := timeNow.Format("2006-01-02 15:04:05.000")
|
|
logStr := CYAN + "[" + timeNowStr + "]" + RESET + " "
|
|
if logInfo.Level == DEBUG {
|
|
logStr += BLUE + "[" + l.getLevelStr(logInfo.Level) + "]" + RESET
|
|
} else if logInfo.Level == INFO {
|
|
logStr += GREEN + "[" + l.getLevelStr(logInfo.Level) + "]" + RESET
|
|
} else if logInfo.Level == WARN {
|
|
logStr += YELLOW + "[" + l.getLevelStr(logInfo.Level) + "]" + RESET
|
|
} else if logInfo.Level == ERROR {
|
|
logStr += RED + "[" + l.getLevelStr(logInfo.Level) + "]" + RESET
|
|
}
|
|
if logInfo.Level == ERROR {
|
|
logStr += " " + RED + logInfo.Msg + RESET + " "
|
|
} else {
|
|
logStr += " " + logInfo.Msg + " "
|
|
}
|
|
if l.Track {
|
|
logStr += MAGENTA + "[" +
|
|
logInfo.FileName + ":" + strconv.Itoa(logInfo.Line) + " " +
|
|
logInfo.FuncName + "()" + " " +
|
|
"goroutine:" + logInfo.GoroutineId + " " +
|
|
"thread:" + logInfo.ThreadId +
|
|
"]" + RESET
|
|
}
|
|
logStr += "\n"
|
|
if l.Mode == CONSOLE {
|
|
log.Print(logStr)
|
|
} else if l.Mode == FILE {
|
|
l.writeLogFile(logStr)
|
|
} else if l.Mode == BOTH {
|
|
log.Print(logStr)
|
|
l.writeLogFile(logStr)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (l *Logger) writeLogFile(logStr string) {
|
|
for _, v := range ALL_COLOR {
|
|
logStr = strings.ReplaceAll(logStr, v, "")
|
|
}
|
|
if l.File == nil {
|
|
file, err := os.OpenFile("./"+l.AppName+".log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
|
|
if err != nil {
|
|
fmt.Printf(RED+"open new log file error: %v\n"+RESET, err)
|
|
return
|
|
}
|
|
LOG.File = file
|
|
}
|
|
fileStat, err := l.File.Stat()
|
|
if err != nil {
|
|
fmt.Printf(RED+"get log file stat error: %v\n"+RESET, err)
|
|
return
|
|
}
|
|
if fileStat.Size() >= int64(l.MaxSize) {
|
|
err = l.File.Close()
|
|
if err != nil {
|
|
fmt.Printf(RED+"close old log file error: %v\n"+RESET, err)
|
|
return
|
|
}
|
|
timeNow := time.Now()
|
|
timeNowStr := timeNow.Format("2006-01-02-15_04_05")
|
|
err = os.Rename(l.File.Name(), l.File.Name()+"."+timeNowStr+".log")
|
|
if err != nil {
|
|
fmt.Printf(RED+"rename old log file error: %v\n"+RESET, err)
|
|
return
|
|
}
|
|
file, err := os.OpenFile("./"+l.AppName+".log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
|
|
if err != nil {
|
|
fmt.Printf(RED+"open new log file error: %v\n"+RESET, err)
|
|
return
|
|
}
|
|
LOG.File = file
|
|
}
|
|
_, err = l.File.WriteString(logStr)
|
|
if err != nil {
|
|
fmt.Printf(RED+"write log file error: %v\n"+RESET, err)
|
|
return
|
|
}
|
|
}
|
|
|
|
func Debug(msg string, param ...any) {
|
|
if LOG.Level > DEBUG {
|
|
return
|
|
}
|
|
logInfo := new(LogInfo)
|
|
logInfo.Level = DEBUG
|
|
logInfo.Msg = fmt.Sprintf(msg, param...)
|
|
if LOG.Track {
|
|
logInfo.FileName, logInfo.Line, logInfo.FuncName = LOG.getLineFunc()
|
|
logInfo.GoroutineId = LOG.getGoroutineId()
|
|
logInfo.ThreadId = LOG.getThreadId()
|
|
}
|
|
LOG.LogInfoChan <- logInfo
|
|
}
|
|
|
|
func Info(msg string, param ...any) {
|
|
if LOG.Level > INFO {
|
|
return
|
|
}
|
|
logInfo := new(LogInfo)
|
|
logInfo.Level = INFO
|
|
logInfo.Msg = fmt.Sprintf(msg, param...)
|
|
if LOG.Track {
|
|
logInfo.FileName, logInfo.Line, logInfo.FuncName = LOG.getLineFunc()
|
|
logInfo.GoroutineId = LOG.getGoroutineId()
|
|
logInfo.ThreadId = LOG.getThreadId()
|
|
}
|
|
LOG.LogInfoChan <- logInfo
|
|
}
|
|
|
|
func Warn(msg string, param ...any) {
|
|
if LOG.Level > WARN {
|
|
return
|
|
}
|
|
logInfo := new(LogInfo)
|
|
logInfo.Level = WARN
|
|
logInfo.Msg = fmt.Sprintf(msg, param...)
|
|
if LOG.Track {
|
|
logInfo.FileName, logInfo.Line, logInfo.FuncName = LOG.getLineFunc()
|
|
logInfo.GoroutineId = LOG.getGoroutineId()
|
|
logInfo.ThreadId = LOG.getThreadId()
|
|
}
|
|
LOG.LogInfoChan <- logInfo
|
|
}
|
|
|
|
func Error(msg string, param ...any) {
|
|
if LOG.Level > ERROR {
|
|
return
|
|
}
|
|
logInfo := new(LogInfo)
|
|
logInfo.Level = ERROR
|
|
logInfo.Msg = fmt.Sprintf(msg, param...)
|
|
if LOG.Track {
|
|
logInfo.FileName, logInfo.Line, logInfo.FuncName = LOG.getLineFunc()
|
|
logInfo.GoroutineId = LOG.getGoroutineId()
|
|
logInfo.ThreadId = LOG.getThreadId()
|
|
}
|
|
LOG.LogInfoChan <- logInfo
|
|
}
|
|
|
|
func (l *Logger) getLevelInt(level string) (ret int) {
|
|
switch level {
|
|
case "DEBUG":
|
|
ret = DEBUG
|
|
case "INFO":
|
|
ret = INFO
|
|
case "WARN":
|
|
ret = WARN
|
|
case "ERROR":
|
|
ret = ERROR
|
|
default:
|
|
ret = DEBUG
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (l *Logger) getLevelStr(level int) (ret string) {
|
|
switch level {
|
|
case DEBUG:
|
|
ret = "DEBUG"
|
|
case INFO:
|
|
ret = "INFO"
|
|
case WARN:
|
|
ret = "WARN"
|
|
case ERROR:
|
|
ret = "ERROR"
|
|
default:
|
|
ret = "DEBUG"
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (l *Logger) getModeInt(mode string) (ret int) {
|
|
switch mode {
|
|
case "CONSOLE":
|
|
ret = CONSOLE
|
|
case "FILE":
|
|
ret = FILE
|
|
case "BOTH":
|
|
ret = BOTH
|
|
case "NEITHER":
|
|
ret = NEITHER
|
|
default:
|
|
ret = CONSOLE
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (l *Logger) getGoroutineId() (goroutineId string) {
|
|
buf := make([]byte, 32)
|
|
runtime.Stack(buf, false)
|
|
buf = bytes.TrimPrefix(buf, []byte("goroutine "))
|
|
buf = buf[:bytes.IndexByte(buf, ' ')]
|
|
goroutineId = string(buf)
|
|
return goroutineId
|
|
}
|
|
|
|
func (l *Logger) getLineFunc() (fileName string, line int, funcName string) {
|
|
var pc uintptr
|
|
var file string
|
|
var ok bool
|
|
pc, file, line, ok = runtime.Caller(2)
|
|
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 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 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))
|
|
}
|
|
}
|