From f5143c56a94c7cf97fa195b588e14470a31685b2 Mon Sep 17 00:00:00 2001 From: Giovanni Harting <539@idlegandalf.com> Date: Wed, 15 Nov 2023 20:18:43 +0100 Subject: [PATCH] made ping continuous to make response quicker --- .idea/.gitignore | 1 + go.mod | 13 +++-- go.sum | 22 ++++---- ping-package.go | 135 +++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 134 insertions(+), 37 deletions(-) create mode 100644 .idea/.gitignore diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..62c8935 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1 @@ +.idea/ \ No newline at end of file diff --git a/go.mod b/go.mod index aa1cfc7..750bdce 100644 --- a/go.mod +++ b/go.mod @@ -2,11 +2,14 @@ module ping-package go 1.19 -require github.com/prometheus-community/pro-bing v0.1.0 +require ( + github.com/montanaflynn/stats v0.7.1 + github.com/prometheus-community/pro-bing v0.3.0 +) require ( - github.com/google/uuid v1.3.0 // indirect - golang.org/x/net v0.9.0 // indirect - golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.7.0 // indirect + github.com/google/uuid v1.4.0 // indirect + golang.org/x/net v0.18.0 // indirect + golang.org/x/sync v0.5.0 // indirect + golang.org/x/sys v0.14.0 // indirect ) diff --git a/go.sum b/go.sum index 4c7e5af..09b6eb4 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,12 @@ -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/prometheus-community/pro-bing v0.1.0 h1:zjzLGhfNPP0bP1OlzGB+SJcguOViw7df12LPg2vUJh8= -github.com/prometheus-community/pro-bing v0.1.0/go.mod h1:BpWlHurD9flHtzq8wrh8QGWYz9ka9z9ZJAyOel8ej58= -golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= +github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/prometheus-community/pro-bing v0.3.0 h1:SFT6gHqXwbItEDJhTkzPWVqU6CLEtqEfNAPp47RUON4= +github.com/prometheus-community/pro-bing v0.3.0/go.mod h1:p9dLb9zdmv+eLxWfCT6jESWuDrS+YzpPkQBgysQF8a0= +golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/ping-package.go b/ping-package.go index ba521d3..65daa0b 100644 --- a/ping-package.go +++ b/ping-package.go @@ -4,15 +4,24 @@ import ( "encoding/json" "flag" "fmt" + "github.com/montanaflynn/stats" "github.com/prometheus-community/pro-bing" "math" + "os" + "os/signal" + "sync" + "syscall" "time" ) +type ContinuousPinger struct { + Pings []*probing.Packet + Lock *sync.RWMutex +} + var ( Waybar = flag.Bool("waybar", false, "output waybar json format") PingCount = flag.Int("count", 3, "how many pings to average") - PingInterval = flag.Int("i", 5, "ping interval") PingWarningLimit = flag.Int("warn", 50, "ping warning limit") PingCritLimit = flag.Int("crit", 100, "ping critical limit") PacketLossWarnLimit = flag.Int("pwarn", 10, "package-loss warning limit") @@ -20,6 +29,12 @@ var ( Host = flag.String("host", "google.com", "host to ping") ) +type PingStats struct { + AvgRtt time.Duration + StdDev time.Duration + PacketLoss float64 +} + //goland:noinspection ALL const ( CritColor = "ff5050" @@ -32,8 +47,8 @@ type WaybarOut struct { Text string `json:"text"` } -func formatLine(stats *probing.Statistics) { - if stats.PacketLoss >= 100.0 || stats.PacketsRecv == 0 { +func formatLine(stats *PingStats) { + if stats.PacketLoss >= 100.0 { // fontawesome/forkawesome doesn't have the fitting icon... // so this is the utf-8 icon/emoji fmt.Printf("%%{F#%s}🚫\n", CritColor) @@ -57,13 +72,13 @@ func formatLine(stats *probing.Statistics) { packetColor = fmt.Sprintf("%%{F#%s}", CritColor) } - fmt.Printf("%s\uE4E2 %dms %s\uF1B2 %d%%\n", rttColor, stats.AvgRtt.Milliseconds(), packetColor, int(math.Round(stats.PacketLoss))) + fmt.Printf("%s\uE4E2 %d \uE43C %dms %s\uF1B2 %d%%\n", rttColor, stats.AvgRtt.Milliseconds(), stats.StdDev.Milliseconds(), packetColor, int(math.Round(stats.PacketLoss))) } -func formatLineWaybar(stats *probing.Statistics) { +func formatLineWaybar(stats *PingStats) { res := new(WaybarOut) - res.Text = fmt.Sprintf("\uE4E2 %dms \uF1B2 %d%%", int(stats.AvgRtt.Milliseconds()), int(math.Round(stats.PacketLoss))) + res.Text = fmt.Sprintf("\uE4E2 %d \uE43C %dms \uF1B2 %d%%", stats.AvgRtt.Milliseconds(), stats.StdDev.Milliseconds(), int(math.Round(stats.PacketLoss))) res.Class = "good" switch { @@ -82,28 +97,104 @@ func formatLineWaybar(stats *probing.Statistics) { fmt.Println(string(jOut)) } +func (cp *ContinuousPinger) Push(packet *probing.Packet) { + cp.Lock.Lock() + defer cp.Lock.Unlock() + if len(cp.Pings) >= *PingCount { + cp.Pings = cp.Pings[:len(cp.Pings)-1] + } + cp.Pings = append([]*probing.Packet{packet}, cp.Pings...) +} + +func (cp *ContinuousPinger) Stats(dSent, dReceive int) (*PingStats, error) { + cp.Lock.RLock() + defer cp.Lock.RUnlock() + var rttArray []float64 + ps := new(PingStats) + + var sum int64 + var pkgsInArr int + for _, pkg := range cp.Pings { + if pkg != nil { + rttArray = append(rttArray, float64(pkg.Rtt)) + sum += int64(pkg.Rtt) + pkgsInArr++ + } + } + ps.AvgRtt = time.Duration(sum / int64(pkgsInArr)) + ps.PacketLoss = 100.0 - (float64(dReceive) / float64(dSent) * 100.0) + stdDev, err := stats.StandardDeviation(rttArray) + if err != nil { + return nil, err + } + ps.StdDev = time.Duration(stdDev) + + return ps, nil +} + func main() { flag.Parse() + killSignals := make(chan os.Signal, 1) + signal.Notify(killSignals, syscall.SIGINT, syscall.SIGTERM) - for { - pinger, err := probing.NewPinger(*Host) + lp := new(ContinuousPinger) + lp.Pings = make([]*probing.Packet, *PingCount) + lp.Lock = new(sync.RWMutex) + ts := 0 + tr := 0 + lr := time.Now().UTC() + + pinger, err := probing.NewPinger(*Host) + pinger.RecordRtts = false + + pinger.OnRecv = func(pkt *probing.Packet) { + lp.Push(pkt) + pStats, err := lp.Stats(pinger.PacketsSent-ts, pinger.PacketsRecv-tr) + lr = time.Now().UTC() + ts = pinger.PacketsSent + tr = pinger.PacketsRecv if err != nil { fmt.Println(err) - goto sleep - } - pinger.Count = *PingCount - pinger.Timeout = 3 * time.Second - if *Waybar { - pinger.OnFinish = formatLineWaybar + } else if *Waybar { + formatLineWaybar(pStats) } else { - pinger.OnFinish = formatLine + formatLine(pStats) } - - if pinger.Run() != nil { - fmt.Println(err) - } - - sleep: - time.Sleep(time.Duration(*PingInterval) * time.Second) } + + go func() { + for { + if time.Since(lr).Milliseconds() > 1500 { + pStats, err := lp.Stats(pinger.PacketsSent-ts, pinger.PacketsRecv-tr) + ts = pinger.PacketsSent + tr = pinger.PacketsRecv + if err != nil { + fmt.Println(err) + } else if *Waybar { + formatLineWaybar(pStats) + } else { + formatLine(pStats) + } + } + time.Sleep(time.Second) + } + }() + + go func() { + for { + if err = pinger.Run(); err != nil { + fmt.Println(err) + time.Sleep(time.Second) + } + } + }() + +killLoop: + for { + select { + case <-killSignals: + break killLoop + } + } + pinger.Stop() }