v0_4 让输出的跟踪信息更具层次感
# v0.4 让输出的跟踪信息更具层次感
对于程序员来说,缩进是最能体现出“层次感”的方法,如果将上面示例中 Goroutine 00001 的函数调用跟踪信息用如下的形式展示出来,函数的调用顺序更加一目了然:
g[00001]: ->main.A1
g[00001]: ->main.B1
g[00001]: ->main.C1
g[00001]: ->main.D
g[00001]: <-main.D
g[00001]: <-main.C1
g[00001]: <-main.B1
g[00001]: <-main.A1
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
代码如下:
// trace3/trace.go
func printTrace(id uint64, name, arrow string, indent int) {
indents := ""
for i := 0; i < indent; i++ {
indents += " "
}
fmt.Printf("g[%05d]:%s%s%s\n", id, indents, arrow, name)
}
var mu sync.Mutex
var m = make(map[uint64]int)
func Trace() func() {
pc, _, _, ok := runtime.Caller(1)
if !ok {
panic("not found caller")
}
fn := runtime.FuncForPC(pc)
name := fn.Name()
gid := curGoroutineID()
mu.Lock()
indents := m[gid] // 获取当前gid对应的缩进层次
m[gid] = indents + 1 // 缩进层次+1后存入map
mu.Unlock()
printTrace(gid, name, "->", indents+1)
return func() {
mu.Lock()
indents := m[gid] // 获取当前gid对应的缩进层次
m[gid] = indents - 1 // 缩进层次-1后存入map
mu.Unlock()
printTrace(gid, name, "<-", indents)
}
}
/*
g[00001]: ->main.A1
g[00001]: ->main.B1
g[00001]: ->main.C1
g[00001]: ->main.D
g[00001]: <-main.D
g[00001]: <-main.C1
g[00001]: <-main.B1
g[00001]: <-main.A1
g[00018]: ->main.A2
g[00018]: ->main.B2
g[00018]: ->main.C2
g[00018]: ->main.D
g[00018]: <-main.D
g[00018]: <-main.C2
g[00018]: <-main.B2
g[00018]: <-main.A2
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
使用了一个 map 类型变量 m 来保存每个 Goroutine 当前的缩进信息:m 的 key 为 Goroutine 的 ID,值为缩进的层次。然后,考虑到 Trace 函数可能在并发环境中运行,根据“map 不支持并发写”的注意事项,增加了一个 sync.Mutex 实例 mu 用于同步对 m 的写操作。
这样,对于一个 Goroutine 来说,每次刚进入一个函数调用,我们就在输出入口跟踪信息之前,将缩进层次加一,并输出入口跟踪信息,加一后的缩进层次值也保存到 map 中。然后,在函数退出前,我们取出当前缩进层次值并输出出口跟踪信息,之后再将缩进层次减一后保存到 map 中。
除了增加缩进层次信息外,在这一版的 Trace 函数实现中,也把输出出入口跟踪信息的操作提取到了一个独立的函数 printTrace 中,这个函数会根据传入的 Goroutine ID、函数名、箭头类型与缩进层次值,按预定的格式拼接跟踪信息并输出。
上次更新: 2022/10/06, 00:04:41