An overview of the
The previous article shared the routing configuration of the Gin framework, and this one shares the logging.
Check a lot of information, most of all, Go logging with github.com/sirupsen/logrus.
Logrus is a structured logger for Go (golang), completely API compatible with the standard library logger.
Logs from the Gin framework are only exported to the console by default. We use Logrus to encapsulate middleware and log to a file.
This article is about learning and using Logrus.
Log format
For example, we agree that the log format is Text and contains the following fields:
Request time, log level, status code, execution time, request IP, request mode, and request route.
Next, let’s implement it with Logrus.
Logrus use
Install in DEP mode.
Added to gopkg.toml file:
[[constraint]]
name = "github.com/sirupsen/logrus"
version = "1.4.2"
Copy the code
Import in a project:
import "github.com/sirupsen/logrus"
Copy the code
Execute on the project command line:
dep ensure
Copy the code
At this point, you will see the sirupsen directory in the vendor/github.com/ directory.
We are ready to use it. Before we use it, let’s make a plan and set this function as a middleware, such as Logger.go.
The log can be logged to File by defining a LoggerToFile method.
Logs can be logged to MongoDB and a LoggerToMongo method defined.
Logs can be logged to ES, defining a LoggerToES method.
Logs can be logged to MQ, defining a LoggerToMQ method.
.
This time we first realize the record to the file, the implementation of LoggerToFile method, other can be implemented according to their own needs.
The Logger middleware, once created, can be migrated and used in any other project.
Without further ado, just look at the code.
package middleware
import (
"fmt"
"ginDemo/config"
"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
"os"
"path"
"time") // Log to file func LoggerToFile() gin.handlerfunc {logFilePath := config.Log_FILE_PATH
logFileName := path.join (FileName := config.logFilePath, logFileName) / / write file SRC, err: = OS. The OpenFile (FileName, OS O_APPEND | OS. O_WRONLY, OS. ModeAppend)iferr ! = nil { fmt.Println("err". Logrus.new () // Set the output logger.out = SRC // Set the log level logrus.setLevel (logrus.debugLevel) // Set the log format logger.SetFormatter(&logrus.TextFormatter{})returnFunc (c *gin.Context) {// startTime startTime := time.now () // process request c.ext () // endTime endTime := time.now () // execute time LatencyTime := endtime. Sub(startTime) // Request mode reqMethod := c. request. Method // Request route reqUri := c. request.requesturi // StatusCode := c.wirit.status () // Request IP clientIP := c.clientip () // Log format logger.infof ("| %3d | %13v | %15s | %s | %s |", statusCode, latencyTime, clientIP, reqMethod, reqUri,)}} // Log to MongoDB func LoggerToMongo() gin.HandlerFunc {returnFunc (c * gin.context) {}} // Log to ES func LoggerToES() gin.handlerfunc {returnFunc (c * gin.context) {}} // Log to MQ func LoggerToMQ() gin.handlerFunc {return func(c *gin.Context) {
}
}
Copy the code
Log middleware is written, how to call?
Simply add in main.go:
Engine := gin.Default() // Add engine.use (middleware.loggertofile ()) after this lineCopy the code
Run it and look at the log:
time="2019-07-17T22:10:45+08:00" level=info msg="| | | 27.698 (including 200 s: : 1 | GET | / v1 / product/add? name=a&price=10 |"
time="2019-07-17T22:10:46+08:00" level=info msg="| | | 27.239 (including 200 s: : 1 | GET | / v1 / product/add? name=a&price=10 |"
Copy the code
thistime="2019-07-17T22:10:45+08:00"
This time format is not what we want, what should we do?
Time needs to be formatted, modify logger.setformatter
Logger.setformatter (&logrus.textFormatter {TimestampFormat:"The 2006-01-02 15:04:05",})Copy the code
Run the following command to look at the log again:
time="The 2019-07-17 22:15:57" level=info msg="| 200 | 185.027µs | ::1 | GET | /v1/product/add?name=a&price=10 |"
time="The 2019-07-17 22:15:58" level=info msg="| | | 56.989 (including 200 s: : 1 | GET | / v1 / product/add? name=a&price=10 |"
Copy the code
Time became normal.
I don’t like text format, I like JSON format, what do I do?
Logger.setformatter (& logrus.jsonformatter {TimestampFormat:"The 2006-01-02 15:04:05",})Copy the code
Run the following command to look at the log again:
{"level":"info"."msg":"| | | 24.78 (including 200 s: : 1 | GET | / v1 / product/add? name=a\u0026price=10 |"."time":"The 2019-07-17 22:23:55"}
{"level":"info"."msg":"| | | 26.946 (including 200 s: : 1 | GET | / v1 / product/add? name=a\u0026price=10 |"."time":"The 2019-07-17 22:23:56"}
Copy the code
MSG message too much, inconvenient to see, how to do?
Logger.withfields (logrus.fields {"status_code" : statusCode,
"latency_time" : latencyTime,
"client_ip" : clientIP,
"req_method" : reqMethod,
"req_uri" : reqUri,
}).Info()
Copy the code
Run the following command to look at the log again:
{"client_ip":: : "1"."latency_time": 26681,"level":"info"."msg":""."req_method":"GET"."req_uri":"/v1/product/add? name=a\u0026price=10"."status_code": 200,"time":"The 2019-07-17 22:37:54"}
{"client_ip":: : "1"."latency_time": 24315,"level":"info"."msg":""."req_method":"GET"."req_uri":"/v1/product/add? name=a\u0026price=10"."status_code": 200,"time":"The 2019-07-17 22:37:55"}
Copy the code
Time, MSG, and level are automatically added by logrus.
Does Logrus support output file names and line numbers?
Not supported, the author replies that it is too performance intensive.
However, there are some people on the Internet who have implemented it by Hook. When you choose to use it in the production environment, remember to do performance testing.
Does Logrus support log splitting?
Not supported, but there are ways to implement it.
1. Linux Logrotate can be used for unified operation and maintenance processing.
2. It can be implemented using file-rotatelogs.
Need to import packages:
github.com/lestrrat-go/file-rotatelogs
github.com/rifflock/lfshook
Send the full code:
package middleware
import (
"fmt"
"ginDemo/config"
"github.com/gin-gonic/gin"
rotatelogs "github.com/lestrrat-go/file-rotatelogs"
"github.com/rifflock/lfshook"
"github.com/sirupsen/logrus"
"os"
"path"
"time") // Log to file func LoggerToFile() gin.handlerfunc {logFilePath := config.Log_FILE_PATH
logFileName := path.join (FileName := config.logFilePath, logFileName) / / write file SRC, err: = OS. The OpenFile (FileName, OS O_APPEND | OS. O_WRONLY, OS. ModeAppend)iferr ! = nil { fmt.Println("err". Logrus.new () // Set the output logger.out = SRC // Set the log level logrus.setLevel (logrus.debugLevel) // Set rotatelogslogWriter, err := rotatelogs.New(// Name of the split file fileName +".%Y%m%d.log", // generate a soft chain, Rotatelogs. WithLinkName(fileName), rotatelogs.WithMaxAge(7*24* time.hour), / / set log cutting time interval (1 day) rotatelogs. WithRotationTime (24 * time. The Hour),) writeMap: = lfshook. WriterMap {logrus. InfoLevel:logWriter,
logrus.FatalLevel: logWriter,
logrus.DebugLevel: logWriter,
logrus.WarnLevel: logWriter,
logrus.ErrorLevel: logWriter,
logrus.PanicLevel: logWriter,
}
lfHook := lfshook.NewHook(writeMap, &logrus.JSONFormatter{
TimestampFormat:"The 2006-01-02 15:04:05"}) // AddHook logger.addhook (lfHook)returnFunc (c *gin.Context) {// startTime startTime := time.now () // process request c.ext () // endTime endTime := time.now () // execute time LatencyTime := endtime. Sub(startTime) // Request mode reqMethod := c. request. Method // Request route reqUri := c. request.requesturi // StatusCode := c.wirit.status () // Request IP clientIP := c.clientip () // Log format logger.withFields (logrus.fields {"status_code" : statusCode,
"latency_time" : latencyTime,
"client_ip" : clientIP,
"req_method" : reqMethod,
"req_uri": reqUri,}).info ()}} // Log to MongoDB func LoggerToMongo() gin.HandlerFunc {returnFunc (c * gin.context) {}} // Log to ES func LoggerToES() gin.handlerfunc {returnFunc (c * gin.context) {}} // Log to MQ func LoggerToMQ() gin.handlerFunc {return func(c *gin.Context) {
}
}
Copy the code
In this case, a new file system.log.20190717.log is generated. The log content is in the same format as the preceding file.
Finally, logrus has many extendable hooks, which you can find online.
Some readers suggested updating the code to GitHub because it was inconvenient to see it on mobile.
It has been updated to the following address:
Github.com/xinliangnot…
Recommended reading
Gin framework
- Gin framework – Data binding and validation
- Gin framework – Use Logrus logging
- Gin framework – Installation and routing configuration
Based on article
- Go – function
- Go – cycle
- Go-map collection
- Go-struct structure
- Go-slice Slice
- Go – array
- Go – Variable declaration
- Go-environment installation
This article is welcome to forward, forward please indicate the author and source, thank you!