一,安装zap
$ go get -u go.uber.org/zap
go: downloading go.uber.org/zap v1.27.0
go: downloading go.uber.org/multierr v1.10.0
go: downloading go.uber.org/multierr v1.11.0
go: added go.uber.org/multierr v1.11.0
go: added go.uber.org/zap v1.27.0
二,测试一个例子:
//得到列表
func (ic *ImageController) List(c *gin.Context) {//logger := zap.NewExample()cfg := zap.NewProductionConfig()cfg.OutputPaths = []string{"/data/gologs/logs/access.log",//"stderr","stdout",}logger,err := cfg.Build()if err!=nil {fmt.Println("日志启动出错:",err.Error())return}defer logger.Sync()timeStr := time.Now().Format("2006-01-02 15:04:05")logger.Info("记录一条日志",zap.String("time", timeStr),zap.String("url", c.Request.URL.String()),)c.JSON(http.StatusOK, gin.H{"message": "image list",})
}
输出例子:
{"level":"info","ts":1738244531.3267372,"caller":"controller/ImageController.go:54","msg":"记录一条日志","time":"2025-01-30 21:42:11","url":"/image/list?a=1&bc=2"}
三,记录访问日志
package middlewareimport ("bytes""fmt""github.com/gin-gonic/gin""go.uber.org/zap""imagebank/global""io""time"
)type responseWriter struct {gin.ResponseWriterb *bytes.Buffer
}//重写 Write([]byte) (int, error) 方法
func(w responseWriter)Write(b []byte)(int, error) {//向一个bytes.buffer中写一份数据来为获取body使用w.b.Write(b)//完成gin.Context.Writer.Write()原有功能return w.ResponseWriter.Write(b)
}func AccessLog() gin.HandlerFunc {return func(c *gin.Context) {//请求 headerrequestHeader := c.Request.HeaderrequestHeaderStr:=fmt.Sprintf("%v",requestHeader)fmt.Println("请求头:",requestHeaderStr)//请求体 bodyrequestBody := ""b, err := c.GetRawData()if err != nil {requestBody = "failed to get request body"} else {requestBody = string(b)}c.Request.Body = io.NopCloser(bytes.NewBuffer(b))fmt.Println("请求体:",requestBody)writer := responseWriter{c.Writer,bytes.NewBuffer([]byte{}),}c.Writer = writerbeginTime := time.Now().UnixNano()c.Next()endTime := time.Now().UnixNano()duration:=endTime-beginTimecfg := zap.NewProductionConfig()cfg.OutputPaths = []string{"/data/gologs/logs/access.log",//"stderr","stdout",}logger,err := cfg.Build()if err!=nil {fmt.Println("日志启动出错:",err.Error())return}defer logger.Sync()timeStr := time.Now().Format("2006-01-02 15:04:05")//响应状态码responseStatus := c.Writer.Status()//响应 headerresponseHeader := c.Writer.Header()responseHeaderStr := fmt.Sprintf("%v",responseHeader)//响应体大小responseBodySize := c.Writer.Size()//响应体 bodyresponseBody := writer.b.String()logger.Info("记录一条日志",zap.String("time", timeStr),zap.String("ip", c.ClientIP()),zap.String("proto", c.Request.Proto),zap.String("method", c.Request.Method),zap.String("host", c.Request.Host),zap.String("url", c.Request.URL.String()),zap.String("get_params", global.GetAllGetParams(c)),zap.String("post_params", global.GetAllPostParams(c)),zap.String("UserAgent", c.Request.UserAgent()),//请求头,请求体zap.String("requestHeader", requestHeaderStr),zap.String("requestBody", requestBody),//响应头、响应体zap.Int("responseStatus", responseStatus),zap.String("responseHeader", responseHeaderStr),zap.Int("responseBodySize", responseBodySize),zap.String("responseBody", responseBody),//时长,微秒zap.Int64("duration", duration/1000),)}
}
四,测试效果:
{"level":"info","ts":1738288864.7150245,"caller":"middleware/accesslog.go:122","msg":"记录一条日志","time":"2025-01-31 10:01:04","ip":"192.168.219.1","proto":"HTTP/1.1","method":"GET","host":"192.168.219.3:8080","url":"/image/list?a=1&bc=2","get_params":"key:a,value:1\nkey:bc,value:2\n","post_params":"","UserAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36","requestHeader":"map[Accept:[text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7] Accept-Encoding:[gzip, deflate] Accept-Language:[zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,ja;q=0.6] Cache-Control:[max-age=0] Connection:[keep-alive] Cookie:[PHPSID=e239cbb4d5ddd941f501d2d3a9cca3d5] Upgrade-Insecure-Requests:[1] User-Agent:[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36]]","requestBody":"","responseStatus":200,"responseHeader":"map[Content-Type:[application/json; charset=utf-8]]","responseBodySize":24,"responseBody":"{\"message\":\"image list\"}","duration":42}