Reference documents: https://liwenzhou.com/posts/Go/zap/
Whether it is the debugging stage of software development or the operation stage after the software goes online, logging has always been a very important link. We should also develop the good habit of recording logs in the program.
The log package built in Go language implements a simple log service. This paper introduces the basic use of the standard log library and the selection and use of the third log library.
The log package defines the logger type, which provides some methods to format the output. This package also provides a predefined "standard" logger, which can be used by calling the functions Print series (Print|Printf|Println), Fatal series (Fatal|fatalf|fataln), and Panic series (Panic|Panicf|Panicln). It is easier to use than creating a logger object by yourself.
For example, we can call the methods mentioned above directly through the log package like the following code. By default, they will print the log information to the terminal interface:
package main import ( "log" ) func main() { log.Println("This is a very common log.") v := "Very common" log.Printf("This is a%s journal.\n", v) log.Fatalln("This is a trigger fatal Log of.") log.Panicln("This is a trigger panic Log of.") }
Compile and execute the above code to get the following output:
2017/06/19 14:04:17 This is a very common log. 2017/06/19 14:04:17 This is a very common log. 2017/06/19 14:04:17 This is a trigger fatal Log of.
logger prints the date and time of each log information, and the default output to the standard error of the system. The Fatal series function will call os.Exit(1) after writing log information. The Panic series function will be panic after writing log information.
1.1 logger configuration
By default, the logger only provides the time information of the log, but in many cases, we want more information, such as the file name and line number of the log. The log standard library provides us with methods to customize these settings.
The Flags function in the log standard library returns the output configuration of the standard logger, and the SetFlags function is used to set the output configuration of the standard logger.
func Flags() int func SetFlags(flag int)
1.1.1 flag option
The log standard library provides the following flag options, which are a series of defined constants.
const ( // Controls the details of the output log information, not the order and format of the output. // The output log will be separated by a colon after each item: for example, 2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message Ldate = 1 << iota // Date: January 23, 2009 Ltime // Time: 01:23:23 Lmicroseconds // Microsecond time: 01:23:23.123123 (used to enhance Ltime bit) Llongfile // File full path name + line number: / a/b/c/d.go:23 Lshortfile // File name + line number: d.go:23 (Llongfile will be overwritten) LUTC // Use UTC time LstdFlags = Ldate | Ltime // Initial value of standard logger )
Let's set the output options of the standard logger before logging:
func main() { log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate) log.Println("This is a very common log.") }
The output results obtained after compilation and execution are as follows:
2017/06/19 14:05:17.494943 .../log_demo/main.go:11: This is a very common log.
1.1.2 configuring log prefixes
The log standard library also provides two methods for the prefix of log information:
func Prefix() string func SetPrefix(prefix string)
The Prefix function is used to view the output Prefix of the standard logger, and the SetPrefix function is used to set the output Prefix.
func main() { log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate) log.Println("This is a very common log.") log.SetPrefix("[princeling]") log.Println("This is a very common log.") }
The above code output is as follows:
[princeling]2017/06/19 14:05:57.940542 .../log_demo/main.go:13: This is a very common log.
In this way, we can add the specified prefix to our log information in the code to facilitate the retrieval and processing of log information later.
1.1.3 configure log output location
func SetOutput(w io.Writer)
The SetOutput function is used to set the output destination of the standard logger. The default is standard error output.
For example, the following code will output the log to the xx.log file in the same directory.
func main() { logFile, err := os.OpenFile("./xx.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) if err != nil { fmt.Println("open log file failed, err:", err) return } log.SetOutput(logFile) log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate) log.Println("This is a very common log.") log.SetPrefix("[princeling]") log.Println("This is a very common log.") }
If you want to use the standard logger, we usually write the above configuration operation to the init function.
func init() { logFile, err := os.OpenFile("./xx.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) if err != nil { fmt.Println("open log file failed, err:", err) return } log.SetOutput(logFile) log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate) }
1.2 create logger
The log standard library also provides a constructor - New for creating a New logger object, which enables us to create our own logger examples. The signature of the New function is as follows:
func New(out io.Writer, prefix string, flag int) *Logger
New creates a Logger object. The parameter out sets the destination where log information is written. The parameter prefix will be added in front of each generated log. The parameter flag defines the properties of the log (time, file, etc.).
for instance:
func main() { logger := log.New(os.Stdout, "<New>", log.Lshortfile|log.Ldate|log.Ltime) logger.Println("This is custom logger Log of records.") }
After compiling and executing the above code, the results are as follows:
<New>2017/06/19 14:06:51 main.go:34: This is custom logger Log of records.
2.1 sorting of log selection requirements
- Log write performance
- The log level is separated and can be separated into multiple log files
- Readability and structure. Json format may have separators to facilitate subsequent log collection and monitoring
- Be able to print basic information, such as calling file / function name and line number, log time, etc
- Log writing is friendly, and automatic log trace through context is supported
- For file cutting, the log can be split by hour and day, or by file size
- File scheduled deletion
- Open source, which is better supported than other open source frameworks
- Multi output - supports standard output, files, etc
2.2 log comparison
2.2.1 function comparison
Reference documents:
- https://www.jianshu.com/p/38a67ab593ee
- https://zhuanlan.zhihu.com/p/141321801
- zerolog: https://zhuanlan.zhihu.com/p/136296821
Among the many log frameworks searched, the last two are Uber open source Zap and ZeroLog, which have obvious good performance. Refer to the log references of open source projects in github and the log surrounding framework support, and finally select Zap.
Demand pointGo.uber.org/zap (there are many open source projects in China with good performance, which is recommended)github.com/rs/zerologLog write performancehigherhighLog level separationsupportsupportReadability (Json format or separator to facilitate subsequent log collection, monitoring, etc.)json formatjson formatEase of use: convenient access, convenient writing (formatting), Hook can be injected into trace_id, etcAutomatic access time, code information, log level, support HookIt can support access time, code information, log level, etc., and HookFile cutting (log splitting by time, file size)Not supported. It can be implemented through lumberjacksupportScheduled deletionsupportsupportMulti output - supports standard output, files, etcsupportsupport2.2.3 performance data comparison
According to the documentation of Uber go Zap, its performance is better than similar structured log packages - and faster than the standard library. The following is the benchmark information released by Zap
Record a message and 10 fields:
Record a static string without any context or printf style template:
In the next article, we will talk about the use of high-performance logging framework Zap and how to meet our rich use needs of logging framework. See you next time, Peace 😘
I am Jian Fan, an inspirational migrant worker in the new era who aims to describe the most complex problems in the simplest language. If you have any doubts about this article, please leave a message in my WeChat official account. What I can do is to help you:
- Help build your own knowledge system
- Real high concurrency scenarios on the Internet
- Occasionally share classic scenarios and practices related to Golang and Java
My blog: https://besthpt.github.io/
My wechat: bestbear666
The official account of WeChat: