乐趣区

关于gin: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(中间件名称) 即可。
  • 输入的成果:

    {"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 middleware

import (
    "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… 两篇文章,非原创。

退出移动版