我们常使用 Go log 以下三组函数:
- Print/Printf/Println : 打印日志信息
- Panic/Panicf/Panicln : 打印日志信息后,以拼装好的字符串为参数调用 Panic
- Fatal/Fatalf/Fatalln : 打印日志信息后,os.Exit(1) 退出程序
var std = New(os.Stderr, "", LstdFlags)
func New(out io.Writer, prefix string, flag int) *Logger {
return &Logger{out: out, prefix: prefix, flag: flag}
}
type Logger struct {
mu sync.Mutex // ensures atomic writes; protects the following fields
prefix string // prefix on each line to identify the logger (but see Lmsgprefix)
flag int // properties
out io.Writer // destination for output
buf []byte // for accumulating text to write
}
func Println(v ...interface{}) {
std.Output(2, fmt.Sprintln(v...))
}
std
使用 log.New
构造出来,三个参数:
-
io.Writer
: 任何实现了 Writer 接口的结构,日志会写到这个里面, std 的输出位置是 os.Stderr -
prefix
: 自定义前缀字符串,std 传入的是空字符串 -
flag
: 一些标志位,定制化 prefix,std 的是 LstdFlags, 默认日志格式中的时间就从这个标志位而来
而日志输出位置,自定义前缀字符串,flag 这三者都能够自定义:
func main() {
var buf bytes.Buffer
log.SetOutput(&buf)
log.SetPrefix("[info: ]")
log.SetFlags(log.LstdFlags | log.Lshortfile)
log.Println("自定义日志格式")
//fmt.Print(&buf)
}
基本的 log 至少还需要输出不同的日志级别,所以可以基于标准库的 Log库 简单封装一个支持不同日志级别输出的日志。
package main
import (
"fmt"
"io"
"log"
"os"
"runtime"
"strings"
)
type Level int
const (
ErrorLevel Level = 0
WarnLevel Level = 1
InfoLevel Level = 2
DebugLevel Level = 3
)
func levelToString(level Level) string {
switch level {
case InfoLevel:
return "info"
case WarnLevel:
return "warn"
case ErrorLevel:
return "error"
case DebugLevel:
return "debug"
}
return ""
}
func levelToFormatString(level Level) string {
switch level {
case InfoLevel:
return "[" + levelToString(level) + "]"
case WarnLevel:
return "[" + levelToString(level) + "]"
case ErrorLevel:
return "[" + levelToString(level) + "]"
case DebugLevel:
return "[" + levelToString(level) + "]"
}
return ""
}
type Logger struct {
out io.WriteCloser
level Level
logger *log.Logger
requestID string
}
var logFlags = log.Ldate | log.Ltime | log.Lmicroseconds
func NewLogger(path string, logLevel Level) Logger {
file, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
panic("failed to open log file" + path)
}
l := Logger{
out: file,
level: logLevel,
logger: log.New(file, "", logFlags),
}
return l
}
func (l *Logger) SetRequestID(requestID string) {
l.requestID = requestID
}
func (l Logger) Close() error {
return l.out.Close()
}
func (l Logger) Debug(args ...interface{}) {
if l.level < DebugLevel {
return
}
preFixArray := make([]interface{}, 0, 10)
preFixArray = append(preFixArray, getCaller())
preFixArray = append(preFixArray, l.requestID)
preFixArray = append(preFixArray, levelToFormatString(DebugLevel))
args = append(preFixArray, args...)
l.logger.Println(args...)
}
func (l Logger) INFO(args ...interface{}) {
if l.level < InfoLevel {
return
}
preFixArray := make([]interface{}, 0, 10)
preFixArray = append(preFixArray, getCaller())
preFixArray = append(preFixArray, l.requestID)
preFixArray = append(preFixArray, levelToFormatString(InfoLevel))
args = append(preFixArray, args...)
l.logger.Println(args...)
}
func (l Logger) Warn(args ...interface{}) {
if l.level < WarnLevel {
return
}
preFixArray := make([]interface{}, 0, 10)
preFixArray = append(preFixArray, getCaller())
preFixArray = append(preFixArray, l.requestID)
preFixArray = append(preFixArray, levelToFormatString(WarnLevel))
args = append(preFixArray, args...)
l.logger.Println(args...)
}
func (l Logger) Error(args ...interface{}) {
if l.level < ErrorLevel {
return
}
preFixArray := make([]interface{}, 0, 10)
preFixArray = append(preFixArray, getCaller())
preFixArray = append(preFixArray, l.requestID)
preFixArray = append(preFixArray, levelToFormatString(ErrorLevel))
args = append(preFixArray, args...)
l.logger.Println(args...)
}
func getCaller() string {
pc, fullPath, line, ok := runtime.Caller(2)
if !ok {
return ""
}
pcName := runtime.FuncForPC(pc).Name()
file := fullPath
pcNameParts := strings.Split(pcName, "/")
pcName = pcNameParts[len(pcNameParts)-1]
pcNameParts = strings.Split(pcName, ".")
pcName = pcNameParts[len(pcNameParts)-1]
return fmt.Sprintf("%s:%s:%d", file, pcName, line)
}
var GLog Logger
测试:
func main() {
GLog := NewLogger("./core.log", InfoLevel)
GLog.SetRequestID("wyauix1qu")
defer GLog.Close()
GLog.Debug("hello world")
GLog.INFO("hello world")
GLog.Warn("hello world")
GLog.Error("hello world")
}
输出日志格式:
2022/05/15 05:29:42.186008 D:/Code/go_workspace/project/gotour/gotour/loger/main.go:main:9 wyauix1qu [info] hello world
2022/05/15 05:29:42.212080 D:/Code/go_workspace/project/gotour/gotour/loger/main.go:main:10 wyauix1qu [warn] hello world
2022/05/15 05:29:42.212080 D:/Code/go_workspace/project/gotour/gotour/loger/main.go:main:11 wyauix1qu [error] hello world
网友评论