108 lines
2.7 KiB
Go
108 lines
2.7 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"flag"
|
|
"fmt"
|
|
"github.com/prometheus-community/pro-bing"
|
|
"math"
|
|
"time"
|
|
)
|
|
|
|
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")
|
|
PacketLossCritLimit = flag.Int("pcrit", 25, "package-loss critical limit")
|
|
Host = flag.String("host", "google.com", "host to ping")
|
|
)
|
|
|
|
//goland:noinspection ALL
|
|
const (
|
|
CritColor = "ff5050"
|
|
WarnColor = "ffbf00"
|
|
ResetColor = "{F-}"
|
|
)
|
|
|
|
type WaybarOut struct {
|
|
Class string `json:"class"`
|
|
Text string `json:"text"`
|
|
}
|
|
|
|
func formatLine(stats *probing.Statistics) {
|
|
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)
|
|
return
|
|
}
|
|
|
|
rttColor := ResetColor
|
|
packetColor := ResetColor
|
|
|
|
switch {
|
|
case int(stats.AvgRtt.Milliseconds()) >= *PingWarningLimit:
|
|
rttColor = fmt.Sprintf("%%{F#%s}", WarnColor)
|
|
case int(stats.AvgRtt.Milliseconds()) >= *PingCritLimit:
|
|
rttColor = fmt.Sprintf("%%{F#%s}", CritColor)
|
|
}
|
|
|
|
switch {
|
|
case int(math.Round(stats.PacketLoss)) >= *PacketLossWarnLimit:
|
|
packetColor = fmt.Sprintf("%%{F#%s}", WarnColor)
|
|
case int(math.Round(stats.PacketLoss)) >= *PacketLossCritLimit:
|
|
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)))
|
|
}
|
|
|
|
func formatLineWaybar(stats *probing.Statistics) {
|
|
res := new(WaybarOut)
|
|
|
|
res.Text = fmt.Sprintf("\uE4E2 %dms \uF1B2 %d%%", int(stats.AvgRtt.Milliseconds()), int(math.Round(stats.PacketLoss)))
|
|
res.Class = "good"
|
|
|
|
switch {
|
|
case int(math.Round(stats.PacketLoss)) >= *PacketLossWarnLimit || int(stats.AvgRtt.Milliseconds()) >= *PingWarningLimit:
|
|
res.Class = "warning"
|
|
case int(math.Round(stats.PacketLoss)) >= *PacketLossCritLimit || int(stats.AvgRtt.Milliseconds()) >= *PingCritLimit:
|
|
res.Class = "critical"
|
|
}
|
|
|
|
jOut, err := json.Marshal(res)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
fmt.Println(string(jOut))
|
|
}
|
|
|
|
func main() {
|
|
flag.Parse()
|
|
|
|
for {
|
|
pinger, err := probing.NewPinger(*Host)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
goto sleep
|
|
}
|
|
pinger.Count = *PingCount
|
|
if *Waybar {
|
|
pinger.OnFinish = formatLineWaybar
|
|
} else {
|
|
pinger.OnFinish = formatLine
|
|
}
|
|
|
|
if pinger.Run() != nil {
|
|
fmt.Println(err)
|
|
}
|
|
|
|
sleep:
|
|
time.Sleep(time.Duration(*PingInterval) * time.Second)
|
|
}
|
|
}
|