在项目开发的时候日志记录必不可少,logrus使用灵活,可移植性高
package main
import (
"fmt"
"io"
"os"
log "github.com/sirupsen/logrus"
)
func main() {
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
}
rw := io.MultiWriter(f, os.Stdout)
log.SetOutput(rw)
log.WithFields(log.Fields{
"animal": "walrus",
"baibai": "拜拜",
}).Info("A walrus appears")
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()
}
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
}