优化日志记录中间件

This commit is contained in:
白茶清欢 2023-12-29 16:02:39 +08:00
parent 4dc70ee96b
commit 80ce64f8e1

View File

@ -17,17 +17,14 @@ import (
"go.uber.org/zap" "go.uber.org/zap"
) )
// Access 记录请求日志 // fillCfg 填充默认配置
// //
// Author : go_developer@163.com<白茶清欢> // Author : go_developer@163.com<白茶清欢>
// //
// Date : 10:55 2022/7/14 // Date : 15:37 2023/12/29
func Access(cfg *AccessConfig) gin.HandlerFunc { func fillCfg(cfg *AccessConfig) {
// 未传入配置或者未传入日志实例 if nil == cfg {
if nil == cfg || nil == cfg.Logger { return
return func(ctx *gin.Context) {
ctx.Next()
}
} }
if nil == cfg.IsRecordLog { if nil == cfg.IsRecordLog {
cfg.IsRecordLog = defaultIsRecordLog cfg.IsRecordLog = defaultIsRecordLog
@ -36,12 +33,63 @@ func Access(cfg *AccessConfig) gin.HandlerFunc {
cfg.ExtraFieldList = make([]string, 0) cfg.ExtraFieldList = make([]string, 0)
} }
cfg.ExtraFieldList = append(cfg.ExtraFieldList, define.RecordRequestDataField, define.RecordResponseDataField) cfg.ExtraFieldList = append(cfg.ExtraFieldList, define.RecordRequestDataField, define.RecordResponseDataField)
}
// getLogRequestHeader 获取记录的请求header
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:59 2023/12/29
func getLogRequestHeader(ctx *gin.Context, cfg *AccessConfig) map[string][]string {
// 请求header
headerTable := make(map[string][]string)
if len(cfg.RequestHeaderList) == 0 {
// 全部记录
for headerKey, _ := range ctx.Request.Header {
cfg.RequestHeaderList = append(cfg.RequestHeaderList, headerKey)
}
}
for _, key := range cfg.RequestHeaderList {
headerTable[key] = ctx.Request.Header.Values(key)
}
return headerTable
}
// getLogResponseHeader 记录相应header
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:01 2023/12/29
func getLogResponseHeader(ctx *gin.Context, cfg *AccessConfig) map[string][]string {
// 响应header
responseHeaderTable := make(map[string][]string)
if len(cfg.ResponseHeaderList) == 0 {
// 全部记录
for headerKey, _ := range ctx.Writer.Header() {
cfg.ResponseHeaderList = append(cfg.ResponseHeaderList, headerKey)
}
zap.Any("pkg_gin_response_header", ctx.Writer.Header())
}
for _, key := range cfg.ResponseHeaderList {
responseHeaderTable[key] = ctx.Writer.Header().Values(key)
}
return responseHeaderTable
}
// Access 记录请求日志
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:55 2022/7/14
func Access(cfg *AccessConfig) gin.HandlerFunc {
fillCfg(cfg)
return func(ctx *gin.Context) { return func(ctx *gin.Context) {
// 未传入配置或者未传入日志实例
if nil == cfg || nil == cfg.Logger || !cfg.IsRecordLog(ctx) {
ctx.Next() ctx.Next()
if !cfg.IsRecordLog(ctx) {
// 不记录日志
return return
} }
ctx.Next()
startRequestTime := wrapper.OwnTime(ctx.GetTime(define.StartRequestTimeField)) startRequestTime := wrapper.OwnTime(ctx.GetTime(define.StartRequestTimeField))
logDataList := []zap.Field{ logDataList := []zap.Field{
// 开始请求时间 // 开始请求时间
@ -53,47 +101,27 @@ func Access(cfg *AccessConfig) gin.HandlerFunc {
logDataList, logDataList,
zap.Any(define.FinishRequestTimeField, startRequestTime.FormatUnixMilli()), zap.Any(define.FinishRequestTimeField, startRequestTime.FormatUnixMilli()),
zap.Int64("pkg_gin_request_cost", finishRequestTime.UnixMilli()-startRequestTime.UnixMilli()), zap.Int64("pkg_gin_request_cost", finishRequestTime.UnixMilli()-startRequestTime.UnixMilli()),
zap.Any("pkg_gin_request_header", getLogRequestHeader(ctx, cfg)),
zap.Any("pkg_gin_response_header", getLogResponseHeader(ctx, cfg)),
) )
// 请求header
if len(cfg.RequestHeaderList) == 0 {
// 全部记录
zap.Any("pkg_gin_request_header", ctx.Request.Header)
} else {
headerTable := make(map[string][]string, 0)
for _, key := range cfg.RequestHeaderList {
headerTable[key] = ctx.Request.Header.Values(key)
}
zap.Any("pkg_gin_request_header", headerTable)
}
// 响应header
if len(cfg.ResponseHeaderList) == 0 {
// 全部记录
zap.Any("pkg_gin_response_header", ctx.Writer.Header())
} else {
headerTable := make(map[string][]string, 0)
for _, key := range cfg.ResponseHeaderList {
headerTable[key] = ctx.Writer.Header().Values(key)
}
zap.Any("pkg_gin_response_header", headerTable)
}
// 扩展数据 // 扩展数据
for _, field := range cfg.ExtraFieldList { for _, field := range cfg.ExtraFieldList {
val, _ := ctx.Get(field) val, _ := ctx.Get(field)
logDataList = append(logDataList, zap.Any(field, val)) logDataList = append(logDataList, zap.Any(field, val))
} }
cfg.Logger.Info("请求日志记录", logDataList...) cfg.Logger.Info("请求日志记录", logDataList...)
if nil != cfg.FinishHook { if nil == cfg.FinishHook {
return
}
// hook 不为nil, 自动触发 // hook 不为nil, 自动触发
cfg.FinishHook( cfg.FinishHook(
ctx, ctx,
[]byte(ctx.GetString(define.RecordRequestDataField)), []byte(ctx.GetString(define.RecordRequestDataField)),
[]byte(ctx.GetString(define.RecordResponseDataField)), ctx.GetStringMap(define.RecordResponseDataField),
finishRequestTime.UnixMilli()-startRequestTime.UnixMilli(), finishRequestTime.UnixMilli()-startRequestTime.UnixMilli(),
) )
}
} }
} }
@ -108,7 +136,7 @@ type AccessConfig struct {
ResponseHeaderList []string // 要记录哪些响应header, 不传全部记录 ResponseHeaderList []string // 要记录哪些响应header, 不传全部记录
IsRecordLog func(ctx *gin.Context) bool // 验证当前请求是否记录日志 IsRecordLog func(ctx *gin.Context) bool // 验证当前请求是否记录日志
ExtraFieldList []string // 记录的扩展字段列表,请将相关数据使用 ctx.Set 写入上下文中, 日志会自动记录 ExtraFieldList []string // 记录的扩展字段列表,请将相关数据使用 ctx.Set 写入上下文中, 日志会自动记录
FinishHook func(ctx *gin.Context, requestData []byte, responseData []byte, cost int64) // 请求处理完成之后, 触发的hook函数 FinishHook func(ctx *gin.Context, requestData []byte, responseData map[string]interface{}, cost int64) // 请求处理完成之后, 触发的hook函数
} }
// defaultIsRecordLog 默认仅记录 json api 日志 // defaultIsRecordLog 默认仅记录 json api 日志