Logrus是一个结构化的Go日志记录器(golang),完全使用API与标准库日志记录器兼容。

Logrus处于维护模式。我们不会引入新的特性。以一种不会破坏很多人的项目的方式来实现它实在是太难了,这是您最不希望从日志库中得到的(再次…)。

我相信Logrus最大的贡献是在今天Golang广泛使用的结构化日志中发挥了作用。似乎没有理由把迭代分解成Logrus V2,因为出色的Go社区已经独立构建了它们。许多奇妙的替代品如雨后春笋般涌现。如果按照我们今天所知道的Go中的结构化登录方式重新设计的话,Logrus看起来就是这样的。比如Zerolog, ZapApex

看到奇怪的大小写敏感问题了吗?在过去,可以同时导入大写和小写的Logrus。由于Go包的环境,这在社区中引起了问题,我们需要一个标准。一些环境在使用大写变体时遇到了问题,因此决定使用小写。所有使用logrus的东西都需要使用小写字母:github.com/sirupsen/logrus。任何不是这样的包都应该更改。

要修复Glide,请看下面的评论。对于代码问题深入理解,具体看 这些评论

漂亮的颜色编码在开发(当一个TTY是附加的,否则只是纯文本):

logrus - 图1

使用log.SetFormatter(&log.JSONFormatter{}),通过logstash或Splunk轻松解析:

  1. {"animal":"walrus","level":"info","msg":"A group of walrus emerges from the
  2. ocean","size":10,"time":"2014-03-10 19:57:38.562264131 -0400 EDT"}
  3. {"level":"warning","msg":"The group's number increased tremendously!",
  4. "number":122,"omg":true,"time":"2014-03-10 19:57:38.562471297 -0400 EDT"}
  5. {"animal":"walrus","level":"info","msg":"A giant walrus appears!",
  6. "size":10,"time":"2014-03-10 19:57:38.562500591 -0400 EDT"}
  7. {"animal":"walrus","level":"info","msg":"Tremendously sized cow enters the ocean.",
  8. "size":9,"time":"2014-03-10 19:57:38.562527896 -0400 EDT"}
  9. {"level":"fatal","msg":"The ice breaks!","number":100,"omg":true,
  10. "time":"2014-03-10 19:57:38.562543128 -0400 EDT"}

当没有附加TTY时,使用默认的log.SetFormatter(&log.TextFormatter{}),输出与logfmt格式兼容:

  1. time="2015-03-26T01:27:38-04:00" level=debug msg="Started observing beach" animal=walrus number=8
  2. time="2015-03-26T01:27:38-04:00" level=info msg="A group of walrus emerges from the ocean" animal=walrus size=10
  3. time="2015-03-26T01:27:38-04:00" level=warning msg="The group's number increased tremendously!" number=122 omg=true
  4. time="2015-03-26T01:27:38-04:00" level=debug msg="Temperature changes" temperature=-4
  5. time="2015-03-26T01:27:38-04:00" level=panic msg="It's over 9000!" animal=orca size=9009
  6. time="2015-03-26T01:27:38-04:00" level=fatal msg="The ice breaks!" err=&{0x2082280c0 map[animal:orca size:9009] 2015-03-26 01:27:38.441574009 -0400 EDT panic It's over 9000!} number=100 omg=true

即使附加了TTY,也要确保这种行为,请按如下方式设置格式化程序:

  1. log.SetFormatter(&log.TextFormatter{
  2. DisableColors: true,
  3. FullTimestamp: true,
  4. })

日志记录方法名称

如果你想添加调用方法作为一个字段,通过以下方式指示日志记录器:

  1. log.SetReportCaller(true)

这将调用者添加为“方法”,如下所示:

  1. {"animal":"penguin","level":"fatal","method":"github.com/sirupsen/arcticcreatures.migrate","msg":"a penguin swims by",
  2. "time":"2014-03-10 19:57:38.562543129 -0400 EDT"}
  1. time="2015-03-26T01:27:38-04:00" level=fatal method=github.com/sirupsen/arcticcreatures.migrate msg="a penguin swims by" animal=penguin

注意,这确实增加了可测量的开销——成本将取决于Go的版本,但在最近的1.6和1.7测试中在20%到40%之间。您可以验证这在您的环境通过基准:

  1. go test -bench=.*CallerTracing

敏感情况

该组织的名称已更改为小写——而且不会再更改回小写。如果由于大小写敏感导致导入冲突,请使用小写导入:github.com/sirupsen/logrus。

Example

使用Logrus最简单的方法就是使用包级导出的日志程序:

  1. package main
  2. import (
  3. log "github.com/sirupsen/logrus"
  4. )
  5. func main() {
  6. log.WithFields(log.Fields{
  7. "animal": "walrus",
  8. }).Info("A walrus appears")
  9. }

注意,它与stdlib日志记录器完全兼容api,所以你可以在任何地方用日志“github.com/sirupsen/logrus”替换你的日志导入,现在你将拥有Logrus的灵活性。你可以自定义它所有你想:

  1. package main
  2. import (
  3. "os"
  4. log "github.com/sirupsen/logrus"
  5. )
  6. func init() {
  7. // Log as JSON instead of the default ASCII formatter.
  8. log.SetFormatter(&log.JSONFormatter{})
  9. // Output to stdout instead of the default stderr
  10. // Can be any io.Writer, see below for File example
  11. log.SetOutput(os.Stdout)
  12. // Only log the warning severity or above.
  13. log.SetLevel(log.WarnLevel)
  14. }
  15. func main() {
  16. log.WithFields(log.Fields{
  17. "animal": "walrus",
  18. "size": 10,
  19. }).Info("A group of walrus emerges from the ocean")
  20. log.WithFields(log.Fields{
  21. "omg": true,
  22. "number": 122,
  23. }).Warn("The group's number increased tremendously!")
  24. log.WithFields(log.Fields{
  25. "omg": true,
  26. "number": 100,
  27. }).Fatal("The ice breaks!")
  28. // A common pattern is to re-use fields between logging statements by re-using
  29. // the logrus.Entry returned from WithFields()
  30. contextLogger := log.WithFields(log.Fields{
  31. "common": "this is a common field",
  32. "other": "I also should be logged always",
  33. })
  34. contextLogger.Info("I'll be logged with common and other field")
  35. contextLogger.Info("Me too")
  36. }

对于更高级的使用,比如从同一个应用程序记录到多个位置,你也可以创建一个logrus日志记录器的实例:

  1. package main
  2. import (
  3. "os"
  4. "github.com/sirupsen/logrus"
  5. )
  6. // Create a new instance of the logger. You can have any number of instances.
  7. var log = logrus.New()
  8. func main() {
  9. // The API for setting attributes is a little different than the package level
  10. // exported logger. See Godoc.
  11. log.Out = os.Stdout
  12. // You could set this to any `io.Writer` such as a file
  13. // file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
  14. // if err == nil {
  15. // log.Out = file
  16. // } else {
  17. // log.Info("Failed to log to file, using default stderr")
  18. // }
  19. log.WithFields(logrus.Fields{
  20. "animal": "walrus",
  21. "size": 10,
  22. }).Info("A group of walrus emerges from the ocean")
  23. }

Fields

Logrus鼓励通过日志字段进行谨慎的、结构化的日志记录,而不是冗长的、不可解析的错误消息。例如,代替 : log.Fatalf(“Failed to send event %s to topic %s with key %d”),您应该记录更多可发现的内容:

  1. log.WithFields(log.Fields{
  2. "event": event,
  3. "topic": topic,
  4. "key": key,
  5. }).Fatal("Failed to send event")

我们发现这个API迫使您以一种产生更有用的日志消息的方式来考虑日志记录。我们已经遇到过无数这样的情况:只需向日志语句中添加一个字段就可以节省我们的时间。WithFields调用是可选的。

一般来说,使用任何printf家族函数的Logrus都应该被视为应该添加字段的提示,但是,仍然可以使用Logrus家族函数。

Default Fields

通常,将字段始终附加到应用程序中的日志语句或其中的部分日志语句中是很有帮助的。例如,您可能希望始终将request_id和user_ip记录在请求的上下文中。而不是写log.WithFields(log.Fields{“request_id”: request_id, “user_ip”: user_ip})在每一行上,您可以创建一个logrus。进入传递代替:

  1. requestLogger := log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip})
  2. requestLogger.Info("something happened on that request") # will log request_id and user_ip
  3. requestLogger.Warn("something not great happened")

