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) } }