194 lines
4.0 KiB
Go
194 lines
4.0 KiB
Go
package main
|
|
|
|
import (
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/go-ping/ping"
|
|
"golang.org/x/image/colornames"
|
|
"gonum.org/v1/plot"
|
|
"gonum.org/v1/plot/plotter"
|
|
"gonum.org/v1/plot/vg"
|
|
"gonum.org/v1/plot/vg/draw"
|
|
"gonum.org/v1/plot/vg/vgsvg"
|
|
)
|
|
|
|
type stat struct {
|
|
t time.Duration
|
|
errs int
|
|
ok bool
|
|
}
|
|
|
|
var csec = 0
|
|
var pastHour [3600]stat
|
|
var cmin = 0
|
|
var pastWeek [10080]stat
|
|
|
|
func pinger() {
|
|
var q [60]time.Duration
|
|
|
|
pinger := ping.New("1.1.1.1")
|
|
// pinger.Interval = time.Millisecond * 1000
|
|
pinger.OnRecv = func(p *ping.Packet) {
|
|
pastHour[p.Seq-3600*(p.Seq/3600)] = stat{t: p.Rtt, ok: true}
|
|
sec := p.Seq - 60*(p.Seq/60)
|
|
q[sec] = p.Rtt
|
|
// fmt.Printf("%+v\n", p)
|
|
if p.Seq%60 == 0 {
|
|
var errs int
|
|
var sum time.Duration
|
|
for _, x := range q {
|
|
sum += x
|
|
if sum == 0 {
|
|
errs++
|
|
}
|
|
}
|
|
sum /= (60 - time.Duration(errs))
|
|
pastWeek[(p.Seq-10080*(p.Seq/10080))/60] = stat{t: sum, ok: true}
|
|
// fmt.Println("past minute", sum)
|
|
}
|
|
}
|
|
pinger.OnSend = func(p *ping.Packet) {
|
|
pastHour[p.Seq-3600*(p.Seq/3600)] = stat{t: p.Rtt, ok: true}
|
|
sec := p.Seq - 60*(p.Seq/60)
|
|
csec = p.Seq - 3600*(p.Seq/3600)
|
|
q[sec] = p.Rtt
|
|
// fmt.Printf("%+v\n", p)
|
|
if p.Seq%60 == 0 {
|
|
var sum time.Duration
|
|
for _, x := range q {
|
|
sum += x
|
|
}
|
|
sum /= 60
|
|
cmin = (p.Seq - 10080*(p.Seq/10080)) / 60
|
|
//fmt.Println(cmin)
|
|
pastWeek[(p.Seq-10080*(p.Seq/10080))/60] = stat{t: sum, ok: true}
|
|
// fmt.Println("past minute", sum)
|
|
}
|
|
}
|
|
if len(os.Args) > 1 {
|
|
pinger.SetPrivileged(true)
|
|
}
|
|
if err := pinger.Resolve(); err != nil {
|
|
log.Fatalln(err)
|
|
}
|
|
if err := pinger.Run(); err != nil {
|
|
log.Fatalln(err)
|
|
}
|
|
}
|
|
|
|
func pingEP(w http.ResponseWriter, r *http.Request) {
|
|
p := plot.New()
|
|
p.Title.Text = "Ping over past hour"
|
|
p.X.Label.Text = "Time (seconds)"
|
|
p.Y.Label.Text = "Ping (ms)"
|
|
|
|
current := csec
|
|
|
|
var period = pastHour[:]
|
|
if r.URL.Query().Get("week") != "" {
|
|
period = pastWeek[:]
|
|
p.Title.Text = "Ping over past week"
|
|
p.X.Label.Text = "Time (minutes)"
|
|
current = cmin
|
|
}
|
|
|
|
maxPing := 0.
|
|
maxErrs := 0
|
|
|
|
var pingpoints = make(plotter.XYs, len(period))
|
|
var errspoints = make(plotter.XYs, len(period))
|
|
for i, x := range period {
|
|
if !x.ok {
|
|
pingpoints = pingpoints[:i]
|
|
errspoints = errspoints[:i]
|
|
break
|
|
}
|
|
|
|
pingpoints[i] = plotter.XY{
|
|
Y: float64(x.t) / float64(time.Millisecond),
|
|
X: float64(i),
|
|
}
|
|
errs := 0
|
|
switch {
|
|
case x.errs != 0:
|
|
errs = x.errs
|
|
case x.t == 0:
|
|
errs = 1
|
|
}
|
|
errspoints[i] = plotter.XY{
|
|
Y: float64(errs),
|
|
X: float64(i),
|
|
}
|
|
|
|
if float64(x.t)/float64(time.Millisecond) > maxPing {
|
|
maxPing = float64(x.t) / float64(time.Millisecond)
|
|
}
|
|
if errs > maxErrs {
|
|
maxErrs = errs
|
|
}
|
|
}
|
|
switch {
|
|
case maxErrs == 0:
|
|
case maxErrs == 1:
|
|
for i := range errspoints {
|
|
errspoints[i].Y *= maxPing
|
|
}
|
|
default:
|
|
for i, x := range errspoints {
|
|
errspoints[i].Y = (x.Y / float64(maxErrs)) * maxPing
|
|
}
|
|
}
|
|
p.Legend.Top = true
|
|
|
|
/*
|
|
plotutil.DefaultColors = []color.Color{
|
|
colornames.Dodgerblue,
|
|
colornames.Darkseagreen,
|
|
colornames.Red,
|
|
}
|
|
plotutil.DefaultDashes = [][]vg.Length{
|
|
{vg.Points(2), vg.Points(4)},
|
|
{},
|
|
{},
|
|
}
|
|
plotutil.AddLines(p,
|
|
"Now", plotter.XYs{{X: float64(current), Y: maxPing}, {X: float64(current), Y: 0}},
|
|
"Ping", pingpoints,
|
|
"Errs", errspoints,
|
|
)*/
|
|
|
|
nowline, err := plotter.NewLine(plotter.XYs{{X: float64(current), Y: maxPing}, {X: float64(current), Y: 0}})
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
nowline.Color = colornames.Dodgerblue
|
|
nowline.Dashes = []vg.Length{vg.Points(2), vg.Points(4)}
|
|
p.Add(nowline)
|
|
p.Legend.Add("Now", nowline)
|
|
|
|
pingline, err := plotter.NewLine(pingpoints)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
pingline.Color = colornames.Darkseagreen
|
|
p.Add(pingline)
|
|
p.Legend.Add("Ping", pingline)
|
|
|
|
errsline, err := plotter.NewLine(errspoints)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
errsline.Color = colornames.Red
|
|
p.Add(errsline)
|
|
p.Legend.Add("Errors", errsline)
|
|
|
|
canv := vgsvg.New(vg.Millimeter*290, vg.Millimeter*200)
|
|
p.Draw(draw.New(canv))
|
|
|
|
w.Header().Set("content-type", "image/svg+xml")
|
|
canv.WriteTo(w)
|
|
}
|