From b9c0389e7bb0380495970240309c67598a529313 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Fri, 26 Jul 2024 12:25:22 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8D=87=E7=BA=A7=E8=AF=B7=E6=B1=82=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E8=AE=B0=E5=BD=95=20+=20=E5=8D=87=E7=BA=A7=20request?= =?UTF-8?q?=20wrapperHandle=20+=20=E6=8B=86=E5=88=86after=20hook?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- middleware/access_log.go | 77 +++++++++++-------------------- middleware/hook_after_response.go | 38 +++++++++++++++ middleware/init_request.go | 2 +- request/wrapper.go | 11 ++++- response/response.go | 4 +- 5 files changed, 78 insertions(+), 54 deletions(-) create mode 100644 middleware/hook_after_response.go diff --git a/middleware/access_log.go b/middleware/access_log.go index d6a6c3a..4411b65 100644 --- a/middleware/access_log.go +++ b/middleware/access_log.go @@ -8,14 +8,15 @@ package middleware import ( + "git.zhangdeman.cn/zhangdeman/consts" + "git.zhangdeman.cn/zhangdeman/gin/request" + "go.uber.org/zap" "strings" - "git.zhangdeman.cn/zhangdeman/wrapper" - "git.zhangdeman.cn/zhangdeman/gin/define" + "git.zhangdeman.cn/zhangdeman/logger" "github.com/gin-gonic/gin" - "go.uber.org/zap" ) // fillCfg 填充默认配置 @@ -30,20 +31,12 @@ func fillCfg(cfg *AccessConfig) { if nil == cfg.IsRecordLog { cfg.IsRecordLog = defaultIsRecordLog } - if nil == cfg.ExtraFieldList { - cfg.ExtraFieldList = make([]string, 0) - } if nil == cfg.RequestHeaderList { cfg.RequestHeaderList = make([]string, 0) } if nil == cfg.ResponseHeaderList { cfg.ResponseHeaderList = make([]string, 0) } - if nil == cfg.ExtraFieldList { - cfg.ExtraFieldList = make([]string, 0) - } - handleConfig := define.GetHttpHandleConfig() - cfg.ExtraFieldList = append(cfg.ExtraFieldList, handleConfig.RecordRequestDataField, handleConfig.RecordResponseDataField) } // getLogRequestHeader 获取记录的请求header @@ -97,43 +90,31 @@ func LogRequest(cfg *AccessConfig) gin.HandlerFunc { handleConfig := define.GetHttpHandleConfig() return func(ctx *gin.Context) { // 未传入配置或者未传入日志实例 - if nil == cfg || nil == cfg.Logger || !cfg.IsRecordLog(ctx) { + if nil == cfg || nil == cfg.Logger || (nil != cfg.IsRecordLog && !cfg.IsRecordLog(ctx)) { ctx.Next() return } + startRequestTime := request.WrapperHandle.GetCtxIntData(ctx, handleConfig.StartRequestTimeField, 0) + // 记录请求日志 + logData := logger.NewLogData(ctx, consts.LogTypeRequest, "", map[string]any{ + handleConfig.StartRequestTimeField: startRequestTime, // 开始请求时间 + "request_header": getLogRequestHeader(ctx, cfg), // 请求header + "request_query": request.WrapperHandle.GetQuery(ctx), // 获取请求query + "request_body": request.WrapperHandle.GetRequestBody(ctx), // 请求body + }) + cfg.Logger.Info("接口请求日志记录", logger.ZapLogDataList(logData)...) ctx.Next() - startRequestTime := wrapper.OwnTime(ctx.GetTime(handleConfig.StartRequestTimeField)) - logDataList := []zap.Field{ - // 开始请求时间 - zap.Any(handleConfig.StartRequestTimeField, startRequestTime.FormatUnixMilli()), - } // 结束时间 - finishRequestTime := wrapper.OwnTime(ctx.GetTime(handleConfig.FinishRequestTimeField)) - logDataList = append( - logDataList, - zap.Any(handleConfig.FinishRequestTimeField, finishRequestTime.FormatUnixMilli()), // 请求完成时间 - zap.Int64("pkg_gin_request_cost", finishRequestTime.UnixMilli()-startRequestTime.UnixMilli()), // 接口耗时 - zap.Any("pkg_gin_request_header", getLogRequestHeader(ctx, cfg)), // 请求header - zap.Any("pkg_gin_response_header", getLogResponseHeader(ctx, cfg)), // 响应header - ) - - // 扩展数据 - for _, field := range cfg.ExtraFieldList { - val, _ := ctx.Get(field) - logDataList = append(logDataList, zap.Any(field, val)) - } - cfg.Logger.Info("请求日志记录", logDataList...) - if nil == cfg.FinishHook { - return - } - // hook 不为nil, 自动触发 - cfg.FinishHook( - ctx, - []byte(ctx.GetString(handleConfig.RecordRequestDataField)), - ctx.GetStringMap(handleConfig.RecordResponseDataField), - finishRequestTime.UnixMilli()-startRequestTime.UnixMilli(), - ) - + finishRequestTime := request.WrapperHandle.GetCtxIntData(ctx, handleConfig.FinishRequestTimeField, 0) + ctx.Set(handleConfig.FinishRequestTimeField, finishRequestTime) + // 记录相应日志 + logResponseData := logger.NewLogData(ctx, consts.LogTypeOutput, "", map[string]any{ + handleConfig.FinishRequestTimeField: finishRequestTime, // 完成请求时间 + "request_cost": finishRequestTime - startRequestTime, // 请求耗时 + "response_body": request.WrapperHandle.GetResponseBody(ctx, handleConfig.ResponseDataField, map[string]any{}), // 响应body + "response_header": getLogResponseHeader(ctx, cfg), // 响应header + }) + cfg.Logger.Info("接口响应日志记录", logger.ZapLogDataList(logResponseData)...) } } @@ -143,12 +124,10 @@ func LogRequest(cfg *AccessConfig) gin.HandlerFunc { // // Date : 11:26 2022/7/14 type AccessConfig struct { - Logger *zap.Logger // 日志实例 - RequestHeaderList []string // 要记录哪些header , 不传全部记录 - ResponseHeaderList []string // 要记录哪些响应header, 不传全部记录 - IsRecordLog func(ctx *gin.Context) bool // 验证当前请求是否记录日志 - ExtraFieldList []string // 记录的扩展字段列表,请将相关数据使用 ctx.Set 写入上下文中, 日志会自动记录 - FinishHook func(ctx *gin.Context, requestData []byte, responseData map[string]interface{}, cost int64) // 请求处理完成之后, 触发的hook函数 + Logger *zap.Logger // 日志实例 + RequestHeaderList []string // 要记录哪些header , 不传全部记录 + ResponseHeaderList []string // 要记录哪些响应header, 不传全部记录 + IsRecordLog func(ctx *gin.Context) bool // 验证当前请求是否记录日志 } // defaultIsRecordLog 默认仅记录 json api 日志 diff --git a/middleware/hook_after_response.go b/middleware/hook_after_response.go new file mode 100644 index 0000000..81a7d5c --- /dev/null +++ b/middleware/hook_after_response.go @@ -0,0 +1,38 @@ +// Package middleware ... +// +// Description : middleware ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2024-07-26 11:54 +package middleware + +import ( + "git.zhangdeman.cn/zhangdeman/gin/define" + "git.zhangdeman.cn/zhangdeman/gin/request" + "github.com/gin-gonic/gin" +) + +type HookFunc func(ctx *gin.Context, requestData []byte, responseData map[string]interface{}, cost int64) + +// HookAfterResponseMiddleware 请求最终处理完成之后执行的中间件 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 11:55 2024/7/26 +func HookAfterResponseMiddleware(ctx *gin.Context, hookFunc HookFunc) gin.HandlerFunc { + handleConfig := define.GetHttpHandleConfig() + return func(ctx *gin.Context) { + ctx.Next() + if nil == hookFunc { + return + } + // hook 不为nil, 自动触发 + hookFunc( + ctx, + []byte(ctx.GetString(handleConfig.RecordRequestDataField)), + ctx.GetStringMap(handleConfig.RecordResponseDataField), + request.WrapperHandle.GetCtxIntData(ctx, handleConfig.StartRequestTimeField, 0)-request.WrapperHandle.GetCtxIntData(ctx, handleConfig.StartRequestTimeField, 0), + ) + } +} diff --git a/middleware/init_request.go b/middleware/init_request.go index 4645eca..61bb406 100644 --- a/middleware/init_request.go +++ b/middleware/init_request.go @@ -32,7 +32,7 @@ func InitRequest() gin.HandlerFunc { requestID := getRequestID(ctx, traceID) ctx.Set(httpHandleConfig.TraceIDField, traceID) ctx.Set(httpHandleConfig.RequestIDField, requestID) - ctx.Set(httpHandleConfig.StartRequestTimeField, time.Now()) + ctx.Set(httpHandleConfig.StartRequestTimeField, time.Now().UnixMilli()) ctx.Next() } } diff --git a/request/wrapper.go b/request/wrapper.go index 689f1e1..67d6dd4 100644 --- a/request/wrapper.go +++ b/request/wrapper.go @@ -160,8 +160,15 @@ func (wh *wrapperHandle) GetRequestBody(ctx *gin.Context) map[string]any { // Author : go_developer@163.com<白茶清欢> // // Date : 15:18 2024/1/2 -func (wh *wrapperHandle) GetResponseBody(ctx *gin.Context, defaultVal string) string { - return "" +func (wh *wrapperHandle) GetResponseBody(ctx *gin.Context, key string, defaultVal any) any { + if nil == ctx { + return defaultVal + } + if val, exist := ctx.Get(key); !exist || nil == val { + return defaultVal + } else { + return val + } } // GetClientIp 获取请求客户端IP diff --git a/response/response.go b/response/response.go index 4acf36c..8eda65e 100644 --- a/response/response.go +++ b/response/response.go @@ -44,13 +44,13 @@ func Send(ctx *gin.Context, code interface{}, httpCode int, data interface{}) { // 设置数据已发送的标识 defer ctx.Set(hasSendResponseFlag, true) responseConfig := define.GetHttpHandleConfig() - finishRequestTime := time.Now() + finishRequestTime := time.Now().UnixMilli() responseData := map[string]interface{}{ responseConfig.ResponseCodeField: code, responseConfig.ResponseMessageField: exception.GetMessage(code), responseConfig.ResponseTraceIDField: ctx.GetString(responseConfig.ResponseTraceIDField), responseConfig.ResponseDataField: data, - responseConfig.HandleRequestCostField: finishRequestTime.UnixMilli() - ctx.GetTime(responseConfig.StartRequestTimeField).UnixMilli(), + responseConfig.HandleRequestCostField: finishRequestTime - ctx.GetTime(responseConfig.StartRequestTimeField).UnixMilli(), } // 记录完成时间 ctx.Set(responseConfig.FinishRequestTimeField, finishRequestTime)