gin框架之日志的使用

在项目开发中,日志模块必不可少。Golang作为新兴的语言,第三方日志包也越来越多,其中star数最多的是logrus。云盘项目中使用的日志包就是logrus,下面就介绍一下该日志包的特性和使用方法。目前项目中使用的服务端框架是gin,日志就以gin中间件的方式来使用。
一、logrus特性:

  • 完全兼容golang标准库日志模块:logrus提供了6中日志级别:debug、info、warn、error、fatal和panic,这是golang标准日志模块的超集,需要注意的是:fatal直接调用的os.Exit(),来不及执行defer。
  • 可扩展的hook机制:允许使用者通过hook的方式将日志发送到任意的地方,如:本地文件系统、标准输出、logstash和elasticsearch或者mq等,也可以通过hook自定义日志的内容或格式。
  • 可选的日志输出格式:logrus内置两种日志格式:JSONFormatter和TextFormatter,如果这两种格式不满足需求,可以自己手动实现接口,定义日志的输出格式。
  • Field机制:logrus鼓励通过Field机制进行精细化和结构化的日志记录,而不是通过冗长的消息来记录日志。
二、基本使用
  • 写入文件:先从配置中获取到日志文件的路径和日志文件名,打开文件,以追加写的模式写入日志
    // 写入文件 f, err := os.OpenFile(fileName, os.O_WRONLY|os.O_APPEND, os.ModeAppend) if err != nil { fmt.Println("err", err) }

  • 创建实例、设置输出和日志输出级别
    // 实例化 logger := logrus.New() // 设置输出 logger.Out = f // 设置日志级别 logger.SetLevel(logrus.DebugLevel)

  • 设置rotatelogs
    // 设置rotatelogs和writeMap logWriter, _ := rotatelogs.New( // 分割后的文件名称 fileName+".%Y%m%d.log", // 生成软链,指向最新的日志文件 rotatelogs.WithLinkName(fileName), // 设置最长保存时间,这里设置成7天 rotatelogs.WithMaxAge(7*24*time.Hour), // 设置日志切割间隔时间,这里设置成1天 rotatelogs.WithRotationTime(24*time.Hour), ) writeMap := lfshook.WriterMap{ logrus.InfoLevel:logWriter, logrus.FatalLevel: logWriter, logrus.DebugLevel: logWriter, logrus.WarnLevel:logWriter, logrus.ErrorLevel: logWriter, logrus.PanicLevel: logWriter, }

  • 添加自定义的hook
    lfhook := lfshook.NewHook(writeMap, &logrus.JSONFormatter{ TimestampFormat: "2006-01-02 15:04:05", }) // 新增hook logger.AddHook(lfhook)

  • 设置日志输出的格式
    startTime := time.Now() // 处理请求 c.Next() endTime := time.Now() // 执行时间 latencyTime := endTime.Sub(startTime) // 请求方式 reqMethod := c.Request.Method // 请求路由 reqUrl := c.Request.URL // 状态码 statuCode := c.Writer.Status() // 请求IP clientIP := c.ClientIP() // 日志格式 logger.Infof("| %3d | %13v | %15s | %s | %s", statuCode, latencyTime, clientIP, reqMethod, reqUrl, )

  • 中间件的使用:直接在gin的router配置中使用router.use(中间件名称)即可。
  • 【gin框架之日志的使用】输出的效果:
    {"level":"info","msg":"| 200 |27.394785ms |127.0.0.1 | GET | /api/v1/token/folder/?user_id=1","time":"2021-09-04 16:06:09"} {"level":"info","msg":"| 200 |19.440787ms |127.0.0.1 | GET | /api/v1/token/trash/?user_id=1","time":"2021-09-04 16:06:09"} {"level":"info","msg":"| 200 |135.751439ms |127.0.0.1 | DELETE | /api/v1/token/trash/file?id=2\u0026type=1\u0026file_sha1=3dd360aadc76a400518e4084b9992024cdd10d9f\u0026user_id=1\u0026folder_id=1","time":"2021-09-04 16:06:11"} {"level":"info","msg":"| 200 |53.791428ms |127.0.0.1 | DELETE | /api/v1/token/trash/file?id=3\u0026type=0\u0026file_sha1=\u0026user_id=1\u0026folder_id=4","time":"2021-09-04 16:06:13"}

三、完整代码
package middlewareimport ( "file-store/utils" "fmt" "os" "path" "time""github.com/gin-gonic/gin" rotatelogs "github.com/lestrrat-go/file-rotatelogs" "github.com/rifflock/lfshook" "github.com/sirupsen/logrus" )// logrus: 日志到文件 func LoggerToFile() gin.HandlerFunc { logFilePath := utils.GlobalConfig.Log.FilePath logFileName := utils.GlobalConfig.Log.FileName // fileName拼接 fileName := path.Join(logFilePath, logFileName) // 写入文件 f, err := os.OpenFile(fileName, os.O_WRONLY|os.O_APPEND, os.ModeAppend) if err != nil { fmt.Println("err", err) } // 实例化 logger := logrus.New() // 设置输出 logger.Out = f // 设置日志级别 logger.SetLevel(logrus.DebugLevel) // 设置rotatelogs logWriter, _ := rotatelogs.New( // 分割后的文件名称 fileName+".%Y%m%d.log", // 生成软链,指向最新的日志文件 rotatelogs.WithLinkName(fileName), // 设置最长保存时间 rotatelogs.WithMaxAge(7*24*time.Hour), // 设置日志切割间隔时间 rotatelogs.WithRotationTime(24*time.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: "2006-01-02 15:04:05", }) // 新增hook logger.AddHook(lfhook)return func(c *gin.Context) { startTime := time.Now() // 处理请求 c.Next() endTime := time.Now() // 执行时间 latencyTime := endTime.Sub(startTime) // 请求方式 reqMethod := c.Request.Method // 请求路由 reqUrl := c.Request.URL // 状态码 statuCode := c.Writer.Status() // 请求IP clientIP := c.ClientIP() // 日志格式 logger.Infof("| %3d | %13v | %15s | %s | %s", statuCode, latencyTime, clientIP, reqMethod, reqUrl, ) } }

文章借鉴自: https://cloud.tencent.com/dev...和 https://www.cnblogs.com/it-33...两篇文章,非原创。

    推荐阅读