package tracelog import ( "fmt" "io" "log" "net" "os" "strconv" "strings" "github.com/xgadget-lab/nexttrace/trace" ) func RealtimePrinter(res *trace.Result, ttl int) { f, err := os.OpenFile("/tmp/trace.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, os.ModePerm) if err != nil { return } defer func(f *os.File) { err := f.Close() if err != nil { log.Fatal(err) } }(f) multiWriter := io.MultiWriter(os.Stdout, f) log.SetOutput(multiWriter) log.SetFlags(0) var res_str string res_str += fmt.Sprintf("%-2d ", ttl+1) // 去重 var latestIP string tmpMap := make(map[string][]string) for i, v := range res.Hops[ttl] { if v.Address == nil && latestIP != "" { tmpMap[latestIP] = append(tmpMap[latestIP], fmt.Sprintf("%s ms", "*")) continue } else if v.Address == nil { continue } if _, exist := tmpMap[v.Address.String()]; !exist { tmpMap[v.Address.String()] = append(tmpMap[v.Address.String()], strconv.Itoa(i)) // 首次进入 if latestIP == "" { for j := 0; j < i; j++ { tmpMap[v.Address.String()] = append(tmpMap[v.Address.String()], fmt.Sprintf("%s ms", "*")) } } latestIP = v.Address.String() } tmpMap[v.Address.String()] = append(tmpMap[v.Address.String()], fmt.Sprintf("%.2f ms", v.RTT.Seconds()*1000)) } if latestIP == "" { res_str += fmt.Sprintf("%s\n", "*") log.Print(res_str) return } var blockDisplay = false for ip, v := range tmpMap { if blockDisplay { res_str += fmt.Sprintf("%4s", "") } if net.ParseIP(ip).To4() == nil { res_str += fmt.Sprintf("%-25s ", ip) } else { res_str += fmt.Sprintf("%-15s ", ip) } i, _ := strconv.Atoi(v[0]) if res.Hops[ttl][i].Geo.Asnumber != "" { res_str += fmt.Sprintf("AS%-7s", res.Hops[ttl][i].Geo.Asnumber) } else { res_str += fmt.Sprintf(" %-8s", "*") } if net.ParseIP(ip).To4() != nil { whoisFormat := strings.Split(res.Hops[ttl][i].Geo.Whois, "-") if len(whoisFormat) > 1 { whoisFormat[0] = strings.Join(whoisFormat[:2], "-") } if whoisFormat[0] != "" { whoisFormat[0] = "[" + whoisFormat[0] + "]" } res_str += fmt.Sprintf("%-16s", whoisFormat[0]) } if res.Hops[ttl][i].Geo.Country == "" { res.Hops[ttl][i].Geo.Country = "LAN Address" } if net.ParseIP(ip).To4() != nil { res_str += fmt.Sprintf(" %s %s %s %s %-6s\n %-39s ", res.Hops[ttl][i].Geo.Country, res.Hops[ttl][i].Geo.Prov, res.Hops[ttl][i].Geo.City, res.Hops[ttl][i].Geo.District, res.Hops[ttl][i].Geo.Owner, res.Hops[ttl][i].Hostname) } else { res_str += fmt.Sprintf(" %s %s %s %s %-6s\n %-35s ", res.Hops[ttl][i].Geo.Country, res.Hops[ttl][i].Geo.Prov, res.Hops[ttl][i].Geo.City, res.Hops[ttl][i].Geo.District, res.Hops[ttl][i].Geo.Owner, res.Hops[ttl][i].Hostname) } for j := 1; j < len(v); j++ { if len(v) == 2 || j == 1 { res_str += v[j] } else { res_str += fmt.Sprintf("/ %s", v[j]) } } log.Print(res_str) blockDisplay = true } }