封装 logrus
封装 logrus
Golang 常用的 log 库
golang 标准库的 log 也很好用,但是缺乏一些特性功能,新能较差,所以社区衍生出如下日志库:
- logrus 可能是最早的第三方日志库
- uber_zap 优步推出的高性能日志库
- go-kit 基于 kit 产生了很多的衍生品,例如:
- google_glog_分支klog 大名鼎鼎的 kubernetes 使用的日志库特点在于增加了缓存,flush 机制。
我遇见的问题
例如:
package main
import (
log "github.com/sirupsen/logrus"
)
func main() {
// Add this line for logging filename and line number!
log.SetReportCaller(true)
log.Println("hello world")
}
输出:
INFO[0000]/Users/hello/go/src/github.com/bob/test/main.go:17 main.main() hello world
如何曲线救国
go build -v -a -ldflags '-w -s' \
-gcflags="all=-trimpath=${PWD}" \
-asmflags="all=-trimpath=${PWD}" \
-o ./app main.go
官方解决方案
但是在我的项目里调用的时候总觉得奇奇怪怪:
例如:
// log pkg
package mylog
import (
"github.com/sirupsen/logrus"
)
var Log = logrus.New()
func init(){
log.SetReportCaller(true)
log.Formatter = &logrus.TextFormatter{
CallerPrettyfier: func(f *runtime.Frame) (string, string) {
repopath := fmt.Sprintf("%s/src/github.com/bob", os.Getenv("GOPATH"))
filename := strings.Replace(f.File, repopath, "", -1)
return fmt.Sprintf("%s()", f.Function), fmt.Sprintf("%s:%d", filename, f.Line)
},
}
}
// caller func
package app
import (
"myapp/mylog"
)
func AppFunc(){
// 这里要多写一层
mylog.Log.Info("hello world")
}
封装 logrus
// mylog
package mylog
import (
"fmt"
"os"
"path"
"runtime"
"github.com/sirupsen/logrus"
)
type mylogger struct {
fp string
funcn string
l *logrus.Logger
}
var log = &mylogger{
l: logrus.New(),
}
func init() {
log.l.SetOutput(os.Stdout)
log.l.SetFormatter(&logrus.JSONFormatter{
TimestampFormat: "2006-01-02T15:04:05",
})
}
// getCallerInfo 获取调用者的函数名,调用行
func (l *mylogger) getCallerInfo() {
// 调用链往上翻三层,找到调用函数的信息
pc, file, line, ok := runtime.Caller(3)
if !ok {
return
}
funcName := runtime.FuncForPC(pc).Name()
l.funcn = path.Base(funcName)
_, fileName := path.Split(file)
l.fp = fmt.Sprintf("%s:%d", fileName, line)
}
// printer 日志处理函数
func (l *mylogger) printer(level logrus.Level, msg ...interface{}) {
log.getCallerInfo()
l.l.WithFields(logrus.Fields{"filePath": l.fp, "func": l.funcn}).Log(level, msg...)
}
// printerf 格式化日志处理
func (l *mylogger) printerf(level logrus.Level, format string, msg ...interface{}) {
log.getCallerInfo()
l.l.WithFields(logrus.Fields{"filePath": l.fp, "func": l.funcn}).Logf(level, format, msg...)
}
func Info(msg ...interface{}) {
log.printer(logrus.InfoLevel, msg...)
}
func Infof(format string, msg ...interface{}) {
log.printerf(logrus.InfoLevel, format, msg...)
}
func Debug(msg ...interface{}) {
log.printer(logrus.DebugLevel, msg...)
}
func Error(msg ...interface{}) {
log.printer(logrus.ErrorLevel, msg...)
}
func Errorf(format string, msg ...interface{}) {
log.printerf(logrus.ErrorLevel, format, msg...)
}