// Package request ... // // Description : request ... // // Author : go_developer@163.com<白茶清欢> // // Date : 2025-02-28 11:45 package request import ( "fmt" networkUtil "git.zhangdeman.cn/zhangdeman/network/util" "git.zhangdeman.cn/zhangdeman/wrapper" "github.com/gin-gonic/gin" "git.zhangdeman.cn/zhangdeman/trace" "os" "strings" "sync" "time" ) // getTraceID 生成traceID // // Author : go_developer@163.com<白茶清欢> // // Date : 23:12 2022/6/25 func getTraceID(ctx *gin.Context) string { hostname, _ := os.Hostname() if hostname != "" { hostname = "unknown" } return fmt.Sprintf( "%v-%v-%v-%v-%v", time.Now().UnixNano()/1e6, strings.ReplaceAll(networkUtil.IP.GetHostIP(), ".", ""), strings.ReplaceAll(hostname, ".", ""), strings.ReplaceAll(networkUtil.IP.GetRemoteIP(ctx.Request), ".", ""), wrapper.StringFromRandom(32, "").Md5().Value, ) } // getRequestID 生成requestID // // Author : go_developer@163.com<白茶清欢> // // Date : 23:12 2022/6/25 func getRequestID(ctx *gin.Context, traceID string) string { requestID := ctx.GetHeader("X-Forward-Request-Id") if len(requestID) > 0 { return requestID } if len(traceID) > 0 { return traceID } return getTraceID(ctx) } // NewContext 获取context实例 // // Author : go_developer@163.com<白茶清欢> // // Date : 12:01 2025/2/28 func NewContext(ginContext *gin.Context) *Context { // 生成traceID traceID := getRequestID(ginContext, "") return &Context{ Context: ginContext, StartRequestTime: time.Now(), FinishRequestTime: time.Time(int64(0)), HandlerAfterResponse: make([]gin.HandlerFunc, 0), CustomData: make(map[string]any), lock: &sync.RWMutex{}, TraceID: traceID, Trace: trace.NewRuntime(traceID, 0), } } // Context 请求上下文信息, 对 ctx *gin.Context的二次包装 // // Author : go_developer@163.com<白茶清欢> // // Date : 11:45 2025/2/28 type Context struct { *gin.Context `json:"-"` StartRequestTime time.Time // 开始请求时间(全局) FinishRequestTime time.Time // 结束请求时间(全局) TraceID string `json:"trace_id"` // 请求trace_id ParentAppName string `json:"parent_app_name"` // 父级应用名称 HandlerAfterResponse []gin.HandlerFunc `json:"-"` // 响应数据之后需要执行的逻辑 CustomData map[string]any // 业务上下文自定义数据, 可以合 ginCtx.Value 作区分 lock *sync.RWMutex Trace *trace.Runtime `json:"-"` // 追踪实例 } // SetCustom 设置数据 // // Author : go_developer@163.com<白茶清欢> // // Date : 11:58 2025/2/28 func (ctx *Context) SetCustom(key string, val any) { ctx.lock.Lock() defer ctx.lock.Unlock() if nil == ctx.CustomData { ctx.CustomData = make(map[string]any) } ctx.CustomData[key] = val } // CustomDataValue 获取customData // // Author : go_developer@163.com<白茶清欢> // // Date : 12:03 2025/2/28 func (ctx *Context) CustomDataValue(key string) any { ctx.lock.RLock() defer ctx.lock.RUnlock() if val, exist := ctx.CustomData[key]; exist { return val } else { return nil } } // CustomDataExist 判断 // // Author : go_developer@163.com<白茶清欢> // // Date : 12:04 2025/2/28 func (ctx *Context) CustomDataExist(key string) any { ctx.lock.RLock() defer ctx.lock.RUnlock() _, exist := ctx.CustomData[key] return exist } // CustomDataAppend 向数组数据中追加元素 // // Author : go_developer@163.com<白茶清欢> // // Date : 12:07 2025/2/28 func (ctx *Context) CustomDataAppend(key string, appendValue any) { ctx.lock.Lock() defer ctx.lock.Unlock() val, exist := ctx.CustomData[key] if !exist || nil == val { ctx.CustomData[key] = []any{appendValue} return } if valArr, ok := val.([]any); ok { valArr = append(valArr, appendValue) ctx.CustomData[key] = valArr } // 非数组, 忽略追加行为 } // CustomDataAppendProperty 向一个map中追加/更新属性 // // Author : go_developer@163.com<白茶清欢> // // Date : 12:11 2025/2/28 func (ctx *Context) CustomDataAppendProperty(key string, appendKey string, appendValue any) { ctx.lock.Lock() defer ctx.lock.Unlock() val, exist := ctx.CustomData[key] if !exist || nil == val { ctx.CustomData[key] = map[string]any{ appendKey: appendValue, } return } if valMap, ok := val.(map[string]any); ok { valMap[appendKey] = appendValue ctx.CustomData[key] = valMap } // 非map, 忽略追加行为 } // TraceStart 开始监控 // // Author : go_developer@163.com<白茶清欢> // // Date : 12:24 2025/2/28 func (ctx *Context) TraceStart(action string, actionData map[string]any) int { return ctx.Trace.StartBehavior(action, actionData) } // TraceEnd 完成监控 // // Author : go_developer@163.com<白茶清欢> // // Date : 12:24 2025/2/28 func (ctx *Context) TraceEnd(behaviorID int, endData map[string]any) { ctx.Trace.FinishBehavior(behaviorID, endData) }