package trace import ( "crypto/rand" "encoding/hex" "sync" ) const Header = "X-TRACE-ID" var _ T = (*Trace)(nil) type T interface { i() ID() string WithRequest(req *Request) *Trace WithResponse(resp *Response) *Trace AppendDialog(dialog *Dialog) *Trace AppendDebug(debug *Debug) *Trace AppendSQL(sql *SQL) *Trace AppendRedis(redis *Redis) *Trace AppendGRPC(grpc *Grpc) *Trace } // Trace 记录的参数 type Trace struct { mux sync.Mutex Identifier string `json:"trace_id"` // 链路ID Request *Request `json:"request"` // 请求信息 Response *Response `json:"response"` // 返回信息 ThirdPartyRequests []*Dialog `json:"third_party_requests"` // 调用第三方接口的信息 Debugs []*Debug `json:"debugs"` // 调试信息 SQLs []*SQL `json:"sqls"` // 执行的 SQL 信息 Redis []*Redis `json:"redis"` // 执行的 Redis 信息 GRPCs []*Grpc `json:"grpc"` // 执行的 gRPC 信息 Success bool `json:"success"` // 请求结果 true or false CostSeconds float64 `json:"cost_seconds"` // 执行时长(单位秒) } // Request 请求信息 type Request struct { TTL string `json:"ttl"` // 请求超时时间 Method string `json:"method"` // 请求方式 DecodedURL string `json:"decoded_url"` // 请求地址 Header any `json:"header"` // 请求 Header 信息 Body any `json:"body"` // 请求 Body 信息 } // Response 响应信息 type Response struct { Header any `json:"header"` // Header 信息 Body any `json:"body"` // Body 信息 BusinessCode int `json:"business_code,omitempty"` // 业务码 BusinessCodeMsg string `json:"business_code_msg,omitempty"` // 提示信息 HttpCode int `json:"http_code"` // HTTP 状态码 HttpCodeMsg string `json:"http_code_msg"` // HTTP 状态码信息 CostSeconds float64 `json:"cost_seconds"` // 执行时间(单位秒) } func New(id string) *Trace { if id == "" { buf := make([]byte, 10) _, _ = rand.Read(buf) id = hex.EncodeToString(buf) } return &Trace{ Identifier: id, } } func (t *Trace) i() {} // ID 唯一标识符 func (t *Trace) ID() string { return t.Identifier } // WithRequest 设置request func (t *Trace) WithRequest(req *Request) *Trace { t.Request = req return t } // WithResponse 设置response func (t *Trace) WithResponse(resp *Response) *Trace { t.Response = resp return t } // AppendDialog 安全的追加内部调用过程dialog func (t *Trace) AppendDialog(dialog *Dialog) *Trace { if dialog == nil { return t } t.mux.Lock() defer t.mux.Unlock() t.ThirdPartyRequests = append(t.ThirdPartyRequests, dialog) return t } // AppendDebug 追加 debug func (t *Trace) AppendDebug(debug *Debug) *Trace { if debug == nil { return t } t.mux.Lock() defer t.mux.Unlock() t.Debugs = append(t.Debugs, debug) return t } // AppendSQL 追加 SQL func (t *Trace) AppendSQL(sql *SQL) *Trace { if sql == nil { return t } t.mux.Lock() defer t.mux.Unlock() t.SQLs = append(t.SQLs, sql) return t } // AppendRedis 追加 Redis func (t *Trace) AppendRedis(redis *Redis) *Trace { if redis == nil { return t } t.mux.Lock() defer t.mux.Unlock() t.Redis = append(t.Redis, redis) return t } // AppendGRPC 追加 gRPC 调用信息 func (t *Trace) AppendGRPC(grpc *Grpc) *Trace { if grpc == nil { return t } t.mux.Lock() defer t.mux.Unlock() t.GRPCs = append(t.GRPCs, grpc) return t }