From 7155e3144b8e38a2d316eeb5efe798da68284bec Mon Sep 17 00:00:00 2001 From: steden <1470804@qq.com> Date: Sat, 30 Nov 2024 21:02:40 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=E9=93=BE=E8=B7=AF=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- eumTraceType/enum.go | 34 ------- module.go | 7 +- saveTraceContextConsumer.go | 17 ++-- traceManager.go | 140 ++++++++++++++++++-------- trackContext.go | 193 ------------------------------------ 5 files changed, 108 insertions(+), 283 deletions(-) delete mode 100644 eumTraceType/enum.go delete mode 100644 trackContext.go diff --git a/eumTraceType/enum.go b/eumTraceType/enum.go deleted file mode 100644 index 2680794..0000000 --- a/eumTraceType/enum.go +++ /dev/null @@ -1,34 +0,0 @@ -package eumTraceType - -type Enum int - -const ( - WebApi Enum = iota // WebApi - MqConsumer // MQ消费 - QueueConsumer // 本地消费 - FSchedule // 调度中心 - Task // 本地任务 - WatchKey // ETCD - EventConsumer // 事件消费 - WebSocket // WebSocket -) - -func (e Enum) ToString() string { - switch e { - case WebApi: - return "WebApi" - case MqConsumer: - return "MqConsumer" - case QueueConsumer: - return "QueueConsumer" - case FSchedule: - return "FSchedule" - case Task: - return "Task" - case WatchKey: - return "WatchKey" - case EventConsumer: - return "EventConsumer" - } - return "" -} diff --git a/module.go b/module.go index 8e8b6a1..784160c 100644 --- a/module.go +++ b/module.go @@ -1,13 +1,14 @@ package linkTrace import ( + "strings" + "time" + "github.com/farseer-go/fs/configure" "github.com/farseer-go/fs/container" "github.com/farseer-go/fs/modules" "github.com/farseer-go/fs/trace" "github.com/farseer-go/queue" - "strings" - "time" ) // Enable 是否启用 @@ -38,6 +39,6 @@ func (module Module) PreInitialize() { if !strings.HasSuffix(FopsServer, "/") { FopsServer += "/" } - queue.Subscribe("TraceContext", "SaveTraceContext", 1000,5*time.Second, SaveTraceContextConsumer) + queue.Subscribe("TraceContext", "SaveTraceContext", 1000, 5*time.Second, SaveTraceContextConsumer) } } diff --git a/saveTraceContextConsumer.go b/saveTraceContextConsumer.go index b7b24d2..3d93d4f 100644 --- a/saveTraceContextConsumer.go +++ b/saveTraceContextConsumer.go @@ -9,13 +9,12 @@ import ( "github.com/farseer-go/collections" "github.com/farseer-go/fs/configure" - "github.com/farseer-go/fs/container" "github.com/farseer-go/fs/core" "github.com/farseer-go/fs/exception" "github.com/farseer-go/fs/flog" "github.com/farseer-go/fs/snc" "github.com/farseer-go/fs/trace" - "github.com/farseer-go/linkTrace/eumTraceType" + "github.com/farseer-go/fs/trace/eumTraceType" ) // FopsServer fops地址 @@ -26,14 +25,13 @@ func SaveTraceContextConsumer(subscribeName string, lstMessage collections.ListA if traceContext := trace.CurTraceContext.Get(); traceContext != nil { traceContext.Ignore() } - lstTraceContext := collections.NewList[TraceContext]() + lstTraceContext := collections.NewList[*trace.TraceContext]() lstMessage.Foreach(func(item *any) { // 上下文 - dto := (*item).(TraceContext) + dto := (*item).(*trace.TraceContext) if len(dto.List) == 0 && dto.TraceType != eumTraceType.WebApi { return } - dto.printLog() // 链路超过200条,则丢弃 if len(dto.List) > 200 { @@ -61,15 +59,16 @@ type UploadTraceRequest struct { } // UploadTrace 上传链路记录 -func uploadTrace(lstTraceContext any) error { +func uploadTrace(lstTraceContext collections.List[*trace.TraceContext]) error { bodyByte, _ := snc.Marshal(UploadTraceRequest{List: lstTraceContext}) url := configure.GetFopsServer() + "linkTrace/upload" newRequest, _ := http.NewRequest("POST", url, bytes.NewReader(bodyByte)) newRequest.Header.Set("Content-Type", "application/json") + // 链路追踪 - if traceContext := container.Resolve[trace.IManager]().GetCurTrace(); traceContext != nil { - newRequest.Header.Set("Trace-Id", traceContext.GetTraceId()) - newRequest.Header.Set("Trace-Level", strconv.Itoa(traceContext.GetTraceLevel())) + if traceContext := trace.CurTraceContext.Get(); traceContext != nil { + newRequest.Header.Set("Trace-Id", traceContext.TraceId) + newRequest.Header.Set("Trace-Level", strconv.Itoa(traceContext.TraceLevel)) newRequest.Header.Set("Trace-App-Name", core.AppName) } client := &http.Client{ diff --git a/traceManager.go b/traceManager.go index 157feb7..a8d322e 100644 --- a/traceManager.go +++ b/traceManager.go @@ -3,34 +3,26 @@ package linkTrace import ( "fmt" "strconv" + "strings" "time" "github.com/farseer-go/collections" "github.com/farseer-go/fs/core" "github.com/farseer-go/fs/dateTime" + "github.com/farseer-go/fs/flog" "github.com/farseer-go/fs/parse" "github.com/farseer-go/fs/sonyflake" "github.com/farseer-go/fs/trace" "github.com/farseer-go/fs/trace/eumCallType" - "github.com/farseer-go/linkTrace/eumTraceType" + "github.com/farseer-go/fs/trace/eumTraceType" + "github.com/farseer-go/queue" ) type traceManager struct { } -func (*traceManager) GetCurTrace() trace.ITraceContext { - return trace.CurTraceContext.Get() -} - -func (*traceManager) GetTraceId() string { - if traceContext := trace.CurTraceContext.Get(); traceContext != nil { - return traceContext.GetTraceId() - } - return "" -} - // EntryWebApi Webapi入口 -func (*traceManager) EntryWebApi(domain string, path string, method string, contentType string, header map[string]string, requestIp string) trace.ITraceContext { +func (*traceManager) EntryWebApi(domain string, path string, method string, contentType string, header map[string]string, requestIp string) *trace.TraceContext { headerDictionary := collections.NewDictionaryFromMap(header) traceId := parse.ToString(headerDictionary.GetValue("Trace-Id")) traceLevel := parse.ToInt(headerDictionary.GetValue("Trace-Level")) @@ -39,7 +31,7 @@ func (*traceManager) EntryWebApi(domain string, path string, method string, cont } else { traceLevel++ // 来自上游的请求,自动+1层 } - context := &TraceContext{ + context := &trace.TraceContext{ AppId: strconv.FormatInt(core.AppId, 10), AppName: core.AppName, AppIp: core.AppIp, @@ -49,7 +41,7 @@ func (*traceManager) EntryWebApi(domain string, path string, method string, cont StartTs: time.Now().UnixMicro(), TraceType: eumTraceType.WebApi, CreateAt: dateTime.Now(), - WebContext: WebContext{ + WebContext: trace.WebContext{ WebDomain: domain, WebPath: path, WebMethod: method, @@ -65,7 +57,7 @@ func (*traceManager) EntryWebApi(domain string, path string, method string, cont } // EntryWebSocket WebSocket入口 -func (*traceManager) EntryWebSocket(domain string, path string, header map[string]string, requestIp string) trace.ITraceContext { +func (*traceManager) EntryWebSocket(domain string, path string, header map[string]string, requestIp string) *trace.TraceContext { headerDictionary := collections.NewDictionaryFromMap(header) parentTraceId := parse.ToString(headerDictionary.GetValue("Trace-Id")) traceLevel := parse.ToInt(headerDictionary.GetValue("Trace-Level")) @@ -74,7 +66,7 @@ func (*traceManager) EntryWebSocket(domain string, path string, header map[strin } else { traceLevel++ // 来自上游的请求,自动+1层 } - context := &TraceContext{ + context := &trace.TraceContext{ AppId: strconv.FormatInt(core.AppId, 10), AppName: core.AppName, AppIp: core.AppIp, @@ -84,7 +76,7 @@ func (*traceManager) EntryWebSocket(domain string, path string, header map[strin StartTs: time.Now().UnixMicro(), TraceType: eumTraceType.WebSocket, CreateAt: dateTime.Now(), - WebContext: WebContext{ + WebContext: trace.WebContext{ WebDomain: domain, WebPath: path, WebMethod: "WEBSOCKET", @@ -100,7 +92,7 @@ func (*traceManager) EntryWebSocket(domain string, path string, header map[strin } // EntryMqConsumer mq 消费埋点 -func (*traceManager) EntryMqConsumer(parentTraceId, parentAppName, server string, queueName string, routingKey string) trace.ITraceContext { +func (*traceManager) EntryMqConsumer(parentTraceId, parentAppName, server string, queueName string, routingKey string) *trace.TraceContext { // 如果来自上游,则要自动+1层,默认为0 var traceLevel int if parentTraceId == "" { @@ -108,7 +100,7 @@ func (*traceManager) EntryMqConsumer(parentTraceId, parentAppName, server string } else { traceLevel++ // 来自上游的请求,自动+1层 } - context := &TraceContext{ + context := &trace.TraceContext{ AppId: strconv.FormatInt(core.AppId, 10), AppName: core.AppName, AppIp: core.AppIp, @@ -118,7 +110,7 @@ func (*traceManager) EntryMqConsumer(parentTraceId, parentAppName, server string StartTs: time.Now().UnixMicro(), TraceType: eumTraceType.MqConsumer, CreateAt: dateTime.Now(), - ConsumerContext: ConsumerContext{ + ConsumerContext: trace.ConsumerContext{ ConsumerServer: server, ConsumerQueueName: queueName, ConsumerRoutingKey: routingKey, @@ -130,8 +122,8 @@ func (*traceManager) EntryMqConsumer(parentTraceId, parentAppName, server string } // EntryQueueConsumer queue 消费埋点 -func (*traceManager) EntryQueueConsumer(queueName, subscribeName string) trace.ITraceContext { - context := &TraceContext{ +func (*traceManager) EntryQueueConsumer(queueName, subscribeName string) *trace.TraceContext { + context := &trace.TraceContext{ AppId: strconv.FormatInt(core.AppId, 10), AppName: core.AppName, AppIp: core.AppIp, @@ -140,7 +132,7 @@ func (*traceManager) EntryQueueConsumer(queueName, subscribeName string) trace.I StartTs: time.Now().UnixMicro(), TraceType: eumTraceType.QueueConsumer, CreateAt: dateTime.Now(), - ConsumerContext: ConsumerContext{ + ConsumerContext: trace.ConsumerContext{ ConsumerServer: fmt.Sprintf("本地Queue/%s/%s/%v", core.AppName, core.AppIp, core.AppId), ConsumerQueueName: queueName + "/" + subscribeName, }, @@ -151,19 +143,19 @@ func (*traceManager) EntryQueueConsumer(queueName, subscribeName string) trace.I } // EntryEventConsumer event 事件消费埋点 -func (receiver *traceManager) EntryEventConsumer(server, eventName, subscribeName string) trace.ITraceContext { +func (receiver *traceManager) EntryEventConsumer(server, eventName, subscribeName string) *trace.TraceContext { // 事件消费,一般是由其它入口的程序触发的,所以这里先看能不能取到之前的上下文 var traceId string var traceLevel int var parentAppName string - if cur := receiver.GetCurTrace(); cur != nil { + if cur := trace.CurTraceContext.Get(); cur != nil { traceId, parentAppName, _, _, _ = cur.GetAppInfo() - traceLevel = cur.GetTraceLevel() + 1 + traceLevel = cur.TraceLevel + 1 } else { traceId = strconv.FormatInt(sonyflake.GenerateId(), 10) parentAppName = core.AppName } - context := &TraceContext{ + context := &trace.TraceContext{ AppId: strconv.FormatInt(core.AppId, 10), AppName: core.AppName, AppIp: core.AppIp, @@ -173,7 +165,7 @@ func (receiver *traceManager) EntryEventConsumer(server, eventName, subscribeNam TraceType: eumTraceType.EventConsumer, TraceLevel: traceLevel, CreateAt: dateTime.Now(), - ConsumerContext: ConsumerContext{ + ConsumerContext: trace.ConsumerContext{ ConsumerServer: server, ConsumerQueueName: eventName + "/" + subscribeName, }, @@ -184,9 +176,9 @@ func (receiver *traceManager) EntryEventConsumer(server, eventName, subscribeNam } // EntryTask 创建本地任务入口 -func (*traceManager) EntryTask(taskName string) trace.ITraceContext { +func (*traceManager) EntryTask(taskName string) *trace.TraceContext { traceId := strconv.FormatInt(sonyflake.GenerateId(), 10) - context := &TraceContext{ + context := &trace.TraceContext{ AppId: strconv.FormatInt(core.AppId, 10), AppName: core.AppName, AppIp: core.AppIp, @@ -195,7 +187,7 @@ func (*traceManager) EntryTask(taskName string) trace.ITraceContext { StartTs: time.Now().UnixMicro(), TraceType: eumTraceType.Task, CreateAt: dateTime.Now(), - TaskContext: TaskContext{ + TaskContext: trace.TaskContext{ TaskName: taskName, }, } @@ -205,9 +197,9 @@ func (*traceManager) EntryTask(taskName string) trace.ITraceContext { } // EntryTaskGroup 创建本地任务入口(调度中心专用) -func (*traceManager) EntryTaskGroup(taskName string, taskGroupName string, taskId int64) trace.ITraceContext { +func (*traceManager) EntryTaskGroup(taskName string, taskGroupName string, taskId int64) *trace.TraceContext { traceId := strconv.FormatInt(sonyflake.GenerateId(), 10) - context := &TraceContext{ + context := &trace.TraceContext{ AppId: strconv.FormatInt(core.AppId, 10), AppName: core.AppName, AppIp: core.AppIp, @@ -216,7 +208,7 @@ func (*traceManager) EntryTaskGroup(taskName string, taskGroupName string, taskI StartTs: time.Now().UnixMicro(), TraceType: eumTraceType.Task, CreateAt: dateTime.Now(), - TaskContext: TaskContext{ + TaskContext: trace.TaskContext{ TaskName: fmt.Sprintf("%s,任务组=%s,任务ID=%v", taskName, taskGroupName, taskId), TaskGroupName: taskGroupName, TaskId: taskId, @@ -228,9 +220,9 @@ func (*traceManager) EntryTaskGroup(taskName string, taskGroupName string, taskI } // EntryFSchedule 创建调度中心入口 -func (*traceManager) EntryFSchedule(taskGroupName string, taskId int64, data map[string]string) trace.ITraceContext { +func (*traceManager) EntryFSchedule(taskGroupName string, taskId int64, data map[string]string) *trace.TraceContext { traceId := strconv.FormatInt(sonyflake.GenerateId(), 10) - context := &TraceContext{ + context := &trace.TraceContext{ AppId: strconv.FormatInt(core.AppId, 10), AppName: core.AppName, AppIp: core.AppIp, @@ -239,7 +231,7 @@ func (*traceManager) EntryFSchedule(taskGroupName string, taskId int64, data map StartTs: time.Now().UnixMicro(), TraceType: eumTraceType.FSchedule, CreateAt: dateTime.Now(), - TaskContext: TaskContext{ + TaskContext: trace.TaskContext{ TaskName: taskGroupName, TaskGroupName: taskGroupName, TaskId: taskId, @@ -252,9 +244,9 @@ func (*traceManager) EntryFSchedule(taskGroupName string, taskId int64, data map } // EntryWatchKey 创建etcd入口 -func (*traceManager) EntryWatchKey(key string) trace.ITraceContext { +func (*traceManager) EntryWatchKey(key string) *trace.TraceContext { traceId := strconv.FormatInt(sonyflake.GenerateId(), 10) - context := &TraceContext{ + context := &trace.TraceContext{ AppId: strconv.FormatInt(core.AppId, 10), AppName: core.AppName, AppIp: core.AppIp, @@ -263,7 +255,7 @@ func (*traceManager) EntryWatchKey(key string) trace.ITraceContext { StartTs: time.Now().UnixMicro(), TraceType: eumTraceType.WatchKey, CreateAt: dateTime.Now(), - WatchKeyContext: WatchKeyContext{ + WatchKeyContext: trace.WatchKeyContext{ WatchKey: key, }, } @@ -417,14 +409,74 @@ func add(traceDetail trace.ITraceDetail) { if t := trace.CurTraceContext.Get(); t != nil { detail := traceDetail.GetTraceDetail() // 时间轴:上下文入口起点时间到本次开始时间 - detail.Timeline = time.Duration(detail.StartTs-t.GetStartTs()) * time.Microsecond - details := t.GetList() + detail.Timeline = time.Duration(detail.StartTs-t.StartTs) * time.Microsecond + details := t.List if len(details) > 0 { detail.UnTraceTs = time.Duration(detail.StartTs-details[len(details)-1].(trace.ITraceDetail).GetTraceDetail().EndTs) * time.Microsecond } else { - detail.UnTraceTs = time.Duration(detail.StartTs-t.GetStartTs()) * time.Microsecond + detail.UnTraceTs = time.Duration(detail.StartTs-t.StartTs) * time.Microsecond } detail.TraceId, detail.AppName, detail.AppId, detail.AppIp, detail.ParentAppName = t.GetAppInfo() t.AddDetail(traceDetail) } } + +// End 结束当前链路 +func (receiver *traceManager) Push(traceContext *trace.TraceContext, err error) { + // 清空当前上下文 + defer trace.CurTraceContext.Remove() + + if traceContext.IsIgnore() { + return + } + traceContext.Error(err) + traceContext.EndTs = time.Now().UnixMicro() + traceContext.UseTs = time.Duration(traceContext.EndTs-traceContext.StartTs) * time.Microsecond + traceContext.UseDesc = traceContext.UseTs.String() + // 移除忽略的明细 + var newList []any + for _, detail := range traceContext.List { + if !detail.(trace.ITraceDetail).GetTraceDetail().IsIgnore() { + newList = append(newList, detail) + } + } + traceContext.List = newList + traceContext.TraceCount = len(newList) + + // 启用了链路追踪后,把数据写入到本地队列中 + if defConfig.Enable { + queue.Push("TraceContext", traceContext) + } + + // 打印日志 + if defConfig.PrintLog { + lst := collections.NewList[string]() + for i := 0; i < len(traceContext.List); i++ { + tab := strings.Repeat("\t", traceContext.List[i].(trace.ITraceDetail).GetLevel()-1) + detail := traceContext.List[i].(trace.ITraceDetail).GetTraceDetail() + log := fmt.Sprintf("%s%s (%s):%s", tab, flog.Blue(i+1), flog.Green(detail.UnTraceTs.String()), traceContext.List[i].(trace.ITraceDetail).ToString()) + lst.Add(log) + + if detail.Exception != nil && detail.Exception.ExceptionIsException { + lst.Add(fmt.Sprintf("%s:%s %s 出错了:%s", detail.Exception.ExceptionCallFile, flog.Blue(detail.Exception.ExceptionCallLine), flog.Red(detail.Exception.ExceptionCallFuncName), flog.Red(detail.Exception.ExceptionMessage))) + } + } + + if traceContext.Exception != nil && traceContext.Exception.ExceptionIsException { + lst.Add(fmt.Sprintf("%s%s:%s %s %s", flog.Red("【异常】"), flog.Blue(traceContext.Exception.ExceptionCallFile), flog.Blue(traceContext.Exception.ExceptionCallLine), flog.Green(traceContext.Exception.ExceptionCallFuncName), flog.Red(traceContext.Exception.ExceptionMessage))) + } + + lst.Add("-----------------------------------------------------------------") + logs := strings.Join(lst.ToArray(), "\n") + switch traceContext.TraceType { + case eumTraceType.WebApi: + flog.Printf("【%s链路追踪】TraceId:%s,耗时:%s,%s\n%s\n", traceContext.TraceType.ToString(), flog.Green(traceContext.TraceId), flog.Red(traceContext.UseTs.String()), traceContext.WebContext.WebPath, logs) + case eumTraceType.MqConsumer, eumTraceType.QueueConsumer, eumTraceType.EventConsumer: + flog.Printf("【%s链路追踪】TraceId:%s,耗时:%s,%s\n%s\n", traceContext.TraceType.ToString(), flog.Green(traceContext.TraceId), flog.Red(traceContext.UseTs.String()), traceContext.ConsumerContext.ConsumerQueueName, logs) + case eumTraceType.Task, eumTraceType.FSchedule: + flog.Printf("【%s链路追踪】TraceId:%s,耗时:%s,%s %s\n%s\n", traceContext.TraceType.ToString(), flog.Green(traceContext.TraceId), flog.Red(traceContext.UseTs.String()), traceContext.TaskContext.TaskName, traceContext.TaskContext.TaskGroupName, logs) + default: + flog.Printf("【%s链路追踪】TraceId:%s,耗时:%s\n%s\n", traceContext.TraceType.ToString(), flog.Green(traceContext.TraceId), flog.Red(traceContext.UseTs.String()), logs) + } + } +} diff --git a/trackContext.go b/trackContext.go deleted file mode 100644 index 2a30f83..0000000 --- a/trackContext.go +++ /dev/null @@ -1,193 +0,0 @@ -package linkTrace - -import ( - "fmt" - "strings" - "time" - - "github.com/farseer-go/collections" - "github.com/farseer-go/fs/dateTime" - "github.com/farseer-go/fs/flog" - "github.com/farseer-go/fs/trace" - "github.com/farseer-go/linkTrace/eumTraceType" - "github.com/farseer-go/queue" -) - -type TraceContext struct { - TraceId string `json:"tid"` // 上下文ID - AppId string `json:"aid"` // 应用ID - AppName string `json:"an"` // 应用名称 - AppIp string `json:"aip"` // 应用IP - ParentAppName string `json:"pn"` // 上游应用 - TraceLevel int `json:"tl"` // 逐层递增(显示上下游顺序) - StartTs int64 `json:"st"` // 调用开始时间戳(微秒) - EndTs int64 `json:"et"` // 调用结束时间戳(微秒) - UseTs time.Duration `json:"ut"` // 总共使用时间(微秒) - UseDesc string `json:"ud"` // 总共使用时间(描述) - TraceType eumTraceType.Enum `json:"tt"` // 状态码 - List []any `json:"l"` // 调用的上下文trace.ITraceDetail - TraceCount int `json:"tc"` // 追踪明细数量 - ignore bool // 忽略这次的链路追踪 - Exception *trace.ExceptionStack `json:"e"` // 异常信息 - WebContext - ConsumerContext - TaskContext - WatchKeyContext - CreateAt dateTime.DateTime `json:"ca"` // 请求时间 -} - -type WebContext struct { - WebDomain string `json:"wd"` // 请求域名 - WebPath string `json:"wp"` // 请求地址 - WebMethod string `json:"wm"` // 请求方式 - WebContentType string `json:"wct"` // 请求内容类型 - WebStatusCode int `json:"wsc"` // 状态码 - WebHeaders collections.Dictionary[string, string] `json:"wh"` // 请求头部 - WebRequestBody string `json:"wrb"` // 请求参数 - WebResponseBody string `json:"wpb"` // 输出参数 - WebRequestIp string `json:"wip"` // 客户端IP -} - -func (receiver WebContext) IsNil() bool { - return receiver.WebDomain == "" && receiver.WebPath == "" && receiver.WebMethod == "" && receiver.WebContentType == "" && receiver.WebStatusCode == 0 -} - -type ConsumerContext struct { - ConsumerServer string `json:"cs"` // MQ服务器 - ConsumerQueueName string `json:"cq"` // 队列名称 - ConsumerRoutingKey string `json:"cr"` // 路由KEY -} - -func (receiver ConsumerContext) IsNil() bool { - return receiver.ConsumerServer == "" && receiver.ConsumerQueueName == "" && receiver.ConsumerRoutingKey == "" -} - -type TaskContext struct { - TaskName string `json:"tn"` // 任务名称 - TaskGroupName string `json:"tgn"` // 任务组ID - TaskId int64 `json:"tid"` // 任务ID - TaskData collections.Dictionary[string, string] `json:"td"` // 任务数据 -} - -func (receiver TaskContext) IsNil() bool { - return receiver.TaskName == "" && receiver.TaskGroupName == "" && receiver.TaskId == 0 -} - -type WatchKeyContext struct { - WatchKey string `json:"wk"` // KEY -} - -func (receiver WatchKeyContext) IsNil() bool { - return receiver.WatchKey == "" -} - -func (receiver *TraceContext) SetBody(requestBody string, statusCode int, responseBody string) { - receiver.WebContext.WebRequestBody = requestBody - receiver.WebContext.WebStatusCode = statusCode - receiver.WebContext.WebResponseBody = responseBody -} - -func (receiver *TraceContext) SetResponseBody(responseBody string) { - receiver.WebContext.WebResponseBody = responseBody -} - -func (receiver *TraceContext) GetTraceId() string { - return receiver.TraceId -} -func (receiver *TraceContext) GetTraceLevel() int { return receiver.TraceLevel } -func (receiver *TraceContext) GetStartTs() int64 { - return receiver.StartTs -} - -// End 结束当前链路 -func (receiver *TraceContext) End(err error) { - // 清空当前上下文 - trace.CurTraceContext.Remove() - - if receiver.ignore { - return - } - receiver.EndTs = time.Now().UnixMicro() - receiver.UseTs = time.Duration(receiver.EndTs-receiver.StartTs) * time.Microsecond - receiver.UseDesc = receiver.UseTs.String() - // 移除忽略的明细 - var newList []any - for _, detail := range receiver.List { - if !detail.(trace.ITraceDetail).GetTraceDetail().IsIgnore() { - newList = append(newList, detail) - } - } - receiver.List = newList - receiver.TraceCount = len(newList) - - // 启用了链路追踪后,把数据写入到本地队列中 - if defConfig.Enable { - queue.Push("TraceContext", *receiver) - } - - // 打印日志 - receiver.printLog() -} - -func (receiver *TraceContext) Ignore() { - receiver.ignore = true -} - -// GetList 获取链路明细 -func (receiver *TraceContext) GetList() []any { - return receiver.List -} - -// AddDetail 添加链路明细 -func (receiver *TraceContext) AddDetail(detail trace.ITraceDetail) { - receiver.List = append(receiver.List, detail) -} - -// printLog 打印日志 -func (receiver *TraceContext) printLog() { - // 打印日志 - if defConfig.PrintLog { - lst := collections.NewList[string]() - for i := 0; i < len(receiver.List); i++ { - tab := strings.Repeat("\t", receiver.List[i].(trace.ITraceDetail).GetLevel()-1) - detail := receiver.List[i].(trace.ITraceDetail).GetTraceDetail() - log := fmt.Sprintf("%s%s (%s):%s", tab, flog.Blue(i+1), flog.Green(detail.UnTraceTs.String()), receiver.List[i].(trace.ITraceDetail).ToString()) - lst.Add(log) - - if detail.Exception != nil && detail.Exception.ExceptionIsException { - lst.Add(fmt.Sprintf("%s:%s %s 出错了:%s", detail.Exception.ExceptionCallFile, flog.Blue(detail.Exception.ExceptionCallLine), flog.Red(detail.Exception.ExceptionCallFuncName), flog.Red(detail.Exception.ExceptionMessage))) - } - } - - if receiver.Exception != nil && receiver.Exception.ExceptionIsException { - lst.Add(fmt.Sprintf("%s%s:%s %s %s", flog.Red("【异常】"), flog.Blue(receiver.Exception.ExceptionCallFile), flog.Blue(receiver.Exception.ExceptionCallLine), flog.Green(receiver.Exception.ExceptionCallFuncName), flog.Red(receiver.Exception.ExceptionMessage))) - } - - lst.Add("-----------------------------------------------------------------") - logs := strings.Join(lst.ToArray(), "\n") - switch receiver.TraceType { - case eumTraceType.WebApi: - flog.Printf("【%s链路追踪】TraceId:%s,耗时:%s,%s\n%s\n", receiver.TraceType.ToString(), flog.Green(receiver.TraceId), flog.Red(receiver.UseTs.String()), receiver.WebContext.WebPath, logs) - case eumTraceType.MqConsumer, eumTraceType.QueueConsumer, eumTraceType.EventConsumer: - flog.Printf("【%s链路追踪】TraceId:%s,耗时:%s,%s\n%s\n", receiver.TraceType.ToString(), flog.Green(receiver.TraceId), flog.Red(receiver.UseTs.String()), receiver.ConsumerContext.ConsumerQueueName, logs) - case eumTraceType.Task, eumTraceType.FSchedule: - flog.Printf("【%s链路追踪】TraceId:%s,耗时:%s,%s %s\n%s\n", receiver.TraceType.ToString(), flog.Green(receiver.TraceId), flog.Red(receiver.UseTs.String()), receiver.TaskContext.TaskName, receiver.TaskContext.TaskGroupName, logs) - default: - flog.Printf("【%s链路追踪】TraceId:%s,耗时:%s\n%s\n", receiver.TraceType.ToString(), flog.Green(receiver.TraceId), flog.Red(receiver.UseTs.String()), logs) - } - } -} - -func (receiver *TraceContext) Error(err error) { - if err != nil { - receiver.Exception = &trace.ExceptionStack{ - ExceptionIsException: true, - ExceptionMessage: err.Error(), - } - receiver.Exception.ExceptionCallFile, receiver.Exception.ExceptionCallFuncName, receiver.Exception.ExceptionCallLine = trace.GetCallerInfo() - } -} - -func (receiver *TraceContext) GetAppInfo() (string, string, string, string, string) { - return receiver.TraceId, receiver.AppName, receiver.AppId, receiver.AppIp, receiver.ParentAppName -}