logrus logging framework


logrus Introduction

Logging framework golang standard library is very simple, only provides print, panic and fatal three functions. For finer the log level, the log file segmentation, and distribution and other aspects of the log, it does not provide support. Golang in the world, popular logging frameworks include logrus, zap, zerolog, seelog and so on.


logrus Configuration

1. Log Level: Logrus has seven log levels, followed byTrace << Debug << Info << Warning << Error << Fatal << Panic

//  只输出不低于当前级别是日志数据
logrus.SetLevel(logrus.DebugLevel)

2. Log Format: Logrus built JSONFormatterand TextFormattertwo formats, can also Formatterinterface definition log format

 // TextFormatter格式
 logrus.SetFormatter(&logrus.TextFormatter{
    ForceColors:               true,
    EnvironmentOverrideColors: true,
    TimestampFormat:           "2006-01-02 15:04:05", //时间格式
    // FullTimestamp:true,
    // DisableLevelTruncation:true,
 })
 // JSONFormatter格式
 logrus.SetFormatter(&logrus.JSONFormatter{
    PrettyPrint:     false,                 //格式化
    TimestampFormat: "2006-01-02 15:04:05", //时间格式
 })

3. Output file:

 logfile, _ := os.OpenFile("./app.log", os.O_CREATE|os.O_RDWR|os.O_APPEND, 0644)
 logrus.SetOutput(logfile) //默认为os.stderr

4.Log Location: positioning line number func=main.main file="./xxx.go:38"(eg: )

logrus.SetReportCaller(true)

Example:

func init() {
   logrus.SetLevel(logrus.DebugLevel)

   logrus.SetFormatter(&logrus.JSONFormatter{
      TimestampFormat: "2006-01-02 15:04:05",
   })

   logfile, _ := os.OpenFile("./app.log", os.O_CREATE|os.O_RDWR|os.O_APPEND, 0644)
   logrus.SetOutput(logfile) //默认为os.stderr
}

//方式一:logrus函数(最终调用的是logrus.StandardLogger默认实例方法)
func main() {
   logrus.Infoln("测试数据")
}


Log Print

FieldLogger Interface: FieldLogger defines the method of printing all logs

type FieldLogger interface {
   WithField(key string, value interface{}) *Entry
   WithFields(fields Fields) *Entry
   WithError(err error) *Entry

   Debugf(format string, args ...interface{})
   Infof(format string, args ...interface{})
   Printf(format string, args ...interface{})
   Warnf(format string, args ...interface{})
   Warningf(format string, args ...interface{})
   Errorf(format string, args ...interface{})
   Fatalf(format string, args ...interface{})
   Panicf(format string, args ...interface{})

   Debug(args ...interface{})
   Info(args ...interface{})
   Print(args ...interface{})
   Warn(args ...interface{})
   Warning(args ...interface{})
   Error(args ...interface{})
   Fatal(args ...interface{})
   Panic(args ...interface{})

   Debugln(args ...interface{})
   Infoln(args ...interface{})
   Println(args ...interface{})
   Warnln(args ...interface{})
   Warningln(args ...interface{})
   Errorln(args ...interface{})
   Fatalln(args ...interface{})
   Panicln(args ...interface{})
}

Print log 1: 默认实例 (函数) , i.e. by the function package provides logrus (covers FieldLoggerall methods interfaces), direct printing log. But in fact logrus pack function is called logrus.Logerthe default instance.

// 直接调用包函数
func main() {
   logrus.Infoln("...")
   logrus.Errorln("...")
   // ...
}

Log Printing 2:Logger实例(对象) , which implements the FieldLoggerinterface.

func main() {
   //var loger = logrus.StandardLogger()
   var loger = logrus.New()
   loger.Formatter = &logrus.JSONFormatter{TimestampFormat: "2006-01-02 15:04:05"}
   loger.Infoln("可以创建任意数量的logrus实例")
}

Print log 3:Entry示例(对象) It also implements FieldLoggerthe interface, it is the final print log entry.

  • Here used Fieldmechanism, logrus encouraged by Fieldfine of structured logging mechanism, rather than logging through lengthy messages.
func main() {
   logrus.SetFormatter(&logrus.JSONFormatter{TimestampFormat: "2006-01-02 15:04:05"})

   // Entry实例
   entry := logrus.WithFields(logrus.Fields{
      "global": "全局字段",
   })

   entry.WithFields(logrus.Fields{"module": "用户模块"}).
      Info("测试ok")
}


HOOK mechanism

  • That hook hook interceptors. It provides logrus powerful extensions, such as the distribution log into any place, such as the local file system logstash, esand so on, or cut logs, define the log content and format. Interface hook prototype is as follows:
type Hook interface {
   Levels() []Level   //日志级别
   Fire(*Entry) error //打印入口(Entry对象)
}

Hook - Cutting logs:

