218 lines
6.1 KiB
Go
218 lines
6.1 KiB
Go
package main
|
|
|
|
import (
|
|
utils "anytunnel/at-common"
|
|
"encoding/json"
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
"sort"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/dustin/go-humanize"
|
|
ui "gopkg.in/gizak/termui.v2"
|
|
)
|
|
|
|
type Msg struct {
|
|
Code int
|
|
Message string
|
|
Data utils.TrafficStatistics
|
|
}
|
|
|
|
var lastStatistics utils.TrafficStatistics
|
|
|
|
func main() {
|
|
|
|
host := flag.String("host", "127.0.0.1", "cluster's host")
|
|
port := flag.Int("port", 37080, "cluster's api port")
|
|
flag.Parse()
|
|
var err error
|
|
url := fmt.Sprintf("https://%s:%d/traffic/count", *host, *port)
|
|
|
|
err = ui.Init()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer ui.Close()
|
|
// handle key q pressing
|
|
ui.Handle("/sys/kbd/q", func(ui.Event) {
|
|
// press q to quit
|
|
ui.StopLoop()
|
|
})
|
|
var first = true
|
|
|
|
var sleep = 2
|
|
go func() {
|
|
for {
|
|
statistics, err := getData(url)
|
|
if first {
|
|
first = false
|
|
lastStatistics = statistics
|
|
}
|
|
if err != nil {
|
|
fmt.Printf("ERR:%s\n", err)
|
|
os.Exit(0)
|
|
}
|
|
speedUpload := humanize.Bytes((statistics.Total.UploadBytes-lastStatistics.Total.UploadBytes)/uint64(sleep)) + "/s"
|
|
speedDownload := humanize.Bytes((statistics.Total.DownloadBytes-lastStatistics.Total.DownloadBytes)/uint64(sleep)) + "/s"
|
|
speedTotal := humanize.Bytes((statistics.Total.UploadBytes+statistics.Total.DownloadBytes-lastStatistics.Total.DownloadBytes-lastStatistics.Total.UploadBytes)/uint64(sleep)) + "/s"
|
|
|
|
ui.Clear()
|
|
table2 := ui.NewTable()
|
|
table2.FgColor = ui.ColorYellow
|
|
table2.BgColor = ui.ColorBlack
|
|
table2.BorderFg = ui.ColorYellow
|
|
table2.TextAlign = ui.AlignCenter
|
|
table2.Separator = true
|
|
table2.Border = true
|
|
table2.Rows = [][]string{
|
|
[]string{"Tunnels", "Servers", "Clients", "Connections", "Upload", "Download", "Total"},
|
|
[]string{strconv.Itoa(statistics.Total.Tunnels),
|
|
strconv.Itoa(statistics.Total.Servers),
|
|
strconv.Itoa(statistics.Total.Clients),
|
|
strconv.Itoa(statistics.Total.Connections),
|
|
strconv.FormatUint(statistics.Total.UploadBytes, 10) + " / " + humanize.Bytes(statistics.Total.UploadBytes) + " (" + speedUpload + ")",
|
|
strconv.FormatUint(statistics.Total.DownloadBytes, 10) + " / " + humanize.Bytes(statistics.Total.DownloadBytes) + " (" + speedDownload + ")",
|
|
strconv.FormatUint(statistics.Total.TotalBytes, 10) + " / " + humanize.Bytes(statistics.Total.TotalBytes) + " (" + speedTotal + ")",
|
|
},
|
|
}
|
|
table2.Analysis()
|
|
table2.SetSize()
|
|
|
|
table3 := ui.NewTable()
|
|
table3.FgColor = ui.ColorWhite
|
|
table3.BgColor = ui.ColorDefault
|
|
table3.TextAlign = ui.AlignCenter
|
|
table3.Separator = true
|
|
table3.Border = true
|
|
table3.Rows = [][]string{
|
|
[]string{"TunnelID", "Connections", "Upload", "Download", "Total", "Limit"},
|
|
}
|
|
for _, total := range sortTunnels(statistics.Traffic, 20) {
|
|
TunnelID := strconv.FormatUint(total["TunnelID"], 10)
|
|
speedUpload := ""
|
|
speedDownload := ""
|
|
speedTotal := ""
|
|
var connections uint64
|
|
if v, ok := lastStatistics.Traffic[TunnelID]; ok {
|
|
speedUpload = humanize.Bytes((total["positive"]-v["positive"])/uint64(sleep)) + "/s"
|
|
speedDownload = humanize.Bytes((total["negative"]-v["negative"])/uint64(sleep)) + "/s"
|
|
_speedTotal := (total["positive"] + total["negative"] - v["negative"] - v["positive"]) / uint64(sleep)
|
|
speedTotal = humanize.Bytes(_speedTotal) + "/s"
|
|
if total["limit"] > 0 {
|
|
connections = _speedTotal / total["limit"]
|
|
}
|
|
if _speedTotal > 0 && connections == 0 {
|
|
connections = 1
|
|
}
|
|
|
|
} else {
|
|
speedUpload = ""
|
|
speedDownload = ""
|
|
speedTotal = ""
|
|
}
|
|
table3.Rows = append(table3.Rows, []string{TunnelID,
|
|
strconv.FormatUint(connections, 10),
|
|
strconv.FormatUint(total["positive"], 10) + " / " + humanize.Bytes(total["positive"]) + " (" + speedUpload + ")",
|
|
strconv.FormatUint(total["negative"], 10) + " / " + humanize.Bytes(total["negative"]) + " (" + speedDownload + ")",
|
|
strconv.FormatUint(total["positive"]+total["negative"], 10) + " / " + humanize.Bytes(total["positive"]+total["negative"]) + " (" + speedTotal + ")",
|
|
humanize.Bytes(total["limit"]) + "/s",
|
|
})
|
|
}
|
|
table3.Analysis()
|
|
table3.SetSize()
|
|
|
|
ui.Body.Rows = []*ui.Row{}
|
|
ui.Body.AddRows(
|
|
ui.NewRow(
|
|
ui.NewCol(12, 0, table2),
|
|
),
|
|
ui.NewRow(
|
|
ui.NewCol(12, 0, table3),
|
|
),
|
|
)
|
|
ui.Body.Align()
|
|
ui.Render(ui.Body)
|
|
lastStatistics = statistics
|
|
time.Sleep(time.Second * time.Duration(sleep))
|
|
}
|
|
}()
|
|
|
|
ui.Loop()
|
|
}
|
|
func getData(url string) (statistics utils.TrafficStatistics, err error) {
|
|
body, code, err := utils.HttpGet(url)
|
|
if err != nil {
|
|
err = fmt.Errorf("ERR:%s", err)
|
|
return
|
|
}
|
|
if code != 200 {
|
|
err = fmt.Errorf("ERR: http code %d,body : %s", code, string(body))
|
|
return
|
|
}
|
|
|
|
var msg Msg
|
|
err = json.Unmarshal(body, &msg)
|
|
if err != nil {
|
|
err = fmt.Errorf("ERR:%s", err)
|
|
return
|
|
}
|
|
if msg.Code != 1 {
|
|
err = fmt.Errorf("ERR:%s", msg.Message)
|
|
return
|
|
}
|
|
statistics = msg.Data
|
|
return
|
|
}
|
|
|
|
type DirRange []uint64
|
|
|
|
func (a DirRange) Len() int { return len(a) }
|
|
func (a DirRange) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
|
func (a DirRange) Less(i, j int) bool { return a[i] > a[j] }
|
|
|
|
func sortTunnels(data map[string]map[string]uint64, limit int) []map[string]uint64 {
|
|
sortMap := map[string]uint64{}
|
|
sortUint := DirRange{}
|
|
for k, v := range data {
|
|
var p uint64 = 0
|
|
if ov, ok := lastStatistics.Traffic[k]; ok {
|
|
p = ov["positive"] + ov["negative"]
|
|
}
|
|
total := (v["positive"] + v["negative"]) - p
|
|
sortMap[k] = total
|
|
sortUint = append(sortUint, total)
|
|
}
|
|
sortUintUniqueMap := map[uint64]bool{}
|
|
for _, v := range sortUint {
|
|
sortUintUniqueMap[v] = true
|
|
}
|
|
uniqueSortUint := DirRange{}
|
|
for k := range sortUintUniqueMap {
|
|
uniqueSortUint = append(uniqueSortUint, k)
|
|
}
|
|
sort.Sort(uniqueSortUint)
|
|
reslut := []map[string]uint64{}
|
|
i := 0
|
|
for _, v := range uniqueSortUint {
|
|
for k, v1 := range sortMap {
|
|
if v == v1 {
|
|
id, _ := strconv.ParseUint(k, 10, 64)
|
|
newItem := map[string]uint64{
|
|
"positive": data[k]["positive"],
|
|
"negative": data[k]["negative"],
|
|
"TunnelID": id,
|
|
"limit": data[k]["limit"],
|
|
}
|
|
reslut = append(reslut, newItem)
|
|
}
|
|
}
|
|
i++
|
|
if i > limit {
|
|
break
|
|
}
|
|
}
|
|
return reslut
|
|
}
|