gin自定义日志

gin的默认日志是只输出到终端,缺点:

1、日志没输出到文件

2、日志不分割

通过自定义日志

用自己写的yanglog库基于zap的高性能日志库,轻松实现(自定义配置也极其轻松):

1、日志默认输出到终端,并写到文件

2、按天轮转,超过单文件大小也轮转

3、旧的日志文件,自动压缩,更旧的文件自动删除

4、状态码400以下的写到info日志文件中,状态码大于等于400的同时写到info和error日志文件中

5、该日志方案除了可以写客户请求时的日志,也可以直接应用到内部函数调用时的日志输出

yanglog 的使用和配置,源码都很简单,请按需使用和修改。

直接上代码
go 复制代码
package main

import (
	"context"
	"fmt"
	"time"

	logger "gitee.com/xiaoshanyangcode/yanglog"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

func main() {
	// 配置日志
	ctx, cancel := context.WithCancel(context.Background())
	logconf := logger.LogConf{}
	log := logger.NewLogger(ctx, logconf)
	defer log.Sync()
	defer cancel()

	// 生产gin对象
	r := Default(log)

	// 正常gin的用法
	r.GET("/ce", func(c *gin.Context) {
		// 取值
		req := "123"
		fmt.Println("request:", req)
		// 页面接收
		c.JSON(200, gin.H{"request": req})
	})

	r.Run()
}

// 提供gin的Default函数,把日志改为我们自定义的
func Default(log *zap.SugaredLogger) *gin.Engine {
	engine := gin.New()
	// 使用自己的日志模块和默认的recovery
	engine.Use(LoggerWithConfig(log), gin.Recovery())
	return engine
}

// 自定义日志函数
func LoggerWithConfig(log *zap.SugaredLogger) gin.HandlerFunc {
	return func(c *gin.Context) {
		// Start timer
		start := time.Now()
		path := c.Request.URL.Path
		raw := c.Request.URL.RawQuery

		// Process request
		c.Next()

		param := gin.LogFormatterParams{
			Request: c.Request,
			Keys:    c.Keys,
		}

		// Stop timer
		param.TimeStamp = time.Now()
		param.Latency = param.TimeStamp.Sub(start)

		param.ClientIP = c.ClientIP()
		param.Method = c.Request.Method
		param.StatusCode = c.Writer.Status()
		param.ErrorMessage = c.Errors.ByType(gin.ErrorTypePrivate).String()

		param.BodySize = c.Writer.Size()
		if raw != "" {
			path = path + "?" + raw
		}

		param.Path = path
		// 根据不同的状态码,设置不同的日志等级
		if param.StatusCode < 400 {
			log.Infow(param.ErrorMessage, "code", param.StatusCode, "client", param.ClientIP, "method", param.Method, "path", param.Path, "size", param.BodySize, "duration", param.Latency)
		} else {
			log.Errorw(param.ErrorMessage, "code", param.StatusCode, "client", param.ClientIP, "method", param.Method, "path", param.Path, "size", param.BodySize, "duration", param.Latency)
		}
	}
}
相关推荐
不会敲代码11 小时前
从零开始学 Go:协程并发与 Web 开发初探
go
扉页的墨2 小时前
Wails v2 实战:用 Go 写桌面应用,从 0 到 1 构建一个本地笔记工具
go
ALex_zry3 小时前
go-zero Redis缓存封装与Model层设计
redis·缓存·golang·气象
我叫黑大帅3 小时前
从零实现一个完整 RAG 系统:基于 Eino 框架的检索增强生成实战
后端·面试·go
XMYX-018 小时前
17 - Go 通道 Channel 底层原理 + 实战详解
开发语言·golang
不会写DN1 天前
通过eino-ext如何正常indexer RAG?
网络·面试·go
donecoding1 天前
遗嘱、水管与抢救室:TS 切入 Go 的流程控制、接口与并发
javascript·typescript·go
Tomhex1 天前
Go调用C代码的场景与实践
golang
扉页的墨1 天前
Go 协程泄漏排查实战:我是如何把线上内存从 500MB 压到 20MB 的
go
donecoding1 天前
对象模型与内存的“钥匙理论”:TS 切入的 Go 的结构体与指针
javascript·typescript·go