mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-04 00:10:25 +08:00
151 lines
3.6 KiB
Go
151 lines
3.6 KiB
Go
package req
|
||
|
||
import (
|
||
"fmt"
|
||
"mayfly-go/pkg/contextx"
|
||
"mayfly-go/pkg/errorx"
|
||
"mayfly-go/pkg/i18n"
|
||
"mayfly-go/pkg/logx"
|
||
"mayfly-go/pkg/utils/anyx"
|
||
"mayfly-go/pkg/utils/runtimex"
|
||
)
|
||
|
||
type SaveLogFunc func(*Ctx)
|
||
|
||
var saveLog SaveLogFunc
|
||
|
||
// 设置保存日志处理函数
|
||
func SetSaveLogFunc(sl SaveLogFunc) {
|
||
saveLog = sl
|
||
}
|
||
|
||
type LogInfo struct {
|
||
Description string // 请求描述
|
||
|
||
LogResp bool // 是否记录返回结果
|
||
save bool // 是否保存日志
|
||
}
|
||
|
||
// NewLog 新建日志信息,默认不保存该日志
|
||
func NewLog(description string) *LogInfo {
|
||
return &LogInfo{Description: description, LogResp: false, save: false}
|
||
}
|
||
|
||
// NewLogI 使用msgId新建日志信息,默认不保存该日志
|
||
func NewLogI(msgId i18n.MsgId) *LogInfo {
|
||
return &LogInfo{Description: i18n.T(msgId), LogResp: false, save: false}
|
||
}
|
||
|
||
// NewLogSave 新建日志信息,并且需要保存该日志信息
|
||
func NewLogSave(description string) *LogInfo {
|
||
return &LogInfo{Description: description, LogResp: false, save: true}
|
||
}
|
||
|
||
// NewLogSaveI 使用msgId新建日志信息,并且需要保存该日志信息
|
||
func NewLogSaveI(msgId i18n.MsgId) *LogInfo {
|
||
return &LogInfo{Description: i18n.T(msgId), LogResp: false, save: true}
|
||
}
|
||
|
||
// 记录返回结果
|
||
func (i *LogInfo) WithLogResp() *LogInfo {
|
||
i.LogResp = true
|
||
return i
|
||
}
|
||
|
||
const DefaultLogFrames = 10
|
||
|
||
func LogHandler(rc *Ctx) error {
|
||
if rc.Conf == nil || rc.Conf.logInfo == nil {
|
||
return nil
|
||
}
|
||
|
||
li := rc.Conf.logInfo
|
||
|
||
attrMap := make(map[string]any, 0)
|
||
|
||
req := rc.GetRequest()
|
||
attrMap[req.Method] = req.URL.Path
|
||
|
||
if la := contextx.GetLoginAccount(rc.MetaCtx); la != nil {
|
||
attrMap["uid"] = la.Id
|
||
attrMap["uname"] = la.Username
|
||
}
|
||
|
||
// 如果需要保存日志,并且保存日志处理函数存在则执行保存日志函数
|
||
if li.save && saveLog != nil {
|
||
go saveLog(rc)
|
||
}
|
||
|
||
logMsg := li.Description
|
||
rcErr := rc.Error
|
||
|
||
if logx.GetConfig().IsJsonType() {
|
||
// json格式日志处理
|
||
attrMap["req"] = rc.ReqParam
|
||
if li.LogResp {
|
||
attrMap["resp"] = rc.ResData
|
||
}
|
||
attrMap["exeTime"] = rc.timed
|
||
|
||
if rcErr != nil {
|
||
nFrames := DefaultLogFrames
|
||
if _, ok := rc.Error.(errorx.BizError); ok {
|
||
nFrames = nFrames / 2
|
||
}
|
||
attrMap["error"] = rc.Err
|
||
// 跳过log_handler等相关堆栈
|
||
attrMap["stacktrace"] = runtimex.StackStr(5, nFrames)
|
||
}
|
||
} else {
|
||
// 处理文本格式日志信息
|
||
if rcErr != nil {
|
||
logMsg = getErrMsg(rc, rcErr)
|
||
} else {
|
||
logMsg = getLogMsg(rc)
|
||
}
|
||
}
|
||
|
||
if rcErr != nil {
|
||
logx.ErrorWithFields(rc.MetaCtx, logMsg, attrMap)
|
||
return nil
|
||
}
|
||
logx.InfoWithFields(rc.MetaCtx, logMsg, attrMap)
|
||
return nil
|
||
}
|
||
|
||
func getLogMsg(rc *Ctx) string {
|
||
logInfo := rc.Conf.logInfo
|
||
msg := logInfo.Description + fmt.Sprintf(" ->%dms", rc.timed)
|
||
if !anyx.IsBlank(rc.ReqParam) {
|
||
msg = msg + fmt.Sprintf("\n--> %s", anyx.ToString(rc.ReqParam))
|
||
}
|
||
|
||
// 返回结果不为空,则记录返回结果
|
||
if logInfo.LogResp && !anyx.IsBlank(rc.ResData) {
|
||
msg = msg + fmt.Sprintf("\n<-- %s", anyx.ToString(rc.ResData))
|
||
}
|
||
return msg
|
||
}
|
||
|
||
func getErrMsg(rc *Ctx, err any) string {
|
||
msg := rc.Conf.logInfo.Description + fmt.Sprintf(" ->%dms", rc.timed)
|
||
if !anyx.IsBlank(rc.ReqParam) {
|
||
msg = msg + fmt.Sprintf("\n--> %s", anyx.ToString(rc.ReqParam))
|
||
}
|
||
|
||
nFrames := DefaultLogFrames
|
||
var errMsg string
|
||
switch t := err.(type) {
|
||
case *errorx.BizError:
|
||
errMsg = fmt.Sprintf("\n<-e %s", t.String())
|
||
nFrames = nFrames / 2
|
||
case error:
|
||
errMsg = fmt.Sprintf("\n<-e errMsg: %s", t.Error())
|
||
case string:
|
||
errMsg = fmt.Sprintf("\n<-e errMsg: %s", t)
|
||
}
|
||
// 加上堆栈信息
|
||
errMsg += fmt.Sprintf("\n<-stacktrace: %s", runtimex.StackStr(5, nFrames))
|
||
return (msg + errMsg)
|
||
}
|