// 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/trace" "git.zhangdeman.cn/zhangdeman/wrapper" "github.com/gin-gonic/gin" "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, "") hostname, _ := os.Hostname() return &Context{ Context: ginContext, StartRequestTime: time.Now(), FinishRequestTime: time.Time(int64(0)), HandlerAfterResponse: make([]gin.HandlerFunc, 0), customData: make(map[string]any), Hostname: hostname, HostIp: networkUtil.IP.GetHostIP(), customLock: &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 `json:"start_request_time"` // 开始请求时间(全局) FinishRequestTime time.Time `json:"finish_request_time"` // 结束请求时间(全局) TraceID string `json:"trace_id"` // 请求trace_id ParentAppName string `json:"parent_app_name"` // 父级应用名称 HandlerAfterResponse []gin.HandlerFunc `json:"-"` // 响应数据之后需要执行的逻辑 Hostname string `json:"hostname"` // 服务器名称 HostIp string `json:"host_ip"` // 服务器IP customData map[string]any `json:"-"` // 业务上下文自定义数据, 可以合 ginCtx.Value 作区分 customLock *sync.RWMutex `json:"-"` // 数据锁 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.customLock.Lock() defer ctx.customLock.Unlock() if nil == ctx.customData { ctx.customData = make(map[string]any) } ctx.Set(key, val) 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.customLock.RLock() defer ctx.customLock.RUnlock() if val, exist := ctx.customData[key]; exist { return val } else { return ctx.Value(key) } } // customDataExist 判断 // // Author : go_developer@163.com<白茶清欢> // // Date : 12:04 2025/2/28 func (ctx *Context) customDataExist(key string) any { ctx.customLock.RLock() defer ctx.customLock.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.customLock.Lock() defer ctx.customLock.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.customLock.Lock() defer ctx.customLock.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) }