Log program is an essential part, due to the built-in log Go language library function is relatively simple, we often choose to use a third-party logging library for development in the actual development. This article describes the logrus
basic use of the log library.
logrus Introduction
Logrus is Go (golang) structured logger, is fully compatible with the standard API library logger.
It has the following characteristics:
- Fully compatible with standard logging library has seven kinds of log levels:
Trace
,Debug
,Info
,Warning
,Error
,Fatal
andPanic
. - Hook extensible mechanism allowing the user by way of the log Hook distributed to any place, such as a local file system, logstash, elasticsearch mq or the like, or by Hook defined format and contents of the log
- Optional log output format, two built-in log format and the TextFormatter JSONFormater, can also customize the log format
- Field mechanism structured by the logging mechanism Filed
- Thread Safety
installation
go get github.com/sirupsen/logrus
A basic example
Logrus The easiest way to use a simple packet-level export logs program:
package main
import (
log "github.com/sirupsen/logrus"
)
func main() {
log.WithFields(log.Fields{
"animal": "dog",
}).Info("一条舔狗出现了。")
}
Advanced example
For more advanced uses, such as recording in the same application to multiple locations, you can also create an instance of logrus Logger:
package main
import (
"os"
"github.com/sirupsen/logrus"
)
// 创建一个新的logger实例。可以创建任意多个。
var log = logrus.New()
func main() {
// 设置日志输出为os.Stdout
log.Out = os.Stdout
// 可以设置像文件等任意`io.Writer`类型作为日志输出
// file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
// if err == nil {
// log.Out = file
// } else {
// log.Info("Failed to log to file, using default stderr")
// }
log.WithFields(logrus.Fields{
"animal": "dog",
"size": 10,
}).Info("一群舔狗出现了。")
}
Log Level
Logrus has seven log levels: Trace
, Debug
, Info
, Warning
, Error
, Fatal
and Panic
.
log.Trace("Something very low level.")
log.Debug("Useful debugging information.")
log.Info("Something noteworthy happened!")
log.Warn("You should probably take a look at this.")
log.Error("Something failed but I'm not quitting.")
// 记完日志后会调用os.Exit(1)
log.Fatal("Bye.")
// 记完日志后会调用 panic()
log.Panic("I'm bailing.")
Set the log level
You can set the level of logging on the Logger, then it will only record with entry level or above the level of any of the content:
// 会记录info及以上级别 (warn, error, fatal, panic)
log.SetLevel(log.InfoLevel)
If your program supports debug mode or an environment variable set log.Level = logrus.DebugLevel
would be helpful.
Field
Logrus encourage prudent structured logging by log fields, rather than lengthy, error messages can not be resolved.
For example, different use log.Fatalf("Failed to send event %s to topic %s with key %d")
, you should use the following recorded content easier to find:
log.WithFields(log.Fields{
"event": event,
"topic": topic,
"key": key,
}).Fatal("Failed to send event")
WithFields
The call is optional.
Default Field
Typically, some of the fields are always attached to the log statement of all or part of the application would be helpful. For example, you might want to always be in the context of the request is recorded request_id
and user_ip
.
Write on each line is different from the log log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip})
, you can create one as to the following sample code logrus.Entry
to pass these fields.
requestLogger := log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip})
requestLogger.Info("something happened on that request") # will log request_id and user_ip
requestLogger.Warn("something not great happened")
Log entry
In addition to using WithField
or WithFields
outside the field added, some fields will be automatically added to all logging in the matter:
- time: time stamp when logging
- msg: log information recorded
- Log level record: level
Hooks
You can add a log level of hook (Hook). For example, tracking service sends abnormal Error
, Fatal
and Panic
information to be transmitted simultaneously StatsD or logs to a plurality of positions, such as syslog.
Logrus is equipped with a built-hook. In init
adding these custom built-in hooks or hooks you in:
import (
log "github.com/sirupsen/logrus"
"gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "airbrake"
logrus_syslog "github.com/sirupsen/logrus/hooks/syslog"
"log/syslog"
)
func init() {
// Use the Airbrake hook to report errors that have Error severity or above to
// an exception tracker. You can create custom hooks, see the Hooks section.
log.AddHook(airbrake.NewHook(123, "xyz", "production"))
hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
if err != nil {
log.Error("Unable to connect to local syslog daemon")
} else {
log.AddHook(hook)
}
}
Meaning: Syslog hook also may support connections to a local syslog (e.g. "/ dev / log" or " / var / run / syslog" or "/ var / run / log".). For more information, please see the syslog Hook the README .
format
logrus built two log formatter:
logrus.TextFormatter
logrus.JSONFormatter
Also supports third-party formatting program, see the project home page.
Record function name
If you want to add the name of the function that will be called for the field, in the following manner:
log.SetReportCaller(true)
This will add the caller as "method", as follows:
{"animal":"penguin","level":"fatal","method":"github.com/sirupsen/arcticcreatures.migrate","msg":"a penguin swims by",
"time":"2014-03-10 19:57:38.562543129 -0400 EDT"}
```
注意:,开启这个模式会增加性能开销。
线程安全
默认的logger在并发写的时候是被mutex保护的,比如当同时调用hook和写log时mutex就会被请求,有另外一种情况,文件是以appending mode打开的, 此时的并发操作就是安全的,可以用
logger.SetNoLock()
来关闭它。gin框架使用logrus
// a gin with logrus demo var log = logrus.New() func init() { // Log as JSON instead of the default ASCII formatter. log.Formatter = &logrus.JSONFormatter{} // Output to stdout instead of the default stderr // Can be any io.Writer, see below for File example f, _ := os.Create("./gin.log") log.Out = f gin.SetMode(gin.ReleaseMode) gin.DefaultWriter = log.Out // Only log the warning severity or above. log.Level = logrus.InfoLevel } func main() { // 创建一个默认的路由引擎 r := gin.Default() // GET:请求方式;/hello:请求的路径 // 当客户端以GET方法请求/hello路径时,会执行后面的匿名函数 r.GET("/hello", func(c *gin.Context) { log.WithFields(logrus.Fields{ "animal": "walrus", "size": 10, }).Warn("A group of walrus emerges from the ocean") // c.JSON:返回JSON格式的数据 c.JSON(200, gin.H{ "message": "Hello world!", }) }) // 启动HTTP服务,默认在0.0.0.0:8080启动服务 r.Run() }