package main
import (
"fmt"
"strconv"
"sync"
)
type Spaninfo struct {
AppNames []string `json:"appNames"`
ContainErr bool `json:"containErr"`
Attrs map[string]interface{} `json:"attrs"`
CspanMethod map[string]string `json:"cspanid_method"`
Cspanids []string `json:"cspanids"`
EndTime string `json:"endTime"` //Timestamp
Host []string `json:"host"`
LogName []string `json:"logName"`
Message []string `json:"message"`
OdinLeaf []string `json:"odinLeaf"`
Spanid string `json:"spanid"`
StartTime string `json:"startTime"` //Timestamp
Su []string `json:"sus"`
Traceid string `json:"traceid"`
URI string `json:"uri"`
//span级别聚合 有先后
Broken bool `json:"broken"`
Duration int `json:"duration"`
//trace级别聚合 有先后
Pspanid string `json:"pspanid"`
Method string `json:"method"`
Children []*Spaninfo `json:"children"`
}
func main() {
m := sync.Map{}
for i := 2; i < 10; i++ {
s := Spaninfo{
Spanid: strconv.Itoa(i),
Pspanid: strconv.Itoa(i - 1),
}
m.Store(strconv.Itoa(i), &s)
}
//组装完毕
m.Store("1", &Spaninfo{Spanid: "1", Pspanid: ""})
m.Store("11", &Spaninfo{Spanid: "11", Pspanid: ""})
m.Store("11", &Spaninfo{Spanid: "12", Pspanid: "11"})
root := &Spaninfo{}
m.Range(func(ik, iv interface{}) bool {
e := &Spaninfo{}
if spaninfo, ok := iv.(*Spaninfo); ok {
e = spaninfo
} else {
return true
}
pid := e.Pspanid
if pid == "" {//将没有父节点的节点放倒根目录下
root.Children = append(root.Children, e)
}else {//把有父节点的节点,找到父节点,然后给父节点添加子节点
ipnode,_ := m.Load(pid)
pnode,_ := ipnode.(*Spaninfo)
pnode.Children = append(pnode.Children,e)
}
return true
})
for _,r := range root.Children {
//遍历树
p := make([]string, 0)
var ListP = make([][]string, 0, 10)
ListPath(r, p, &ListP)
fmt.Println("\n")
for _, p := range ListP {
for _, v := range p {
fmt.Print(v, ",")
}
}
fmt.Println("\n")
}
}
//遍历树节点
func ListPath(root *Spaninfo, path []string, pathList *[][]string) {
if root == nil {
return
}
if root.Children == nil || len(root.Children) == 0 {
path = append(path, root.Spanid)
newPath := make([]string, len(path))
copy(newPath, path) //这一步必须拷贝出来,不然path这个切片视图,如果值改变,会影响pathList的值
*pathList = append(*pathList, newPath)
} else {
path = append(path, root.Spanid)
childs := root.Children
for _, v := range childs {
ListPath(v, path, pathList)
}
}
}