Files
hk4e/pkg/logger/logger.go
2022-12-02 19:23:12 +08:00

226 lines
4.6 KiB
Go

package logger
import (
"bytes"
"fmt"
"log"
"os"
"path"
"runtime"
"strconv"
"time"
)
const (
DEBUG int = 1
INFO int = 2
ERROR int = 3
UNKNOWN int = 4
)
const (
CONSOLE int = 1
FILE int = 2
BOTH int = 3
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 {
Level string `toml:"level"`
Method string `toml:"method"`
TrackLine bool `toml:"track_line"`
}
func InitLogger(name string, cfg Config) {
log.SetFlags(0)
LOG = new(Logger)
LOG.level = getLevelInt(cfg.Level)
LOG.method = getMethodInt(cfg.Method)
LOG.trackLine = cfg.TrackLine
LOG.logInfoChan = make(chan *LogInfo, 1000)
if LOG.method == FILE || LOG.method == BOTH {
file, err := os.OpenFile("./"+name+".log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
info := fmt.Sprintf("open log file error: %v\n", err)
panic(info)
}
LOG.file = file
}
go LOG.doLog()
}
func (l *Logger) doLog() {
for {
logInfo := <-l.logInfoChan
timeNow := time.Now()
timeNowStr := timeNow.Format("2006-01-02 15:04:05.000")
logHeader := "[" + timeNowStr + "]" + " " +
"[" + l.getLevelStr(logInfo.logLevel) + "]" + " "
if l.trackLine {
logHeader += "[" +
"line:" + logInfo.fileInfo + ":" + strconv.FormatInt(int64(logInfo.lineInfo), 10) +
" func:" + logInfo.funcInfo +
" goroutine:" + logInfo.goroutineId +
"]" + " "
}
logStr := logHeader + fmt.Sprintf(logInfo.msg, logInfo.param...) + "\n"
red := string([]byte{27, 91, 51, 49, 109})
green := string([]byte{27, 91, 51, 50, 109})
reset := string([]byte{27, 91, 48, 109})
if l.method == CONSOLE {
if logInfo.logLevel == ERROR {
log.Print(red, logStr, reset)
} else if logInfo.logLevel == INFO {
log.Print(green, logStr, reset)
} else {
log.Print(logStr)
}
} else if l.method == FILE {
_, _ = l.file.WriteString(logStr)
} else if l.method == BOTH {
if logInfo.logLevel == ERROR {
log.Print(red, logStr, reset)
} else if logInfo.logLevel == INFO {
log.Print(green, logStr, reset)
} else {
log.Print(logStr)
}
_, _ = l.file.WriteString(logStr)
}
}
}
func (l *Logger) Debug(msg string, param ...any) {
if l.level > DEBUG {
return
}
logInfo := new(LogInfo)
logInfo.logLevel = DEBUG
logInfo.msg = msg
logInfo.param = param
if l.trackLine {
fileInfo, funcInfo, lineInfo := l.getLineInfo()
logInfo.fileInfo = fileInfo
logInfo.funcInfo = funcInfo
logInfo.lineInfo = lineInfo
logInfo.goroutineId = l.getGoroutineId()
}
l.logInfoChan <- logInfo
}
func (l *Logger) Info(msg string, param ...any) {
if l.level > INFO {
return
}
logInfo := new(LogInfo)
logInfo.logLevel = INFO
logInfo.msg = msg
logInfo.param = param
if l.trackLine {
fileInfo, funcInfo, lineInfo := l.getLineInfo()
logInfo.fileInfo = fileInfo
logInfo.funcInfo = funcInfo
logInfo.lineInfo = lineInfo
logInfo.goroutineId = l.getGoroutineId()
}
l.logInfoChan <- logInfo
}
func (l *Logger) Error(msg string, param ...any) {
if l.level > ERROR {
return
}
logInfo := new(LogInfo)
logInfo.logLevel = ERROR
logInfo.msg = msg
logInfo.param = param
if l.trackLine {
fileInfo, funcInfo, lineInfo := l.getLineInfo()
logInfo.fileInfo = fileInfo
logInfo.funcInfo = funcInfo
logInfo.lineInfo = lineInfo
logInfo.goroutineId = l.getGoroutineId()
}
l.logInfoChan <- logInfo
}
func getLevelInt(level string) (ret int) {
switch level {
case "DEBUG":
ret = DEBUG
case "INFO":
ret = INFO
case "ERROR":
ret = ERROR
default:
ret = UNKNOWN
}
return ret
}
func (l *Logger) getLevelStr(level int) (ret string) {
switch level {
case DEBUG:
ret = "DEBUG"
case INFO:
ret = "INFO"
case ERROR:
ret = "ERROR"
}
return ret
}
func getMethodInt(method string) (ret int) {
switch method {
case "CONSOLE":
ret = CONSOLE
case "FILE":
ret = FILE
case "BOTH":
ret = BOTH
default:
ret = NEITHER
}
return ret
}
func (l *Logger) getGoroutineId() (goroutineId string) {
staticInfo := make([]byte, 32)
runtime.Stack(staticInfo, false)
staticInfo = bytes.TrimPrefix(staticInfo, []byte("goroutine "))
staticInfo = staticInfo[:bytes.IndexByte(staticInfo, ' ')]
goroutineId = string(staticInfo)
return goroutineId
}
func (l *Logger) getLineInfo() (fileName string, funcName string, lineNo int) {
pc, file, line, ok := runtime.Caller(2)
if ok {
fileName = path.Base(file)
funcName = path.Base(runtime.FuncForPC(pc).Name())
lineNo = line
}
return
}