Implementation of Golang logrus log package and log cutting

  • 2020-10-07 18:44:44
  • OfStack

This article mainly introduces the best logging solution in Golang, including the basic use of common log package logrus, how to combine file-ES4en package to achieve the rotary cutting of log files two topics.

Golang there are many packages available for logging processing. The standard library provides fewer log packages, which do not support precise control at the log level, custom adding log fields, and so on. Among the many log packages, it is recommended to use the third party logrus package, which is fully compatible with the native log package. logrus is the largest number of star log libraries on Github. logrus is powerful, highly efficient, and highly flexible, providing the functionality of custom plug-ins.

Many open source projects, such as docker, prometheus, dejavuzhou/ginbro, use logrus for their logging.

logrus features

Fully compatible with golang Standard library log module: logrus has six log levels: debug, info, warn, error, fatal and panic, which is the superset of API of golang Standard Library log module. logrus. Debug (" Useful debugging information. ") logrus. Info (" Something noteworthy happened!" ) logrus.Warn(" You should probably a look at this ") logrus.Error(" Something failed but I m not ") logrus. Fatal(" Bye. ") //log is followed by os. Exit(1) logrus. Panic(" I'm bailing. ") //log panic() Extensible Hook mechanism: Allows users to distribute logs anywhere via hook, such as local file system, standard output, logstash, elasticsearch, or mq, or to define log content and format via hook. Optional log output formats: logrus has two built-in log formats, JSONFormatter and TextFormatter. If these two formats do not meet the requirements, you can implement the interface Formatter to define your own log format. Field mechanism: logrus encourages fine-grained, structured logging through the Field mechanism instead of logging through verbose messages. logrus is a pluggable, structured log framework. Entry: ES93en. WithFields automatically returns 1 *Entry. Some variables in Entry are automatically added time: The timestamp when entry was created msg: Added when calling methods such as.Info () level, current log level

logrus basic use


package main

import (
  "os"

  "github.com/sirupsen/logrus"
  log "github.com/sirupsen/logrus"
)

var logger *logrus.Entry

func init() {
  //  Set the log format to json format 
  log.SetFormatter(&log.JSONFormatter{})
  log.SetOutput(os.Stdout)
  log.SetLevel(log.InfoLevel)
  logger = log.WithFields(log.Fields{"request_id": "123444", "user_ip": "127.0.0.1"})
}

func main() {
  logger.Info("hello, logrus....")
  logger.Info("hello, logrus1....")
  // 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!")
}

Log cutting based on logrus and file-ES110en packages

Many times application will log output to the file system, for highly trafficked application log automatic rotary cutting management is a very important problem, if the application cannot properly handle the log management, then can bring a lot of unnecessary maintenance overhead: external tool cutting logs, manually from the log to ensure that will not play the full disk.

[

file-rotatelogs: When you integrate this to to you app, it automatically write to logs that are rotated from within the app: No more disk-full alerts because you forgot to setup logrotate!

]

logrus itself does not support log rotary cutting function, which needs to be implemented in conjunction with file-ES123en package to prevent the log from filling up the disk. file-Writer realizes the ES126en.ES127en interface, and provides the function of cutting files. In fact, the example can be used as the target output of logrus, and the two can be seamlessly integrated, which is also the original intention of file-ES130en:

[

It's normally expected that this library is used with some other logging service, such as the built-in log library, or loggers such as github.com/lestrrat-go/apache-logformat.

]

Sample code:

Application log files/Users/opensource/test/go log, every 1 minute cycle a new file, keep the last three minutes of the log file, redundant automatically clean up.


package main

import (
 "time"

 rotatelogs "github.com/lestrrat-go/file-rotatelogs"
 log "github.com/sirupsen/logrus"
)

func init() {
 path := "/Users/opensource/test/go.log"
 /*  Log rotation correlation function 
 `WithLinkName`  Establish a soft connection for the latest logs 
 `WithRotationTime`  Set the time and how often the log splits 1 time 
 WithMaxAge  and  WithRotationCount2 Can only set 1 a 
  `WithMaxAge`  Sets the maximum save time for files before cleaning 
  `WithRotationCount`  Sets the maximum number of files to save before cleaning 
 */
 //  The following configuration logs every interval  1  Minutes rotation 1 Three new files, keep the latest  3  Minutes of log files, excess is automatically cleaned up. 
 writer, _ := rotatelogs.New(
 path+".%Y%m%d%H%M",
 rotatelogs.WithLinkName(path),
 rotatelogs.WithMaxAge(time.Duration(180)*time.Second),
 rotatelogs.WithRotationTime(time.Duration(60)*time.Second),
 )
 log.SetOutput(writer)
 //log.SetFormatter(&log.JSONFormatter{})
}

func main() {
 for {
 log.Info("hello, world!")
 time.Sleep(time.Duration(2) * time.Second)
 }
}

Golang standard log library log is used

Although the Golang standard log library has few functions, it can be optionally understood. The following is a simple code example for basic use:


package main

import (
  "fmt"
  "log"
)

func init() {
  log.SetPrefix(" 【 UserCenter 】 ")              //  Set the prefix for each row of logs 
  log.SetFlags(log.LstdFlags | log.Lshortfile | log.LUTC) //  Set the header field for the log 
}

func main() {
  log.Println("log...")
  log.Fatalln("Fatal Error...")
  fmt.Println("Not print!")
}

Custom log output


package main

import (
  "io"
  "log"
  "os"
)

var (
  Info  *log.Logger
  Warning *log.Logger
  Error  *log.Logger
)

func init() {
  errFile, err := os.OpenFile("errors.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
  if err != nil {
    log.Fatalln(" Failed to open log file: ", err)
  }

  Info = log.New(os.Stdout, "Info:", log.Ldate|log.Ltime|log.Lshortfile)
  Warning = log.New(os.Stdout, "Warning:", log.Ldate|log.Ltime|log.Lshortfile)
  Error = log.New(io.MultiWriter(os.Stderr, errFile), "Error:", log.Ldate|log.Ltime|log.Lshortfile)
}

func main() {
  Info.Println("Info log...")
  Warning.Printf("Warning log...")
  Error.Println("Error log...")
}

The related documents

https://mojotv.cn/2018/12/27/golang-logrus-tutorial
https://github.com/lestrrat-go/file-rotatelogs
https://www.flysnow.org/2017/05/06/go-in-action-go-log.html


Related articles: