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)
		}
	}
}
相关推荐
任沫6 小时前
Agent之Function Call
javascript·人工智能·go
唐青枫14 小时前
别再把 interface 当万能盒子:Go 接口从隐式实现到项目解耦
go
tyung3 天前
Go 手写有界 SPSC 环形队列:无 CAS、无锁、Cache 友好的无锁模型
后端·go
喵个咪4 天前
技术复盘:基于 go-wind-cms 的官网+商城双业务渐进拆分实战
后端·架构·go
止语Lab4 天前
Go context 超时传播:你以为设了就安全了
go
何以解忧,唯有..4 天前
Go语言循环语句详解:for、range与循环控制
开发语言·算法·golang
踏着七彩祥云的小丑4 天前
Go学习第9天:并发编程 + 文件操作 + 正则表达式
学习·golang·正则表达式·go
JCGKS4 天前
Go `init` 函数:包初始化顺序到底是怎样的
golang·init·init执行顺序
何以解忧,唯有..4 天前
Go语言中的const:常量声明与iota枚举详解
java·开发语言·golang
止语Lab5 天前
Go 代码生成的三层认知:从忍住不用到自己造轮子
go