Hooks

您可以为日志级别添加钩子。例如,发送错误到异常跟踪服务的错误,致命和恐慌,信息到StatsD或日志到多个地方同时,如syslog。

Logrus自带内置钩子。在init中添加这些,或者自定义钩子:

  1. import (
  2. log "github.com/sirupsen/logrus"
  3. "gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "airbrake"
  4. logrus_syslog "github.com/sirupsen/logrus/hooks/syslog"
  5. "log/syslog"
  6. )
  7. func init() {
  8. // Use the Airbrake hook to report errors that have Error severity or above to
  9. // an exception tracker. You can create custom hooks, see the Hooks section.
  10. log.AddHook(airbrake.NewHook(123, "xyz", "production"))
  11. hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
  12. if err != nil {
  13. log.Error("Unable to connect to local syslog daemon")
  14. } else {
  15. log.AddHook(hook)
  16. }
  17. }

注意:系统slog钩子也支持连接到本地系统slog(例如。“/ dev /日志”或“/ var /运行/ syslog”或“/ var /运行/日志”)。详细信息,请查看syslog钩子自述。

在这个wiki页面中可以找到当前已知的服务钩子列表

Level logging

Logrus有七个日志级别:跟踪、调试、信息、警告、错误、致命和恐慌。

  1. log.Trace("Something very low level.")
  2. log.Debug("Useful debugging information.")
  3. log.Info("Something noteworthy happened!")
  4. log.Warn("You should probably take a look at this.")
  5. log.Error("Something failed but I'm not quitting.")
  6. // Calls os.Exit(1) after logging
  7. log.Fatal("Bye.")
  8. // Calls panic() after logging
  9. log.Panic("I'm bailing.")

你可以在日志记录器上设置日志级别,然后它只会记录严重程度或以上的条目:

  1. // Will log anything that is info or above (warn, error, fatal, panic). Default.
  2. log.SetLevel(log.InfoLevel)

设置日志可能很有用 log.Level = logrus.DebugLevel 如果您的应用程序具有debug或verbose环境中的DebugLevel。

Entries

除了用WithField或WithFields添加的字段,一些字段自动添加到所有日志事件:

  1. time.创建条目时的时间戳
  2. msg. 在AddFields调用后,日志信息被传递到{Info,Warn,Error,Fatal,Panic}。发送事件失败。
  3. level.日志级别。如信息。

Environments