Skip to content

Commit 463b438

Browse files
committed
trace-parser: bind traceid(logid) with goroutine
1 parent a9e3b34 commit 463b438

File tree

4 files changed

+73
-9
lines changed

4 files changed

+73
-9
lines changed

pkg/stats/runtimetrace/parser.go

Lines changed: 68 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,26 @@ type GoroutineInfo struct {
1818
State trace.GoState
1919
Stack []trace.StackFrame
2020
Children []trace.GoID
21+
TraceID string // 关联的 trace.Log() 注入的 ID
2122
}
2223

2324
// TraceParser 用于解析 runtime trace 文件
2425
type TraceParser struct {
2526
goroutines map[trace.GoID]*GoroutineInfo
2627
relationships map[trace.GoID][]trace.GoID // parent -> children
2728
events []trace.Event
29+
goroutineTraceIDs map[trace.GoID]string // goroutine -> trace ID mapping
30+
loggedTraceIDs map[trace.GoID]string // 每个goroutine最后记录的trace.Log() ID
2831
}
2932

3033
// NewTraceParser 创建新的 trace 解析器
3134
func NewTraceParser() *TraceParser {
3235
return &TraceParser{
33-
goroutines: make(map[trace.GoID]*GoroutineInfo),
34-
relationships: make(map[trace.GoID][]trace.GoID),
35-
events: make([]trace.Event, 0),
36+
goroutines: make(map[trace.GoID]*GoroutineInfo),
37+
relationships: make(map[trace.GoID][]trace.GoID),
38+
events: make([]trace.Event, 0),
39+
goroutineTraceIDs: make(map[trace.GoID]string),
40+
loggedTraceIDs: make(map[trace.GoID]string),
3641
}
3742
}
3843

@@ -118,7 +123,12 @@ func (tp *TraceParser) processStateTransition(ev trace.Event) {
118123
if from == trace.GoNotExist && to == trace.GoRunnable {
119124
ginfo.Created = ev.Time()
120125
ginfo.ParentID = ev.Goroutine()
121-
// tp.goroutines[ginfo.ParentID].Children = append(tp.goroutines[ginfo.ParentID].Children, ginfo.ID)
126+
127+
// 继承父 goroutine 的 trace ID
128+
if parentTraceID, exists := tp.goroutineTraceIDs[ginfo.ParentID]; exists {
129+
ginfo.TraceID = parentTraceID
130+
tp.goroutineTraceIDs[goid] = parentTraceID
131+
}
122132
}
123133

124134
// 检测 goroutine 结束
@@ -155,7 +165,19 @@ func (tp *TraceParser) processTaskEvent(ev trace.Event) {
155165
// processLogEvent 处理日志事件
156166
func (tp *TraceParser) processLogEvent(ev trace.Event) {
157167
// 处理 runtime/trace.Log 记录的日志
158-
// 这可以包含用户自定义的标识信息
168+
// 提取用户注入的 trace ID
169+
logEvent := ev.Log()
170+
if logEvent.Message != "" {
171+
goid := ev.Goroutine()
172+
// 记录该 goroutine 的 trace ID
173+
tp.loggedTraceIDs[goid] = logEvent.Message
174+
tp.goroutineTraceIDs[goid] = logEvent.Message
175+
176+
// 更新 goroutine 信息中的 trace ID
177+
if ginfo, exists := tp.goroutines[goid]; exists {
178+
ginfo.TraceID = logEvent.Message
179+
}
180+
}
159181
}
160182

161183
// inferParentGoroutine 推断父 goroutine
@@ -260,9 +282,40 @@ func (tp *TraceParser) printGoroutineSubtree(goid trace.GoID, depth int) {
260282
}
261283
}
262284

285+
// GetGoroutineTraceID 获取指定 goroutine 的 trace ID
286+
func (tp *TraceParser) GetGoroutineTraceID(goid trace.GoID) (string, bool) {
287+
traceID, exists := tp.goroutineTraceIDs[goid]
288+
return traceID, exists
289+
}
290+
291+
// GetGoroutinesByTraceID 获取指定 trace ID 关联的所有 goroutine
292+
func (tp *TraceParser) GetGoroutinesByTraceID(traceID string) []trace.GoID {
293+
var goroutines []trace.GoID
294+
for goid, id := range tp.goroutineTraceIDs {
295+
if id == traceID {
296+
goroutines = append(goroutines, goid)
297+
}
298+
}
299+
return goroutines
300+
}
301+
302+
// GetAllTraceIDs 获取所有的 trace ID
303+
func (tp *TraceParser) GetAllTraceIDs() []string {
304+
traceIDSet := make(map[string]bool)
305+
for _, traceID := range tp.goroutineTraceIDs {
306+
traceIDSet[traceID] = true
307+
}
308+
309+
var traceIDs []string
310+
for traceID := range traceIDSet {
311+
traceIDs = append(traceIDs, traceID)
312+
}
313+
return traceIDs
314+
}
315+
263316
// GetStatistics 获取统计信息
264-
func (tp *TraceParser) GetStatistics() map[string]interface{} {
265-
stats := make(map[string]interface{})
317+
func (tp *TraceParser) GetStatistics() map[string]any {
318+
stats := make(map[string]any)
266319

267320
totalGoroutines := len(tp.goroutines)
268321
stats["total_goroutines"] = totalGoroutines
@@ -292,6 +345,14 @@ func (tp *TraceParser) GetStatistics() map[string]interface{} {
292345
// 计算树的深度
293346
maxDepth := tp.calculateMaxDepth()
294347
stats["max_goroutine_tree_depth"] = maxDepth
348+
349+
// trace ID 统计
350+
stats["total_trace_ids"] = len(tp.GetAllTraceIDs())
351+
traceIDStats := make(map[string]int)
352+
for _, traceID := range tp.goroutineTraceIDs {
353+
traceIDStats[traceID]++
354+
}
355+
stats["trace_id_distribution"] = traceIDStats
295356

296357
return stats
297358
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
实现一个golang runtime trace文件的解析能力,trace文件是通过"runtime/trace"采集的。包含以下功能:
2+
1. 解析 goroutine 相关的 event,分析 goroutine 的父子关系。
3+
2. 解析 trace.Log() 注入的id(string类型),将后续产生的 goroutine 都关联到这个id。

pkg/stats/runtimetrace/tracer_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,7 @@ func TestExecutionTracer(t *testing.T) {
6666
wg.Add(1)
6767
go func() {
6868
defer wg.Done()
69-
id := getLogid(ctx)
70-
runtimeTrace.WithRegion(ctx, id, testFunc)
69+
testFunc()
7170
}()
7271
}
7372
wg.Wait()
@@ -168,6 +167,7 @@ func parseTrace() {
168167
fmt.Println("===============================")
169168
for goid, info := range parser.GetAllGoroutines() {
170169
fmt.Printf("Goroutine %d:\n", goid)
170+
fmt.Printf(" TraceID: %s\n", info.TraceID)
171171
fmt.Printf(" Parent: %d\n", info.ParentID)
172172
fmt.Printf(" Created: %v\n", info.Created)
173173
if info.Finished != 0 {
-129 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)