more of them

This commit is contained in:
Jan Delta 2022-10-06 08:47:43 +09:00
parent 67d946cf48
commit ee8716fc99
7 changed files with 428 additions and 161 deletions

49
cpu.go Normal file
View File

@ -0,0 +1,49 @@
package main
import (
"log"
"strconv"
"github.com/shirou/gopsutil/v3/cpu"
)
var cpuCount = 0
func init() {
count, err := cpu.Counts(true)
if err != nil {
panic(err)
}
cpuInfo.NoVals = count + 1
cpuCount = count
cpuInfo.ValTags = make([]string, count+1)
cpuInfo.ValTags[0] = "Avg"
for i := range cpuInfo.ValTags[1:] {
cpuInfo.ValTags[1+i] = "#" + strconv.Itoa(i+1)
}
}
var cpuInfo = provider{
NoVals: cpuCount + 1,
Fetch: func() []float64 {
var fs = make([]float64, cpuCount+1)
cper, err := cpu.Percent(0, true)
if err != nil {
log.Println(err)
return fs
}
var sum float64
for _, x := range cper {
sum += x
}
sum /= float64(len(cper))
fs[0] = sum
copy(fs[1:], cper)
return fs
},
}

107
generic.go Normal file
View File

@ -0,0 +1,107 @@
package main
import (
"net/http"
"sync"
"time"
"gonum.org/v1/plot"
"gonum.org/v1/plot/plotter"
"gonum.org/v1/plot/plotutil"
"gonum.org/v1/plot/vg"
"gonum.org/v1/plot/vg/draw"
"gonum.org/v1/plot/vg/vgsvg"
)
type statSheet struct {
Values []float64
Ok bool
}
type provider struct {
Current int
Values [3600]statSheet
Fetch func() []float64
NoVals int
ValTags []string
Name string
Y string
}
func (p *provider) Run() {
tick := time.NewTicker(time.Second)
for {
<-tick.C
vals := p.Fetch()
// fmt.Println("tick", p.Name, vals)
p.Values[p.Current] = statSheet{vals, true}
p.Current++
if p.Current >= 3600 {
p.Current = 0
}
}
}
var xypool = sync.Pool{
New: func() any {
return make(plotter.XYs, 3600)
},
}
func (prov *provider) Render(w http.ResponseWriter, r *http.Request) {
p := plot.New()
p.Legend.Top = true
p.Title.Text = prov.Name
p.X.Label.Text = "Time (seconds)"
p.Y.Label.Text = prov.Y
var points = make([]plotter.XYs, prov.NoVals)
var allocs = make([]plotter.XYs, prov.NoVals)
defer func() {
for _, x := range allocs {
xypool.Put(x)
}
}()
for i := range points {
alloc := xypool.Get().(plotter.XYs)
points[i] = alloc
allocs[i] = alloc
}
for i, x := range prov.Values {
if !x.Ok {
for yi := range points {
points[yi] = points[yi][:i]
}
break
}
for yi, y := range x.Values {
points[yi][i] = plotter.XY{
Y: y,
X: float64(i),
}
}
}
for i, x := range points {
line, err := plotter.NewLine(x)
if err != nil {
panic(err)
}
line.Color = plotutil.Color(i)
line.Dashes = plotutil.Dashes(i)
p.Add(line)
p.Legend.Add(prov.ValTags[i], line)
}
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)
}

8
go.mod
View File

@ -7,10 +7,18 @@ require (
github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b // indirect
github.com/go-fonts/liberation v0.2.0 // indirect
github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-pdf/fpdf v0.6.0 // indirect
github.com/go-ping/ping v1.1.0 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/google/uuid v1.2.0 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/shirou/gopsutil/v3 v3.22.9 // indirect
github.com/tklauser/go-sysconf v0.3.10 // indirect
github.com/tklauser/numcpus v0.4.0 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69 // indirect
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect

31
go.sum
View File

@ -8,6 +8,7 @@ github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGW
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g=
github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks=
@ -16,6 +17,8 @@ github.com/go-fonts/liberation v0.2.0/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2H
github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY=
github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81 h1:6zl3BbBhdnMkpSj2YY30qV3gDcVBGtFgVsV3+/i+mKQ=
github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M=
github.com/go-pdf/fpdf v0.6.0 h1:MlgtGIfsdMEEQJr2le6b/HNr1ZlQwxyWr77r2aj2U/8=
github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M=
@ -23,20 +26,40 @@ github.com/go-ping/ping v1.1.0 h1:3MCGhVX4fyEUuhsfwPrsEdQw6xspHkv5zHsiSoDFZYw=
github.com/go-ping/ping v1.1.0/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY=
github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w=
github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk=
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/gopsutil/v3 v3.22.9 h1:yibtJhIVEMcdw+tCTbOPiF1VcsuDeTE4utJ8Dm4c5eA=
github.com/shirou/gopsutil/v3 v3.22.9/go.mod h1:bBYl1kjgEJpWpxeHmLI+dVHWtyAwfcmSBLDsp2TNT8A=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw=
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o=
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@ -61,11 +84,15 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cO
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005 h1:pDMpM2zh2MT0kHy037cKlSby2nEhD50SYqwQk76Nm40=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@ -79,7 +106,11 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/plot v0.12.0 h1:y1ZNmfz/xHuHvtgFe8USZVyykQo5ERXPnspQNVK15Og=
gonum.org/v1/plot v0.12.0/go.mod h1:PgiMf9+3A3PnZdJIciIXmyN1FwdAA6rXELSN761oQkw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=

167
main.go
View File

@ -1,175 +1,20 @@
package main
import (
"image/color"
"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/plotutil"
"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 main() {
go pinger()
go cpuInfo.Run()
go ramInfo.Run()
http.Handle("/", http.HandlerFunc(func(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)"
log.Println("listening on :7123")
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 = x.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
}
}
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,
)
p.Legend.Top = true
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)
}))
http.Handle("/ping", http.HandlerFunc(pingEP))
http.Handle("/cpu", http.HandlerFunc(cpuInfo.Render))
http.Handle("/ram", http.HandlerFunc(ramInfo.Render))
http.Handle("/favicon.ico", http.NotFoundHandler())
if err := http.ListenAndServe(":7123", nil); err != nil {
log.Fatalln(err)

34
memory.go Normal file
View File

@ -0,0 +1,34 @@
package main
import (
"log"
"github.com/shirou/gopsutil/v3/mem"
)
var ramInfo = provider{
NoVals: 5,
ValTags: []string{
"Used",
"Cached",
"Available",
"Swap Cached",
"Swap Free",
},
Fetch: func() []float64 {
mem, err := mem.VirtualMemory()
if err != nil {
log.Println(err)
return []float64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
}
return []float64{
float64(mem.Used) / 1000 / 1000,
float64(mem.Cached) / 1000 / 1000,
float64(mem.Available) / 1000 / 1000,
float64(mem.SwapCached) / 1000 / 1000,
float64(mem.SwapFree) / 1000 / 1000,
}
},
}

193
ping.go Normal file
View File

@ -0,0 +1,193 @@
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)
}