gin/request/context.go

201 lines
5.5 KiB
Go

// 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.Unix(0, 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)
}