go日志记录logrus

617 阅读2分钟

在项目开发的时候日志记录必不可少,logrus使用灵活,可移植性高

package main

import (
	"fmt"
	"io"
	"os"

	log "github.com/sirupsen/logrus"
)

func main() {

	// Log 为JSON而不是默认的ASCII格式。

	log.SetFormatter(&log.JSONFormatter{})

	// 仅记录严重警告以上。

	log.SetLevel(log.InfoLevel)

	f, err := os.OpenFile("./test.log", os.O_CREATE|os.O_RDWR|os.O_APPEND, os.ModeAppend|os.ModePerm)
	if err != nil {
		fmt.Println(err)
		return
	}
	// 输出到标准输出,而不是默认的标准错误

	//可以是任何io.Writer,请参阅下面的文件例如日志。

	rw := io.MultiWriter(f, os.Stdout)

	log.SetOutput(rw)

	log.WithFields(log.Fields{

		"animal": "walrus",
		"baibai": "拜拜",
	}).Info("A walrus appears")

	// log.WithFields(log.Fields{

	// 	"animal": "walrus",

	// 	"size": 10,
	// }).Info("A group of walrus emerges from the ocean")

	// log.WithFields(log.Fields{

	// 	"omg": true,

	// 	"number": 122,
	// }).Warn("The group's number increased tremendously!")

	// -------------------------------------
        // Fatal()会使整个进程退出
        // log.WithFields(log.Fields{

	// 	"omg": true,

	// 	"number": 100,
	// }).Fatal("The ice breaks!")

	// 一种常见的模式是通过重用

	//从WithFields返回的logrus.Entry 来重用日志记录语句之间的字段

	contextLogger := log.WithFields(log.Fields{

		"common": "this is a common field",

		"other": "I also should be logged always",
	})

	contextLogger.Info("I'll be logged with common and other field")

	contextLogger.Info("Me too")

}

输出

{"animal":"walrus","baibai":"拜拜","level":"info","msg":"A walrus appears","time":"2022-03-29T15:57:30+08:00"}
{"common":"this is a common field","level":"info","msg":"I'll be logged with common and other field","other":"I also should be logged always","time":"2022-03-29T15:57:30+08:00"}
{"common":"this is a common field","level":"info","msg":"Me too","other":"I also should be logged always","time":"2022-03-29T15:57:30+08:00"}

推荐的使用模式例如,您可能希望始终在请求的上下文中记录 request_id和user_ip。无需log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip})在每一行上都写 ,而是可以创建一个logrus.Entry传递:

log.WithFields(log.Fields{

  "event": event,

  "topic": topic,

  "key": key,

}).Fatal("Failed to send event")

requestLogger := log.WithFields(log.Fields{"request_id": request_id, "user_ip": user_ip})

requestLogger.Info("something happened on that request") # will log request_id and user_ip

requestLogger.Warn("something not great happened")

可以记录服务相关信息

    func SetUp() gin.HandlerFunc {
        return func(c *gin.Context) {
            requestId := c.Request.Header.Get("X-Request-Id")
            if requestId == "" {
                requestId = util.GenUUID()
            }
            // 可以把这个id记录到日志中
            c.Set("X-Request-Id", requestId)
            c.Writer.Header().Set("X-Request-Id", requestId)
            c.Next()
        }
    }

gin路由中间件

    package logger
    

  import (
	"bytes"
	"encoding/json"
	"fmt"
	"go-gin-api/app/config"
	"go-gin-api/app/util"
	"log"
	"os"

	"github.com/gin-gonic/gin"
)

type bodyLogWriter struct {
	gin.ResponseWriter
	body *bytes.Buffer
}

func (w bodyLogWriter) Write(b []byte) (int, error) {
	w.body.Write(b)
	return w.ResponseWriter.Write(b)
}
func (w bodyLogWriter) WriteString(s string) (int, error) {
	w.body.WriteString(s)
	return w.ResponseWriter.WriteString(s)
}

func SetUp() gin.HandlerFunc {
	return func(c *gin.Context) {
		bodyLogWriter := &bodyLogWriter{body: bytes.NewBufferString(""), ResponseWriter: c.Writer}
		c.Writer = bodyLogWriter

		//开始时间
		startTime := util.GetCurrentMilliTime()

		//处理请求
		c.Next()

		responseBody := bodyLogWriter.body.String()

		var responseCode int
		var responseMsg string
		var responseData interface{}

		if responseBody != "" {
			response := util.Response{}
			err := json.Unmarshal([]byte(responseBody), &response)
			if err == nil {
				responseCode = response.Code
				responseMsg = response.Message
				responseData = response.Data
			}
		}

		//结束时间
		endTime := util.GetCurrentMilliTime()

		if c.Request.Method == "POST" {
			c.Request.ParseForm()
		}

		//日志格式
		accessLogMap := make(map[string]interface{})

		accessLogMap["request_time"] = startTime
		accessLogMap["request_method"] = c.Request.Method
		accessLogMap["request_uri"] = c.Request.RequestURI
		accessLogMap["request_proto"] = c.Request.Proto
		accessLogMap["request_ua"] = c.Request.UserAgent()
		accessLogMap["request_referer"] = c.Request.Referer()
		accessLogMap["request_post_data"] = c.Request.PostForm.Encode()
		accessLogMap["request_client_ip"] = c.ClientIP()

		accessLogMap["response_time"] = endTime
		accessLogMap["response_code"] = responseCode
		accessLogMap["response_msg"] = responseMsg
		accessLogMap["response_data"] = responseData

		accessLogMap["cost_time"] = fmt.Sprintf("%vms", endTime-startTime)

		accessLogJson, _ := util.JsonEncode(accessLogMap)

		if f, err := os.OpenFile(config.AppAccessLogName, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666); err != nil {
			log.Println(err)
		} else {
			f.WriteString(accessLogJson + "\n")
		}
	}
}

依赖包

package util


import "github.com/gin-gonic/gin"


type Gin struct {
    Ctx *gin.Context
}`


type response struct {
     Code int `json:"code"` 
     Message string `json:"msg"` 
     Data interface{} `json:"data"` 
}


func (g *Gin)Response(code int, msg string, data interface{}) {
    g.Ctx.JSON(200, response{
        Code : code,
        Message : msg,
        Data : data,
    })
    return
}