more of them
This commit is contained in:
parent
67d946cf48
commit
ee8716fc99
|
@ -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
|
||||
},
|
||||
}
|
|
@ -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
8
go.mod
|
@ -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
31
go.sum
|
@ -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
167
main.go
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
},
|
||||
}
|
|
@ -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)
|
||||
}
|
Loading…
Reference in New Issue