first commit

This commit is contained in:
2024-07-23 10:23:43 +08:00
commit 7b4c2521a3
126 changed files with 15931 additions and 0 deletions

81
pkg/trace/README.md Normal file
View File

@ -0,0 +1,81 @@
## trace
一个用于开发调试的辅助工具。
可以实时显示当前页面的操作的请求信息、运行情况、SQL执行、错误提示等。
- `trace.go` 主入口文件;
- `dialog.go` 处理 third_party_requests 记录;
- `debug.go` 处理 debug 记录;
#### 数据格式
##### trace_id
当前 trace 的 ID例如938ff86be98439c6c1a7便于搜索使用。
##### request
请求信息,会包括:
- ttl 请求超时时间例如2s 或 un-limit
- method 请求方式例如GET 或 POST
- decoded_url 请求地址
- header 请求头信息
- body 请求体信息
##### response
- header 响应头信息
- body 响应提信息
- business_code 业务码例如10010
- business_code_msg 业务码信息,例如:签名错误
- http_code HTTP 状态码例如200
- http_code_msg HTTP 状态码信息例如OK
- cost_seconds 耗费时长:单位秒,比如 0.001105661
##### third_party_requests
每一个第三方 http 请求都会生成如下的一组数据,多个请求会生成多组数据。
- request同上 request 结构一致
- response同上 response 结构一致
- success是否成功true 或 false
- cost_seconds耗费时长单位秒
注意response 中的 business_code、business_code_msg 为空,因为各个第三方返回结构不同,这两个字段为空。
##### sqls
执行的 SQL 信息,多个 SQL 会记录多组数据。
- timestamp时间格式2006-01-02 15:04:05
- stack文件地址和行号
- cost_seconds执行时长单位
- sqlSQL 语句
- rows_affected影响行数
##### debugs
- key 打印的标示
- value 打印的值
```cassandraql
// 调试时,使用这个方法:
p.Print("key", "value", p.WithTrace(c.Trace()))
```
只有参数中增加了 `p.WithTrace(c.Trace())`,才会记录到 `debugs` 中。
##### success
是否成功true 或 false
```cassandraql
success = !ctx.IsAborted() && ctx.Writer.Status() == http.StatusOK
```
##### cost_seconds
耗费时长:单位秒,比如 0.001105661

7
pkg/trace/debug.go Normal file
View File

@ -0,0 +1,7 @@
package trace
type Debug struct {
Key string `json:"key"` // 标示
Value any `json:"value"` // 值
CostSeconds float64 `json:"cost_seconds"` // 执行时间(单位秒)
}

32
pkg/trace/dialog.go Normal file
View File

@ -0,0 +1,32 @@
package trace
import "sync"
var _ D = (*Dialog)(nil)
type D interface {
i()
AppendResponse(resp *Response)
}
// Dialog 内部调用其它方接口的会话信息失败时会有retry操作所以 response 会有多次。
type Dialog struct {
mux sync.Mutex
Request *Request `json:"request"` // 请求信息
Responses []*Response `json:"responses"` // 返回信息
Success bool `json:"success"` // 是否成功true 或 false
CostSeconds float64 `json:"cost_seconds"` // 执行时长(单位秒)
}
func (d *Dialog) i() {}
// AppendResponse 按转的追加response信息
func (d *Dialog) AppendResponse(resp *Response) {
if resp == nil {
return
}
d.mux.Lock()
d.Responses = append(d.Responses, resp)
d.mux.Unlock()
}

17
pkg/trace/grpc.go Normal file
View File

@ -0,0 +1,17 @@
package trace
import (
"google.golang.org/grpc/metadata"
)
type Grpc struct {
Timestamp string `json:"timestamp"` // 时间格式2006-01-02 15:04:05
Addr string `json:"addr"` // 地址
Method string `json:"method"` // 操作方法
Meta metadata.MD `json:"meta"` // Mate
Request map[string]any `json:"request"` // 请求信息
Response map[string]any `json:"response"` // 返回信息
CostSeconds float64 `json:"cost_seconds"` // 执行时间(单位秒)
Code string `json:"err_code,omitempty"` // 错误码
Message string `json:"err_message,omitempty"` // 错误信息
}

10
pkg/trace/redis.go Normal file
View File

@ -0,0 +1,10 @@
package trace
type Redis struct {
Timestamp string `json:"timestamp"` // 时间格式2006-01-02 15:04:05
Handle string `json:"handle"` // 操作SET/GET 等
Key string `json:"key"` // Key
Value string `json:"value,omitempty"` // Value
TTL float64 `json:"ttl,omitempty"` // 超时时长(单位分)
CostSeconds float64 `json:"cost_seconds"` // 执行时间(单位秒)
}

9
pkg/trace/sql.go Normal file
View File

@ -0,0 +1,9 @@
package trace
type SQL struct {
Timestamp string `json:"timestamp"` // 时间格式2006-01-02 15:04:05
Stack string `json:"stack"` // 文件地址和行号
SQL string `json:"sql"` // SQL 语句
Rows int64 `json:"rows_affected"` // 影响行数
CostSeconds float64 `json:"cost_seconds"` // 执行时长(单位秒)
}

154
pkg/trace/trace.go Normal file
View File

@ -0,0 +1,154 @@
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,omitempty"` // 调用第三方接口的信息
Debugs []*Debug `json:"debugs,omitempty"` // 调试信息
SQLs []*SQL `json:"sqls,omitempty"` // 执行的 SQL 信息
Redis []*Redis `json:"redis,omitempty"` // 执行的 Redis 信息
GRPCs []*Grpc `json:"grpc,omitempty"` // 执行的 gRPC 信息
Success bool `json:"success"` // 请求结果 true or false
CostSeconds float64 `json:"cost_seconds"` // 执行时长(单位秒)
}
// Request 请求信息
type Request struct {
TTL string `json:"ttl,omitempty"` // 请求超时时间
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
}