mirror of
https://github.com/taigrr/wtf
synced 2025-01-18 04:03:14 -08:00
142 lines
3.4 KiB
Go
142 lines
3.4 KiB
Go
package resourceusage
|
|
|
|
import (
|
|
"code.cloudfoundry.org/bytefmt"
|
|
"fmt"
|
|
"github.com/c9s/goprocinfo/linux"
|
|
"github.com/rivo/tview"
|
|
"github.com/senorprogrammer/wtf/wtf"
|
|
)
|
|
|
|
var started = false
|
|
var ok = true
|
|
var prevStats []linux.CPUStat
|
|
|
|
// Widget define wtf widget to register widget later
|
|
type Widget struct {
|
|
wtf.BarGraph
|
|
}
|
|
|
|
// NewWidget Make new instance of widget
|
|
func NewWidget(app *tview.Application) *Widget {
|
|
widget := Widget{
|
|
BarGraph: wtf.NewBarGraph(app, "Resource Usage", "resourceusage", false),
|
|
}
|
|
|
|
widget.View.SetWrap(true)
|
|
widget.View.SetWordWrap(true)
|
|
|
|
return &widget
|
|
}
|
|
|
|
/* -------------------- Exported Functions -------------------- */
|
|
|
|
// MakeGraph - Load the dead drop stats
|
|
func MakeGraph(widget *Widget) {
|
|
|
|
cpuStat, err := linux.ReadStat("/proc/stat")
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
var stats = make([]wtf.Bar, len(cpuStat.CPUStats)+2)
|
|
|
|
for i, stat := range cpuStat.CPUStats {
|
|
prevStat := stat
|
|
if len(prevStats) > i {
|
|
prevStat = prevStats[i]
|
|
} else {
|
|
prevStats = append(prevStats, stat)
|
|
}
|
|
|
|
// based on htop algorithm described here: https://stackoverflow.com/a/23376195/1516085
|
|
prevIdle := prevStat.Idle + prevStat.IOWait
|
|
idle := stat.Idle + stat.IOWait
|
|
|
|
prevNonIdle := prevStat.User + prevStat.Nice + prevStat.System + prevStat.IRQ + prevStat.SoftIRQ + prevStat.Steal
|
|
nonIdle := stat.User + stat.Nice + stat.System + stat.IRQ + stat.SoftIRQ + stat.Steal
|
|
|
|
prevTotal := prevIdle + prevNonIdle
|
|
total := idle + nonIdle
|
|
|
|
// differentiate: actual value minus the previous one
|
|
difference := total - prevTotal
|
|
idled := idle - prevIdle
|
|
|
|
percentage := float64(0)
|
|
if difference > 0 {
|
|
percentage = float64(difference-idled) / float64(difference)
|
|
}
|
|
|
|
bar := wtf.Bar{
|
|
Label: fmt.Sprint(i),
|
|
Percent: int(percentage * 100),
|
|
ValueLabel: fmt.Sprintf("%d%%", int(percentage*100)),
|
|
}
|
|
|
|
stats[i] = bar
|
|
prevStats[i] = stat
|
|
}
|
|
|
|
memInfo, err := linux.ReadMemInfo("/proc/meminfo")
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
memIndex := len(cpuStat.CPUStats)
|
|
memUsed := memInfo.MemTotal - memInfo.MemAvailable
|
|
memPercent := float64(memUsed) / float64(memInfo.MemTotal)
|
|
|
|
usedMemLabel := bytefmt.ByteSize(memUsed * bytefmt.KILOBYTE)
|
|
totalMemLabel := bytefmt.ByteSize(memInfo.MemTotal * bytefmt.KILOBYTE)
|
|
|
|
if usedMemLabel[len(usedMemLabel)-1] == totalMemLabel[len(totalMemLabel)-1] {
|
|
usedMemLabel = usedMemLabel[:len(usedMemLabel)-1]
|
|
}
|
|
|
|
stats[memIndex] = wtf.Bar{
|
|
Label: "Mem",
|
|
Percent: int(memPercent * 100),
|
|
ValueLabel: fmt.Sprintf("%s/%s", usedMemLabel, totalMemLabel),
|
|
}
|
|
|
|
swapIndex := len(cpuStat.CPUStats) + 1
|
|
swapUsed := memInfo.SwapTotal - memInfo.SwapFree
|
|
swapPercent := float64(swapUsed) / float64(memInfo.SwapTotal)
|
|
|
|
usedSwapLabel := bytefmt.ByteSize(swapUsed * bytefmt.KILOBYTE)
|
|
totalSwapLabel := bytefmt.ByteSize(memInfo.SwapTotal * bytefmt.KILOBYTE)
|
|
|
|
if usedSwapLabel[len(usedSwapLabel)-1] == totalMemLabel[len(totalSwapLabel)-1] {
|
|
usedSwapLabel = usedSwapLabel[:len(usedSwapLabel)-1]
|
|
}
|
|
|
|
stats[swapIndex] = wtf.Bar{
|
|
Label: "Swp",
|
|
Percent: int(swapPercent * 100),
|
|
ValueLabel: fmt.Sprintf("%s/%s", usedSwapLabel, totalSwapLabel),
|
|
}
|
|
|
|
widget.BarGraph.BuildBars(stats[:])
|
|
|
|
}
|
|
|
|
// Refresh & update after interval time
|
|
func (widget *Widget) Refresh() {
|
|
|
|
if widget.Disabled() {
|
|
return
|
|
}
|
|
|
|
widget.View.Clear()
|
|
|
|
display(widget)
|
|
|
|
}
|
|
|
|
/* -------------------- Unexported Functions -------------------- */
|
|
|
|
func display(widget *Widget) {
|
|
MakeGraph(widget)
|
|
}
|