Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Zap receives the default logs of the gin framework and configures the method of log archiving

2025-04-02 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)05/31 Report--

Most people do not understand the knowledge points of this article "zap receives the default logs of the gin framework and configures the log archiving method", so the editor summarizes the following contents, detailed contents, clear steps, and has a certain reference value. I hope you can get something after reading this article. Let's take a look at this article "zap receives the default logs of the gin framework and configures the log archiving method".

Gin default middleware

First, let's look at one of the simplest gin projects:

Func main () {r: = gin.Default () r.GET ("/ hello", func (c * gin.Context) {c.String ("hello liwenzhou.com!")}) r.Run (}

Let's take a look at the source code of gin.Default ():

Func Default () * Engine {debugPrintWARNINGDefault () engine: = New () engine.Use (Logger (), Recovery () return engine}

That is, when we use gin.Default (), we use the two default middleware Logger () and Recovery () within the gin framework.

Among them, Logger () outputs the logs of the gin framework to standard output (the logs output at the terminal during our local development and debugging are its work), while Recovery () restores the scene and writes 500 responses when the program appears panic.

Middleware based on zap

We can mimic the implementation of Logger () and Recovery () and use our log library to receive logs from the default output of the gin framework.

Taking zap as an example, we implement two middleware as follows:

/ / GinLogger receives gin framework default log func GinLogger (logger * zap.Logger) gin.HandlerFunc {return func (c * gin.Context) {start: = time.Now () path: = c.Request.URL.Path query: = c.Request.URL.RawQuery c.Next () cost: = time.Since (start) ) logger.Info (path Zap.Int ("status", c.Writer.Status ()), zap.String ("method", c.Request.Method), zap.String ("path", path), zap.String ("query", query), zap.String ("ip", c.ClientIP ()) Zap.String ("user-agent", c.Request.UserAgent ()), zap.String ("errors", c.Errors.ByType (gin.ErrorTypePrivate). String ()), zap.Duration ("cost", cost)}} / / GinRecovery recover the panicfunc GinRecovery that may appear in the project (logger * zap.Logger) Stack bool) gin.HandlerFunc {return func (c * gin.Context) {defer func () {if err: = recover () Err! = nil {/ / Check for a broken connection, as it is not really a / / condition that warrants a panic stack trace. Var brokenPipe bool if ne, ok: = err. (* net.OpError); ok {if se, ok: = ne.Err. (* os.SyscallError) Ok {if strings.Contains (strings.ToLower (se.Error ()), "broken pipe") | | strings.Contains (strings.ToLower (se.Error () "connection reset by peer") {brokenPipe = true} httpRequest _: = httputil.DumpRequest (c.Request, false) if brokenPipe {logger.Error (c.Request.URL.Path, zap.Any ("error", err) Zap.String ("request", string (httpRequest)), / / If the connection is dead, we can't write a status to it. C.Error (err. (error)) / / nolint: errcheck c.Abort () return} if stack {logger.Error ("[Recovery from panic]" Zap.Any (error, err), zap.String (request, string (httpRequest)), zap.String (stack, string (debug.Stack () )} else {logger.Error ("[Recovery from panic]", zap.Any ("error", err) Zap.String ("request", string (httpRequest)) )} c.AbortWithStatus (http.StatusInternalServerError)} () c.Next ()}}

If you don't want to implement it yourself, you can use https://github.com/gin-contrib/zap encapsulated by others on github.

In this way, we can use the two middleware we defined above to replace the default Logger () and Recovery () of the gin framework in the gin framework.

R: = gin.New () r.Use (GinLogger (), GinRecovery ()) uses zap in gin projects

Finally, we add the log cutting commonly used in our project. The complete version of logger.go code is as follows:

Package loggerimport ("gin_zap_demo/config", "net", "net/http", "net/http/httputil", "os", "runtime/debug", "strings", "time", "github.com/gin-gonic/gin", "github.com/natefinch/lumberjack", "go.uber.org/zap"go" .uber.org / zap/zapcore ") var lg * zap.Logger// InitLogger initializes Loggerfunc InitLogger (cfg * config.LogConfig) (err error) {writeSyncer: = getLogWriter (cfg.Filename) Cfg.MaxSize, cfg.MaxBackups, cfg.MaxAge) encoder: = getEncoder () var l = new (zapcore.Level) err = l.UnmarshalText ([] byte (cfg.Level)) if err! = nil {return} core: = zapcore.NewCore (encoder, writeSyncer, l) lg = zap.New (core) Zap.AddCaller () zap.ReplaceGlobals (lg) / / replace the global logger instance in the zap package Later in other packages, simply use the zap.L () call to return} func getEncoder () zapcore.Encoder {encoderConfig: = zap.NewProductionEncoderConfig () encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder encoderConfig.TimeKey = "time" encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder encoderConfig.EncodeDuration = zapcore.SecondsDurationEncoder encoderConfig.EncodeCaller = zapcore.ShortCallerEncoder return zapcore.NewJSONEncoder (encoderConfig)} func getLogWriter (filename string, maxSize, maxBackup) MaxAge int) zapcore.WriteSyncer {lumberJackLogger: = & lumberjack.Logger {Filename: filename, MaxSize: maxSize, MaxBackups: maxBackup, MaxAge: maxAge } return zapcore.AddSync (lumberJackLogger)} / / GinLogger receives gin framework default log func GinLogger () gin.HandlerFunc {return func (c * gin.Context) {start: = time.Now () path: = c.Request.URL.Path query: = c.Request.URL.RawQuery c.Next () Cost: = time.Since (start) lg.Info (path Zap.Int ("status", c.Writer.Status ()), zap.String ("method", c.Request.Method), zap.String ("path", path), zap.String ("query", query), zap.String ("ip", c.ClientIP ()) Zap.String ("user-agent", c.Request.UserAgent ()), zap.String ("errors", c.Errors.ByType (gin.ErrorTypePrivate). String ()), zap.Duration ("cost", cost)}} / / GinRecovery recover the panic that may appear in the project And use zap to record related logs func GinRecovery (stack bool) gin.HandlerFunc {return func (c * gin.Context) {defer func () {if err: = recover () Err! = nil {/ / Check for a broken connection, as it is not really a / / condition that warrants a panic stack trace. Var brokenPipe bool if ne, ok: = err. (* net.OpError); ok {if se, ok: = ne.Err. (* os.SyscallError) Ok {if strings.Contains (strings.ToLower (se.Error ()), "broken pipe") | | strings.Contains (strings.ToLower (se.Error () "connection reset by peer") {brokenPipe = true} httpRequest _: = httputil.DumpRequest (c.Request, false) if brokenPipe {lg.Error (c.Request.URL.Path, zap.Any ("error", err) Zap.String ("request", string (httpRequest)), / / If the connection is dead, we can't write a status to it. C.Error (err. (error)) / / nolint: errcheck c.Abort () return} if stack {lg.Error ("[Recovery from panic]" Zap.Any (error, err), zap.String (request, string (httpRequest)), zap.String (stack, string (debug.Stack () )} else {lg.Error ("[Recovery from panic]", zap.Any ("error", err) Zap.String ("request", string (httpRequest)) )} c.AbortWithStatus (http.StatusInternalServerError)} () c.Next ()}}

Then define the log-related configuration:

Type LogConfig struct {Level string `json: "level" `Filename string `json: "filename" `MaxSize int `json: "maxsize" `MaxAge int `json: "max_age" `MaxBackups int `json: "max_backups" `}

In the project, first load the configuration information from the configuration file, and then call logger.InitLogger (config.Conf.LogConfig) to complete the preliminary recognition of the logger instance. Among them, register our middleware through r.Use (logger.GinLogger (), logger.GinRecovery (true)) to use zap to receive the gin framework's own logs, and use the zap.L (). Xxx () method to record custom log information where needed in the project.

Package mainimport ("fmt"gin_zap_demo/config"gin_zap_demo/logger"net/http"os"go.uber.org/zap"github.com/gin-gonic/gin") func main () {/ / load config from config.json if len (os.Args) < 1 { Return} if err: = config.Init (os.Args [1]) Err! = nil {panic (err)} / / init logger if err: = logger.InitLogger (config.Conf.LogConfig) Err! = nil {fmt.Printf ("init logger failed, err:%v\ n", err) return} gin.SetMode (config.Conf.Mode) r: = gin.Default () / / register zap related middleware r.Use (logger.GinLogger (), logger.GinRecovery (true)) r.GET ("/ hello") Func (c * gin.Context) {/ / suppose you have some data to log (name = "q1mi" age = 18) / / log and use zap.Xxx (key) Val) record related fields zap.L () .Debug ("this is hello func", zap.String ("user", name), zap.Int ("age", age) c.String (http.StatusOK, "hello liwenzhou.com!")}) addr: = fmt.Sprintf (":% v") Config.Conf.Port) r.Run (addr)} above is the content of this article on "zap receives the default logs of the gin framework and configures the method of log archiving" I believe we all have a certain understanding. I hope the content shared by the editor will be helpful to you. If you want to know more about the relevant knowledge, please pay attention to the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 231

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report