本文主要是介绍golang——工程组件logrus日志记录框架(结构化记录,支持文件切割,hook),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
logrus
介绍一个golang 日志框架logrus
- 支持文本与JSON数据格式
- 支持结构化记录
- 支持hook
文档介绍
logrus文档
std
官方案例介绍了如何配置std打印
package mainimport ("os"log "github.com/sirupsen/logrus"
)func init() {// Log as JSON instead of the default ASCII formatter.log.SetFormatter(&log.JSONFormatter{})// Output to stdout instead of the default stderr// Can be any io.Writer, see below for File examplelog.SetOutput(os.Stdout)// Only log the warning severity or above.log.SetLevel(log.WarnLevel)
}func main() {log.WithFields(log.Fields{"animal": "walrus","size": 10,}).Info("A group of walrus emerges from the ocean")log.WithFields(log.Fields{"omg": true,"number": 122,}).Warn("The group's number increased tremendously!")log.WithFields(log.Fields{"omg": true,"number": 100,}).Fatal("The ice breaks!")// A common pattern is to re-use fields between logging statements by re-using// the logrus.Entry returned from WithFields()contextLogger := log.WithFields(log.Fields{"common": "this is a common field","other": "I also should be logged always",})contextLogger.Info("I'll be logged with common and other field")contextLogger.Info("Me too")
}
file
仔细观察,如果要输出到文件,只需要在logrus.SetOutput
设置上对应的*os.File
即可
文件切割
文件日志记录一般都是要切割的,不然文件太大不方便查看
采用的库
https://github.com/lestrrat-go/file-rotatelogs
案例
log.go
package logsimport ("fmt""github.com/sirupsen/logrus""log"
)type Log struct {*logrus.EntryLogWriter
}func (l *Log) Flush() {l.LogWriter.Flush()
}type LogConf struct {Level logrus.LevelAdapterName stringHook logrus.Hook
}func InitLog(conf LogConf) *Log {adapterName := "std"if conf.AdapterName != "" {adapterName = conf.AdapterName}writer, ok := writerAdapter[adapterName]if !ok {adapterName = "std"writer, _ = writerAdapter[adapterName]}fmt.Println("adapterName:" + adapterName)log :=&Log{logrus.NewEntry(logrus.New()),writer(), // 初始化writer}// Log as JSON instead of the default ASCII formatter.log.Logger.SetFormatter(&logrus.JSONFormatter{})// Output to stdout instead of the default stderr// Can be any io.Writer, see below for File examplelog.Logger.SetOutput(log.LogWriter)// Only log the warning severity or above.if conf.Level != 0 {log.Logger.SetLevel(conf.Level)} else {log.Logger.SetLevel(logrus.InfoLevel)}if conf.Hook != nil {log.Logger.AddHook(conf.Hook)}// 设置日志打印位置log.Logger.SetReportCaller(true)return log
}type TestHook struct {}func (hook *TestHook) Levels() []logrus.Level {return []logrus.Level{logrus.InfoLevel}
}
func (hook *TestHook) Fire(entry *logrus.Entry) error {log.Print("hook: %+v", entry)return nil
}
file_rotate.go
package logsimport (rotatelogs "github.com/lestrrat-go/file-rotatelogs""log""time"
)type fileRotateWriter struct {*rotatelogs.RotateLogs
}func (frw *fileRotateWriter) Flush() {frw.Close()
}func newFileRotateWriter() LogWriter {writer, err := getRotateLogs()if err != nil {log.Fatal(err)}return &fileRotateWriter{writer,}
}func getRotateLogs() (*rotatelogs.RotateLogs, error) {path := LOGPATHlogf, err := rotatelogs.New(path + ".%Y%m%d%H%M", // 指定文件格式//rotatelogs.WithLinkName(path), // 将最新文件软链到path,windows环境不支持rotatelogs.WithMaxAge(time.Second*1800), // 日志最长保存时长rotatelogs.WithRotationTime(time.Second*60), // 日志切分时间间隔)return logf, err
}func init() {RegisterInitWriterFunc("file-rotate", newFileRotateWriter)
}
main.go
package mainimport ("logrus-practice/logs""github.com/sirupsen/logrus"
)func main() {conf := logs.LogConf{Level: logrus.InfoLevel,AdapterName: "file-rotate",Hook: &logs.TestHook{},}log := logs.InitLog(conf)log.WithFields(logrus.Fields{"animal": "walrus","size": 10,}).Info("A group of walrus emerges from the ocean")log.WithFields(logrus.Fields{"omg": true,"number": 122,}).Warn("The group's number increased tremendously!")log.WithFields(logrus.Fields{"omg": true,"number": 100,}).Fatal("The ice breaks!")// A common pattern is to re-use fields between logging statements by re-using// the logrus.Entry returned from WithFields()contextLogger := log.WithFields(logrus.Fields{"common": "this is a common field","other": "I also should be logged always",})contextLogger.Info("I'll be logged with common and other field")contextLogger.Info("Me too")
}
hook机制
框架支持,在不同level的日志打印中进行hook。我们可以根据传入的*logrus.Entry
里用户自定义的field进行不同的业务处理
上面代码已经含有hook的使用
type TestHook struct {}func (hook *TestHook) Levels() []logrus.Level {return []logrus.Level{logrus.InfoLevel}
}
func (hook *TestHook) Fire(entry *logrus.Entry) error {// 可以根据data字段里的field 去做操作log.Print("hook: %+v", entry)return nil
}
生成环境中,很多公司都会采用ELK那一套,把日志转发录入到ES中,在kibana按条件搜索
这篇关于golang——工程组件logrus日志记录框架(结构化记录,支持文件切割,hook)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!