gin中logrus日志中间件的使用及日志分割实现

main.go

		...
		gin.SetMode(mode)
		engine := gin.New()
		engine.Use(gzip.Gzip(gzip.DefaultCompression))
		engine.Use(middlewares.Logger())
		...

loggerMiddleware.go

package middlewares

import (
	"fmt"
	"github.com/gin-gonic/gin"
	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
	"github.com/rifflock/lfshook"
	"github.com/sirupsen/logrus"
	"os"
	"time"
)

func Logger() gin.HandlerFunc {
	log := logrus.New()

	// 设置输出文件
	filePath := "logs/"
	fileName := ""
	//        打开指定处的文件,并指定权限为:可读可写,可创建
	file := filePath + fileName
	log.Out = os.Stdout

	// 设置日志级别。低于 Debug 级别的 Trace 将不会被打印
	log.SetLevel(logrus.DebugLevel)

	// 设置日志切割 rotatelogs
	writer, _ := rotatelogs.New(
		file+"%Y%m%d.log",
		//日志最大保存时间
		rotatelogs.WithMaxAge(7*24*time.Hour),
		设置日志切割时间间隔(1天)(隔多久分割一次)
		rotatelogs.WithRotationTime(24*time.Hour),
	)

	// lfshook 决定哪些日志级别可用日志分割
	writeMap := lfshook.WriterMap{
		logrus.PanicLevel: writer,
		logrus.FatalLevel: writer,
		logrus.ErrorLevel: writer,
		logrus.WarnLevel:  writer,
		logrus.InfoLevel:  writer,
		logrus.DebugLevel: writer,
	}

	// 配置 lfshook
	hook := lfshook.NewHook(writeMap, &logrus.JSONFormatter{
		// 设置日期格式
		TimestampFormat: "2006-01-02 15:04:05",
	})

	//为 logrus 实例添加自定义 hook
	log.AddHook(hook)
	return func(c *gin.Context) {
		// 一.配置所需的 Fields
		startTime := time.Now()
		c.Next()
		spendTime := time.Since(startTime).Milliseconds()
		ST := fmt.Sprintf("%d ms", spendTime) // 1.API 调用耗时
		//hostName, err := os.Hostname()        // 2.主机名
		//if err != nil {
		//	hostName = "unknown"
		//}
		statusCode := c.Writer.Status() // 3.状态码
		clientIP := c.ClientIP()        // 4.请求客户端的 IP
		//userAgent := c.Request.UserAgent() // 5.用户代理,通常是某个浏览器。dev环境下是apipost
		dataSize := c.Writer.Size() // 6.响应报文 body 的字节长度
		if dataSize < 0 {
			dataSize = 0
		}
		method := c.Request.Method   // 7.请求方法
		path := c.Request.RequestURI // 8.请求 URL

		// 二.从标准记录器创建一个条目,并向其中添加多个字段(隐式添加 log 本身的时间戳,信息等 fields )
		entry := log.WithFields(logrus.Fields{
			//"HostName":  hostName,
			"Status":    statusCode,
			"SpendTime": ST,
			"IP":        clientIP,
			//"UserAgent": userAgent,
			"Method": method,
			//"DataSize":  dataSize,
			"Path": path,
		})

		// Errors 保存了使用当前context的所有中间件/handler 所产生的全部错误信息。
		// 源码注释: Errors is a list of errors attached to all the handlers/middlewares who used this context.
		// 三.将系统内部的错误 log 出去
		if len(c.Errors) > 0 {
			log.Error(c.Errors.ByType(gin.ErrorTypePrivate).String())
		}

		// 四.根据状态码决定打印 log 的等级
		if statusCode >= 500 {
			entry.Error()
		} else if statusCode >= 400 {
			entry.Warn()
		} else {
			entry.Info()
		}
	}
}


你可能感兴趣的:(GoLang,golang)