import (
   "github.com/lestrrat-go/file-rotatelogs"
   "github.com/rifflock/lfshook"
   "github.com/sirupsen/logrus"
   "time"
)

//  说明:按时间切割日志文件(2秒创建一个日志文件)
func main() {
   hook := NewLfsHook("app_hook", time.Second*2, 5)
   logrus.AddHook(hook)

   logrus.Infoln("测试开始")
   log := logrus.WithFields(logrus.Fields{"module": "用户模块"})

   for i := 0; i < 10; i++ {
      log.Infoln("成功", i)
      time.Sleep(time.Second)
   }
}

// 日志钩子(日志拦截,并重定向)
func NewLfsHook(logName string, rotationTime time.Duration, leastDay uint) logrus.Hook {
   writer, err := rotatelogs.New(
      // 日志文件
      logName+".%Y%m%d%H%M%S",

      // 日志周期(默认每86400秒/一天旋转一次)
      rotatelogs.WithRotationTime(rotationTime),

      // 清除历史 (WithMaxAge和WithRotationCount只能选其一)
      //rotatelogs.WithMaxAge(time.Hour*24*7), //默认每7天清除下日志文件
      rotatelogs.WithRotationCount(leastDay), //只保留最近的N个日志文件
   )
   if err != nil {
      panic(err)
   }

   // 可设置按不同level创建不同的文件名
   lfsHook := lfshook.NewHook(lfshook.WriterMap{
      logrus.DebugLevel: writer,
      logrus.InfoLevel:  writer,
      logrus.WarnLevel:  writer,
      logrus.ErrorLevel: writer,
      logrus.FatalLevel: writer,
      logrus.PanicLevel: writer,
   }, &logrus.JSONFormatter{TimestampFormat: "2006-01-02 15:04:05"})

   return lfsHook
}

Hook - Redis redirection: about to log output to redis

import (
   logredis "github.com/rogierlommers/logrus-redis-hook"
   "io/ioutil"
   "github.com/sirupsen/logrus"
)

func init() {
   hookConfig := logredis.HookConfig{
      Host:     "localhost",
      Key:      "test",
      Format:   "v1",
      App:      "my_app_name",
      Port:     6379,
      Hostname: "my_app_hostname", 
      DB:       0, // optional
      TTL:      3600,
   }

   hook, err := logredis.NewHook(hookConfig)
   if err == nil {
      logrus.AddHook(hook)
   } else {
      logrus.Errorf("logredis error: %q", err)
   }
}

func main() {
   logrus.WithFields(logrus.Fields{
      "module": "user"}).
      Info("user login")

   // If you want to disable writing to stdout, use setOutput
   logrus.SetOutput(ioutil.Discard)
   logrus.Info("log to Redis")
}

// 测试:
// 1.启动redis服务: redis-server
// 2.监控redis数据: redis-cli monitor

Other Hook:


Gin log

  • Log gin framework directed to the log file logrus
func init() {
   // 输出格式
   logrus.SetFormatter(&logrus.JSONFormatter{TimestampFormat: "2006-01-02 15:04:05"})

   // 输出路径
   logfile, _ := os.OpenFile("./app.log", os.O_CREATE|os.O_RDWR|os.O_APPEND, 0644)
   logrus.SetOutput(logfile)

   // Gin日志重定向
   gin.DisableConsoleColor()                              //不需要颜色
   gin.DefaultWriter = io.MultiWriter(os.Stdout, logfile) //os.Stdout
}

//测试:curl 0.0.0.0:8080/index
func main() {
   log := logrus.WithFields(logrus.Fields{
      "module": "用户模块",
   })

   r := gin.Default()
   r.GET("/index", func(c *gin.Context) {
      log.Warnln("gin日志数据")
      c.String(200, "ok")
   })
   _ = r.Run()
}


Fatal processing

  • logrus of Fataloutput, will perform os.Exit(1). logrus provides RegisterExitHandlermethods that can be called api release some resources such as abnormal in the system, so that the application properly closed.
func main() {
   logrus.RegisterExitHandler(func() {
      fmt.Println("发生了fatal异常,执行关闭文件等工作")
   })

   logrus.Warnln("warn测试")
   logrus.Fatalln("fatal测试")
   logrus.Infoln("info测试") //不会执行
}


Thread Safety

  • By default, logrus the api are thread-safe, through its internal mutex to protect concurrent write. Mutex execute when you call or write the log hooks. If you do not lock, you can call logger.SetNoLock()to close it.
    You can turn off logrus mutex scenarios include:
  • Not set hook, or all of the hook are thread-safe implementation.
  • Write logs to logger.Out already thread-safe. For example, logger.Out lock has been protected, or write the file, the file is opened O_APPEND, and each write operation less than 4k.


reference

https://blog.csdn.net/wslyk606/article/details/81670713

Guess you like

Origin www.cnblogs.com/Hollson/p/12169224.html