Go vet/lint cleanups

This commit is contained in:
Sean E. Russell 2020-04-27 20:33:41 -05:00
parent 1e78e6faa0
commit 285d4d0297
19 changed files with 271 additions and 295 deletions

View File

@ -25,6 +25,7 @@ import (
"github.com/xxxserxxx/gotop/v4/devices"
"github.com/xxxserxxx/gotop/v4/layout"
"github.com/xxxserxxx/gotop/v4/logging"
"github.com/xxxserxxx/gotop/v4/widgets"
w "github.com/xxxserxxx/gotop/v4/widgets"
)
@ -38,7 +39,9 @@ const (
)
var (
Version = "0.0.0"
// Version of the program; set during build from git tags
Version = "0.0.0"
// BuildDate when the program was compiled; set during build
BuildDate = "Hadean"
conf gotop.Config
help *w.HelpMenu
@ -104,9 +107,9 @@ func parseArgs(conf *gotop.Config) error {
if *list != "" {
switch *list {
case "layouts":
fmt.Println(LAYOUTS)
fmt.Println(_layouts)
case "colorschemes":
fmt.Println(COLORSCHEMES)
fmt.Println(_colorschemes)
case "paths":
fmt.Println("Loadable colorschemes & layouts, and the config file, are searched for, in order:")
paths := make([]string, 0)
@ -118,7 +121,7 @@ func parseArgs(conf *gotop.Config) error {
case "devices":
listDevices()
case "keys":
fmt.Println(KEYS)
fmt.Println(widgets.KEYBINDS)
default:
fmt.Printf("Unknown option \"%s\"; try layouts, colorschemes, keys, paths, or devices\n", *list)
os.Exit(1)
@ -391,7 +394,7 @@ func run() int {
}
return 1
}
if err := ui.Init(); err != nil {
if err = ui.Init(); err != nil {
stderrLogger.Print(err)
return 1
}
@ -481,40 +484,12 @@ func listDevices() {
}
}
const KEYS = `Quit: q or <C-c>
Process navigation:
k and <Up>: up
j and <Down>: down
<C-u>: half page up
<C-d>: half page down
<C-b>: full page up
<C-f>: full page down
gg and <Home>: jump to top
G and <End>: jump to bottom
Process actions:
<Tab>: toggle process grouping
dd: kill selected process or group of processes with SIGTERM
d3: kill selected process or group of processes with SIGQUIT
d9: kill selected process or group of processes with SIGKILL
Process sorting
c: CPU
m: Mem
p: PID
Process filtering:
/: start editing filter
(while editing):
<Enter> accept filter
<C-c> and <Escape>: clear filter
CPU and Mem graph scaling:
h: scale in
l: scale out
?: toggles keybind help menu`
const LAYOUTS = `Built-in layouts:
const _layouts = `Built-in layouts:
default
minimal
battery
kitchensink`
const COLORSCHEMES = `Built-in colorschemes:
const _colorschemes = `Built-in colorschemes:
default
default-dark (for white background)
solarized

View File

@ -1,6 +1,8 @@
package colorschemes
import (
"github.com/shibukawa/configdir"
"path/filepath"
"reflect"
"testing"
)
@ -8,8 +10,10 @@ import (
func TestColorRegistry(t *testing.T) {
colors := []string{"default", "default-dark", "solarized", "solarized16-dark", "solarized16-light", "monokai", "vice"}
zeroCS := Colorscheme{}
cd := configdir.New("", "gotop")
cd.LocalPath, _ = filepath.Abs(".")
for _, cn := range colors {
c, e := FromName("", cn)
c, e := FromName(cd, cn)
if e != nil {
t.Errorf("unexpected error fetching built-in color %s: %s", cn, e)
}

View File

@ -48,7 +48,7 @@ func NewConfig() Config {
PercpuLoad: true,
TempScale: widgets.Celsius,
Statusbar: false,
NetInterface: widgets.NET_INTERFACE_ALL,
NetInterface: widgets.NetInterfaceAll,
MaxLogSize: 5000000,
Layout: "default",
ExtensionVars: make(map[string]string),
@ -169,16 +169,16 @@ func load(in io.Reader, conf *Config) error {
return nil
}
func (c *Config) Write() (string, error) {
func (conf *Config) Write() (string, error) {
cfn := "gotop.conf"
ds := c.ConfigDir.QueryFolders(configdir.Global)
ds := conf.ConfigDir.QueryFolders(configdir.Global)
if len(ds) == 0 {
ds = c.ConfigDir.QueryFolders(configdir.Local)
ds = conf.ConfigDir.QueryFolders(configdir.Local)
if len(ds) == 0 {
return "", fmt.Errorf("error locating config folders")
}
}
marshalled := marshal(c)
marshalled := marshal(conf)
err := ds[0].WriteFile(cfn, marshalled)
if err != nil {
return "", err

View File

@ -78,7 +78,6 @@ func RegisterDeviceList(typ string, all func() []string, def func() []string) {
func Devices(domain string, all bool) []string {
if all {
return _devs[domain]
} else {
return _defaults[domain]
}
return _defaults[domain]
}

View File

@ -1,4 +1,3 @@
// Copyright 2020 The gotop Authors Licensed under terms of the LICENSE file in this repository.
package layout
import (
@ -165,7 +164,7 @@ func makeWidget(c gotop.Config, widRule widgetRule) interface{} {
dw := widgets.NewDiskWidget()
w = dw
case "cpu":
cpu := widgets.NewCpuWidget(c.UpdateInterval, c.GraphHorizontalScale, c.AverageLoad, c.PercpuLoad)
cpu := widgets.NewCPUWidget(c.UpdateInterval, c.GraphHorizontalScale, c.AverageLoad, c.PercpuLoad)
assignColors(cpu.Data, c.Colorscheme.CPULines, cpu.LineColors)
w = cpu
case "mem":
@ -228,7 +227,7 @@ func assignColors(data map[string][]float64, colors []int, assign map[string]ui.
func countNumRows(rs [][]widgetRule) int {
var ttl int
for len(rs) > 0 {
ttl += 1
ttl++
line := rs[0]
h := 1
for _, c := range line {

View File

@ -111,7 +111,7 @@ func ParseLayout(i io.Reader) layout {
}
weightTotal += weight
} else {
weightTotal += 1
weightTotal++
}
row = append(row, wr)
}

View File

@ -17,8 +17,6 @@ func TestLogging(t *testing.T) {
defer os.RemoveAll(path)
c := gotop.Config{
MaxLogSize: 300,
LogDir: path,
LogFile: "errors.log",
}
wc, err := New(c)
assert.NoError(t, err)
@ -27,7 +25,7 @@ func TestLogging(t *testing.T) {
}
defer wc.Close()
ds := make([]byte, 100)
for i, _ := range ds {
for i := range ds {
ds[i] = 'x'
}

View File

@ -7,7 +7,6 @@ import (
func ConvertLocalizedString(s string) string {
if strings.ContainsAny(s, ",") {
return strings.Replace(s, ",", ".", 1)
} else {
return s
}
return s
}

View File

@ -62,7 +62,7 @@ func (b *BatteryWidget) EnableMetric() {
}
}
func makeId(i int) string {
func makeID(i int) string {
return "Batt" + strconv.Itoa(i)
}
@ -70,7 +70,7 @@ func (b *BatteryWidget) Scale(i int) {
b.LineGraph.HorizontalScale = i
}
func (self *BatteryWidget) update() {
func (b *BatteryWidget) update() {
batteries, err := battery.GetAll()
if err != nil {
switch errt := err.(type) {
@ -94,13 +94,13 @@ func (self *BatteryWidget) update() {
}
}
for i, battery := range batteries {
id := makeId(i)
id := makeID(i)
perc := battery.Current / battery.Full
percentFull := math.Abs(perc) * 100.0
self.Data[id] = append(self.Data[id], percentFull)
self.Labels[id] = fmt.Sprintf("%3.0f%% %.0f/%.0f", percentFull, math.Abs(battery.Current), math.Abs(battery.Full))
if self.metric != nil {
self.metric[i].Set(perc)
b.Data[id] = append(b.Data[id], percentFull)
b.Labels[id] = fmt.Sprintf("%3.0f%% %.0f/%.0f", percentFull, math.Abs(battery.Current), math.Abs(battery.Full))
if b.metric != nil {
b.metric[i].Set(perc)
}
}
}

View File

@ -9,16 +9,16 @@ import (
"github.com/distatus/battery"
"github.com/prometheus/client_golang/prometheus"
. "github.com/xxxserxxx/gotop/v4/termui"
"github.com/xxxserxxx/gotop/v4/termui"
)
type BatteryGauge struct {
*Gauge
*termui.Gauge
metric prometheus.Gauge
}
func NewBatteryGauge() *BatteryGauge {
self := &BatteryGauge{Gauge: NewGauge()}
self := &BatteryGauge{Gauge: termui.NewGauge()}
self.Title = " Power Level "
self.update()
@ -56,7 +56,7 @@ func (b *BatteryGauge) EnableMetric() {
}
}
func (self *BatteryGauge) update() {
func (b *BatteryGauge) update() {
bats, err := battery.GetAll()
if err != nil {
log.Printf("error setting up batteries: %v", err)
@ -78,9 +78,9 @@ func (self *BatteryGauge) update() {
}
tn := (mx - cu) / rate
d, _ := time.ParseDuration(fmt.Sprintf("%fh", tn))
self.Percent = int((cu / mx) * 100.0)
self.Label = fmt.Sprintf(charging, self.Percent, d.Truncate(time.Minute))
if self.metric != nil {
self.metric.Set(cu / mx)
b.Percent = int((cu / mx) * 100.0)
b.Label = fmt.Sprintf(charging, b.Percent, d.Truncate(time.Minute))
if b.metric != nil {
b.metric.Set(cu / mx)
}
}

View File

@ -12,11 +12,11 @@ import (
ui "github.com/xxxserxxx/gotop/v4/termui"
)
type CpuWidget struct {
type CPUWidget struct {
*ui.LineGraph
CpuCount int
CPUCount int
ShowAverageLoad bool
ShowPerCpuLoad bool
ShowPerCPULoad bool
updateInterval time.Duration
updateLock sync.Mutex
metric map[string]prometheus.Gauge
@ -24,20 +24,20 @@ type CpuWidget struct {
var cpuLabels []string
func NewCpuWidget(updateInterval time.Duration, horizontalScale int, showAverageLoad bool, showPerCpuLoad bool) *CpuWidget {
self := &CpuWidget{
func NewCPUWidget(updateInterval time.Duration, horizontalScale int, showAverageLoad bool, showPerCPULoad bool) *CPUWidget {
self := &CPUWidget{
LineGraph: ui.NewLineGraph(),
CpuCount: len(cpuLabels),
CPUCount: len(cpuLabels),
updateInterval: updateInterval,
ShowAverageLoad: showAverageLoad,
ShowPerCpuLoad: showPerCpuLoad,
ShowPerCPULoad: showPerCPULoad,
}
self.Title = " CPU Usage "
self.HorizontalScale = horizontalScale
if !(self.ShowAverageLoad || self.ShowPerCpuLoad) {
if self.CpuCount <= 8 {
self.ShowPerCpuLoad = true
if !(self.ShowAverageLoad || self.ShowPerCPULoad) {
if self.CPUCount <= 8 {
self.ShowPerCPULoad = true
} else {
self.ShowAverageLoad = true
}
@ -47,9 +47,9 @@ func NewCpuWidget(updateInterval time.Duration, horizontalScale int, showAverage
self.Data["AVRG"] = []float64{0}
}
if self.ShowPerCpuLoad {
if self.ShowPerCPULoad {
cpus := make(map[string]int)
devices.UpdateCPU(cpus, self.updateInterval, self.ShowPerCpuLoad)
devices.UpdateCPU(cpus, self.updateInterval, self.ShowPerCPULoad)
for k, v := range cpus {
self.Data[k] = []float64{float64(v)}
}
@ -66,17 +66,17 @@ func NewCpuWidget(updateInterval time.Duration, horizontalScale int, showAverage
return self
}
func (self *CpuWidget) EnableMetric() {
if self.ShowAverageLoad {
self.metric = make(map[string]prometheus.Gauge)
self.metric["AVRG"] = prometheus.NewGauge(prometheus.GaugeOpts{
func (cpu *CPUWidget) EnableMetric() {
if cpu.ShowAverageLoad {
cpu.metric = make(map[string]prometheus.Gauge)
cpu.metric["AVRG"] = prometheus.NewGauge(prometheus.GaugeOpts{
Subsystem: "cpu",
Name: "avg",
})
} else {
cpus := make(map[string]int)
devices.UpdateCPU(cpus, self.updateInterval, self.ShowPerCpuLoad)
self.metric = make(map[string]prometheus.Gauge)
devices.UpdateCPU(cpus, cpu.updateInterval, cpu.ShowPerCPULoad)
cpu.metric = make(map[string]prometheus.Gauge)
for key, perc := range cpus {
gauge := prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: "gotop",
@ -85,53 +85,53 @@ func (self *CpuWidget) EnableMetric() {
})
gauge.Set(float64(perc))
prometheus.MustRegister(gauge)
self.metric[key] = gauge
cpu.metric[key] = gauge
}
}
}
func (b *CpuWidget) Scale(i int) {
b.LineGraph.HorizontalScale = i
func (cpu *CPUWidget) Scale(i int) {
cpu.LineGraph.HorizontalScale = i
}
func (self *CpuWidget) update() {
if self.ShowAverageLoad {
func (cpu *CPUWidget) update() {
if cpu.ShowAverageLoad {
go func() {
cpus := make(map[string]int)
devices.UpdateCPU(cpus, self.updateInterval, false)
self.Lock()
defer self.Unlock()
self.updateLock.Lock()
defer self.updateLock.Unlock()
devices.UpdateCPU(cpus, cpu.updateInterval, false)
cpu.Lock()
defer cpu.Unlock()
cpu.updateLock.Lock()
defer cpu.updateLock.Unlock()
var val float64
for _, v := range cpus {
val = float64(v)
break
}
self.Data["AVRG"] = append(self.Data["AVRG"], val)
self.Labels["AVRG"] = fmt.Sprintf("%3.0f%%", val)
if self.metric != nil {
self.metric["AVRG"].Set(val)
cpu.Data["AVRG"] = append(cpu.Data["AVRG"], val)
cpu.Labels["AVRG"] = fmt.Sprintf("%3.0f%%", val)
if cpu.metric != nil {
cpu.metric["AVRG"].Set(val)
}
}()
}
if self.ShowPerCpuLoad {
if cpu.ShowPerCPULoad {
go func() {
cpus := make(map[string]int)
devices.UpdateCPU(cpus, self.updateInterval, true)
self.Lock()
defer self.Unlock()
self.updateLock.Lock()
defer self.updateLock.Unlock()
devices.UpdateCPU(cpus, cpu.updateInterval, true)
cpu.Lock()
defer cpu.Unlock()
cpu.updateLock.Lock()
defer cpu.updateLock.Unlock()
for key, percent := range cpus {
self.Data[key] = append(self.Data[key], float64(percent))
self.Labels[key] = fmt.Sprintf("%d%%", percent)
if self.metric != nil {
if self.metric[key] == nil {
cpu.Data[key] = append(cpu.Data[key], float64(percent))
cpu.Labels[key] = fmt.Sprintf("%d%%", percent)
if cpu.metric != nil {
if cpu.metric[key] == nil {
log.Printf("no metrics for %s", key)
} else {
self.metric[key].Set(float64(percent))
cpu.metric[key].Set(float64(percent))
}
}
}

View File

@ -64,9 +64,9 @@ func NewDiskWidget() *DiskWidget {
return self
}
func (self *DiskWidget) EnableMetric() {
self.metric = make(map[string]prometheus.Gauge)
for key, part := range self.Partitions {
func (disk *DiskWidget) EnableMetric() {
disk.metric = make(map[string]prometheus.Gauge)
for key, part := range disk.Partitions {
gauge := prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: "gotop",
Subsystem: "disk",
@ -75,11 +75,11 @@ func (self *DiskWidget) EnableMetric() {
})
gauge.Set(float64(part.UsedPercent) / 100.0)
prometheus.MustRegister(gauge)
self.metric[key] = gauge
disk.metric[key] = gauge
}
}
func (self *DiskWidget) update() {
func (disk *DiskWidget) update() {
partitions, err := psDisk.Partitions(false)
if err != nil {
log.Printf("failed to get disk partitions from gopsutil: %v", err)
@ -97,8 +97,8 @@ func (self *DiskWidget) update() {
continue
}
// check if partition doesn't already exist in our list
if _, ok := self.Partitions[partition.Device]; !ok {
self.Partitions[partition.Device] = &Partition{
if _, ok := disk.Partitions[partition.Device]; !ok {
disk.Partitions[partition.Device] = &Partition{
Device: partition.Device,
MountPoint: partition.Mountpoint,
}
@ -107,7 +107,7 @@ func (self *DiskWidget) update() {
// delete a partition if it no longer exists
toDelete := []string{}
for device := range self.Partitions {
for device := range disk.Partitions {
exists := false
for _, partition := range partitions {
if device == partition.Device {
@ -120,11 +120,11 @@ func (self *DiskWidget) update() {
}
}
for _, device := range toDelete {
delete(self.Partitions, device)
delete(disk.Partitions, device)
}
// updates partition info. We add 0.5 to all values to make sure the truncation rounds
for _, partition := range self.Partitions {
for _, partition := range disk.Partitions {
usage, err := psDisk.Usage(partition.MountPoint)
if err != nil {
log.Printf("failed to get partition usage statistics from gopsutil: %v. partition: %v", err, partition)
@ -160,27 +160,27 @@ func (self *DiskWidget) update() {
// converts self.Partitions into self.Rows which is a [][]String
sortedPartitions := []string{}
for seriesName := range self.Partitions {
for seriesName := range disk.Partitions {
sortedPartitions = append(sortedPartitions, seriesName)
}
sort.Strings(sortedPartitions)
self.Rows = make([][]string, len(self.Partitions))
disk.Rows = make([][]string, len(disk.Partitions))
for i, key := range sortedPartitions {
partition := self.Partitions[key]
self.Rows[i] = make([]string, 6)
self.Rows[i][0] = strings.Replace(strings.Replace(partition.Device, "/dev/", "", -1), "mapper/", "", -1)
self.Rows[i][1] = partition.MountPoint
self.Rows[i][2] = fmt.Sprintf("%d%%", partition.UsedPercent)
self.Rows[i][3] = partition.Free
self.Rows[i][4] = partition.BytesReadRecently
self.Rows[i][5] = partition.BytesWrittenRecently
if self.metric != nil {
if self.metric[key] == nil {
partition := disk.Partitions[key]
disk.Rows[i] = make([]string, 6)
disk.Rows[i][0] = strings.Replace(strings.Replace(partition.Device, "/dev/", "", -1), "mapper/", "", -1)
disk.Rows[i][1] = partition.MountPoint
disk.Rows[i][2] = fmt.Sprintf("%d%%", partition.UsedPercent)
disk.Rows[i][3] = partition.Free
disk.Rows[i][4] = partition.BytesReadRecently
disk.Rows[i][5] = partition.BytesWrittenRecently
if disk.metric != nil {
if disk.metric[key] == nil {
log.Printf("ERROR: missing metric %s", key)
} else {
self.metric[key].Set(float64(partition.UsedPercent) / 100.0)
disk.metric[key].Set(float64(partition.UsedPercent) / 100.0)
}
}
}

View File

@ -7,6 +7,7 @@ import (
ui "github.com/gizak/termui/v3"
)
// KEYBINDS is the help text for the in-program shortcuts
const KEYBINDS = `
Quit: q or <C-c>
@ -55,7 +56,7 @@ func NewHelpMenu() *HelpMenu {
}
}
func (self *HelpMenu) Resize(termWidth, termHeight int) {
func (help *HelpMenu) Resize(termWidth, termHeight int) {
textWidth := 53
for _, line := range strings.Split(KEYBINDS, "\n") {
if textWidth < len(line) {
@ -66,17 +67,17 @@ func (self *HelpMenu) Resize(termWidth, termHeight int) {
x := (termWidth - textWidth) / 2
y := (termHeight - textHeight) / 2
self.Block.SetRect(x, y, textWidth+x, textHeight+y)
help.Block.SetRect(x, y, textWidth+x, textHeight+y)
}
func (self *HelpMenu) Draw(buf *ui.Buffer) {
self.Block.Draw(buf)
func (help *HelpMenu) Draw(buf *ui.Buffer) {
help.Block.Draw(buf)
for y, line := range strings.Split(KEYBINDS, "\n") {
for x, rune := range line {
buf.SetCell(
ui.NewCell(rune, ui.Theme.Default),
image.Pt(self.Inner.Min.X+x, self.Inner.Min.Y+y-1),
image.Pt(help.Inner.Min.X+x, help.Inner.Min.Y+y-1),
)
}
}

View File

@ -48,30 +48,30 @@ func NewMemWidget(updateInterval time.Duration, horizontalScale int) *MemWidget
return self
}
func (b *MemWidget) EnableMetric() {
b.metrics = make(map[string]prometheus.Gauge)
func (mem *MemWidget) EnableMetric() {
mem.metrics = make(map[string]prometheus.Gauge)
mems := make(map[string]devices.MemoryInfo)
devices.UpdateMem(mems)
for l, mem := range mems {
b.metrics[l] = prometheus.NewGauge(prometheus.GaugeOpts{
for l, m := range mems {
mem.metrics[l] = prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: "gotop",
Subsystem: "memory",
Name: l,
})
b.metrics[l].Set(mem.UsedPercent)
prometheus.MustRegister(b.metrics[l])
mem.metrics[l].Set(m.UsedPercent)
prometheus.MustRegister(mem.metrics[l])
}
}
func (b *MemWidget) Scale(i int) {
b.LineGraph.HorizontalScale = i
func (mem *MemWidget) Scale(i int) {
mem.LineGraph.HorizontalScale = i
}
func (self *MemWidget) renderMemInfo(line string, memoryInfo devices.MemoryInfo) {
self.Data[line] = append(self.Data[line], memoryInfo.UsedPercent)
func (mem *MemWidget) renderMemInfo(line string, memoryInfo devices.MemoryInfo) {
mem.Data[line] = append(mem.Data[line], memoryInfo.UsedPercent)
memoryTotalBytes, memoryTotalMagnitude := utils.ConvertBytes(memoryInfo.Total)
memoryUsedBytes, memoryUsedMagnitude := utils.ConvertBytes(memoryInfo.Used)
self.Labels[line] = fmt.Sprintf("%3.0f%% %5.1f%s/%.0f%s",
mem.Labels[line] = fmt.Sprintf("%3.0f%% %5.1f%s/%.0f%s",
memoryInfo.UsedPercent,
memoryUsedBytes,
memoryUsedMagnitude,

View File

@ -14,8 +14,10 @@ import (
)
const (
NET_INTERFACE_ALL = "all"
NET_INTERFACE_VPN = "tun0"
// NetInterfaceAll enables all network interfaces
NetInterfaceAll = "all"
// NetInterfaceVpn is the VPN interface
NetInterfaceVpn = "tun0"
)
type NetWidget struct {
@ -63,23 +65,23 @@ func NewNetWidget(netInterface string) *NetWidget {
return self
}
func (b *NetWidget) EnableMetric() {
b.recvMetric = prometheus.NewCounter(prometheus.CounterOpts{
func (net *NetWidget) EnableMetric() {
net.recvMetric = prometheus.NewCounter(prometheus.CounterOpts{
Namespace: "gotop",
Subsystem: "net",
Name: "recv",
})
prometheus.MustRegister(b.recvMetric)
prometheus.MustRegister(net.recvMetric)
b.sentMetric = prometheus.NewCounter(prometheus.CounterOpts{
net.sentMetric = prometheus.NewCounter(prometheus.CounterOpts{
Namespace: "gotop",
Subsystem: "net",
Name: "sent",
})
prometheus.MustRegister(b.sentMetric)
prometheus.MustRegister(net.sentMetric)
}
func (self *NetWidget) update() {
func (net *NetWidget) update() {
interfaces, err := psNet.IOCounters(true)
if err != nil {
log.Printf("failed to get network activity from gopsutil: %v", err)
@ -90,15 +92,15 @@ func (self *NetWidget) update() {
var totalBytesSent uint64
interfaceMap := make(map[string]bool)
// Default behaviour
interfaceMap[NET_INTERFACE_ALL] = true
interfaceMap[NET_INTERFACE_VPN] = false
interfaceMap[NetInterfaceAll] = true
interfaceMap[NetInterfaceVpn] = false
// Build a map with wanted status for each interfaces.
for _, iface := range self.NetInterface {
for _, iface := range net.NetInterface {
if strings.HasPrefix(iface, "!") {
interfaceMap[strings.TrimPrefix(iface, "!")] = false
} else {
// if we specify a wanted interface, remove capture on all.
delete(interfaceMap, NET_INTERFACE_ALL)
delete(interfaceMap, NetInterfaceAll)
interfaceMap[iface] = true
}
}
@ -109,7 +111,7 @@ func (self *NetWidget) update() {
totalBytesSent += _interface.BytesSent
} else if ok { // Present but unwanted
continue
} else if interfaceMap[NET_INTERFACE_ALL] { // Capture other
} else if interfaceMap[NetInterfaceAll] { // Capture other
totalBytesRecv += _interface.BytesRecv
totalBytesSent += _interface.BytesSent
}
@ -118,9 +120,9 @@ func (self *NetWidget) update() {
var recentBytesRecv uint64
var recentBytesSent uint64
if self.totalBytesRecv != 0 { // if this isn't the first update
recentBytesRecv = totalBytesRecv - self.totalBytesRecv
recentBytesSent = totalBytesSent - self.totalBytesSent
if net.totalBytesRecv != 0 { // if this isn't the first update
recentBytesRecv = totalBytesRecv - net.totalBytesRecv
recentBytesSent = totalBytesSent - net.totalBytesSent
if int(recentBytesRecv) < 0 {
log.Printf("error: negative value for recently received network data from gopsutil. recentBytesRecv: %v", recentBytesRecv)
@ -133,20 +135,20 @@ func (self *NetWidget) update() {
recentBytesSent = 0
}
self.Lines[0].Data = append(self.Lines[0].Data, int(recentBytesRecv))
self.Lines[1].Data = append(self.Lines[1].Data, int(recentBytesSent))
if self.sentMetric != nil {
self.sentMetric.Add(float64(recentBytesSent))
self.recvMetric.Add(float64(recentBytesRecv))
net.Lines[0].Data = append(net.Lines[0].Data, int(recentBytesRecv))
net.Lines[1].Data = append(net.Lines[1].Data, int(recentBytesSent))
if net.sentMetric != nil {
net.sentMetric.Add(float64(recentBytesSent))
net.recvMetric.Add(float64(recentBytesRecv))
}
}
// used in later calls to update
self.totalBytesRecv = totalBytesRecv
self.totalBytesSent = totalBytesSent
net.totalBytesRecv = totalBytesRecv
net.totalBytesSent = totalBytesSent
rx, tx := "RX/s", "TX/s"
if self.Mbps {
if net.Mbps {
rx, tx = "mbps", "mbps"
}
format := " %s: %9.1f %2s/s"
@ -163,13 +165,13 @@ func (self *NetWidget) update() {
}
totalConverted, unitTotal := utils.ConvertBytes(total)
if self.Mbps {
if net.Mbps {
recentConverted, unitRecent, format = float64(recent)*0.000008, "", " %s: %11.3f %2s"
} else {
recentConverted, unitRecent = utils.ConvertBytes(recent)
}
self.Lines[i].Title1 = fmt.Sprintf(" Total %s: %5.1f %s", label, totalConverted, unitTotal)
self.Lines[i].Title2 = fmt.Sprintf(format, rate, recentConverted, unitRecent)
net.Lines[i].Title1 = fmt.Sprintf(" Total %s: %5.1f %s", label, totalConverted, unitTotal)
net.Lines[i].Title2 = fmt.Sprintf(format, rate, recentConverted, unitRecent)
}
}

View File

@ -17,14 +17,13 @@ import (
)
const (
UP_ARROW = "▲"
DOWN_ARROW = "▼"
_downArrow = "▼"
)
type ProcSortMethod string
const (
ProcSortCpu ProcSortMethod = "c"
ProcSortCPU ProcSortMethod = "c"
ProcSortMem = "m"
ProcSortPid = "p"
)
@ -33,7 +32,7 @@ type Proc struct {
Pid int
CommandName string
FullCommand string
Cpu float64
CPU float64
Mem float64
}
@ -58,7 +57,7 @@ func NewProcWidget() *ProcWidget {
Table: ui.NewTable(),
updateInterval: time.Second,
cpuCount: cpuCount,
sortMethod: ProcSortCpu,
sortMethod: ProcSortCPU,
showGroupedProcs: true,
filter: "",
}
@ -100,42 +99,42 @@ func NewProcWidget() *ProcWidget {
return self
}
func (p *ProcWidget) EnableMetric() {
func (proc *ProcWidget) EnableMetric() {
// There's (currently) no metric for this
}
func (self *ProcWidget) SetEditingFilter(editing bool) {
self.entry.SetEditing(editing)
func (proc *ProcWidget) SetEditingFilter(editing bool) {
proc.entry.SetEditing(editing)
}
func (self *ProcWidget) HandleEvent(e tui.Event) bool {
return self.entry.HandleEvent(e)
func (proc *ProcWidget) HandleEvent(e tui.Event) bool {
return proc.entry.HandleEvent(e)
}
func (self *ProcWidget) SetRect(x1, y1, x2, y2 int) {
self.Table.SetRect(x1, y1, x2, y2)
self.entry.SetRect(x1+2, y2-1, x2-2, y2)
func (proc *ProcWidget) SetRect(x1, y1, x2, y2 int) {
proc.Table.SetRect(x1, y1, x2, y2)
proc.entry.SetRect(x1+2, y2-1, x2-2, y2)
}
func (self *ProcWidget) Draw(buf *tui.Buffer) {
self.Table.Draw(buf)
self.entry.Draw(buf)
func (proc *ProcWidget) Draw(buf *tui.Buffer) {
proc.Table.Draw(buf)
proc.entry.Draw(buf)
}
func (self *ProcWidget) filterProcs(procs []Proc) []Proc {
if self.filter == "" {
func (proc *ProcWidget) filterProcs(procs []Proc) []Proc {
if proc.filter == "" {
return procs
}
var filtered []Proc
for _, proc := range procs {
if strings.Contains(proc.FullCommand, self.filter) || strings.Contains(fmt.Sprintf("%d", proc.Pid), self.filter) {
filtered = append(filtered, proc)
for _, p := range procs {
if strings.Contains(p.FullCommand, proc.filter) || strings.Contains(fmt.Sprintf("%d", p.Pid), proc.filter) {
filtered = append(filtered, p)
}
}
return filtered
}
func (self *ProcWidget) update() {
func (proc *ProcWidget) update() {
procs, err := getProcs()
if err != nil {
log.Printf("failed to retrieve processes: %v", err)
@ -144,103 +143,103 @@ func (self *ProcWidget) update() {
// have to iterate over the entry number in order to modify the array in place
for i := range procs {
procs[i].Cpu /= float64(self.cpuCount)
procs[i].CPU /= float64(proc.cpuCount)
}
procs = self.filterProcs(procs)
self.ungroupedProcs = procs
self.groupedProcs = groupProcs(procs)
procs = proc.filterProcs(procs)
proc.ungroupedProcs = procs
proc.groupedProcs = groupProcs(procs)
self.sortProcs()
self.convertProcsToTableRows()
proc.sortProcs()
proc.convertProcsToTableRows()
}
// sortProcs sorts either the grouped or ungrouped []Process based on the sortMethod.
// Called with every update, when the sort method is changed, and when processes are grouped and ungrouped.
func (self *ProcWidget) sortProcs() {
self.Header = []string{"Count", "Command", "CPU%", "Mem%"}
func (proc *ProcWidget) sortProcs() {
proc.Header = []string{"Count", "Command", "CPU%", "Mem%"}
if !self.showGroupedProcs {
self.Header[0] = "PID"
if !proc.showGroupedProcs {
proc.Header[0] = "PID"
}
var procs *[]Proc
if self.showGroupedProcs {
procs = &self.groupedProcs
if proc.showGroupedProcs {
procs = &proc.groupedProcs
} else {
procs = &self.ungroupedProcs
procs = &proc.ungroupedProcs
}
switch self.sortMethod {
case ProcSortCpu:
sort.Sort(sort.Reverse(SortProcsByCpu(*procs)))
self.Header[2] += DOWN_ARROW
switch proc.sortMethod {
case ProcSortCPU:
sort.Sort(sort.Reverse(SortProcsByCPU(*procs)))
proc.Header[2] += _downArrow
case ProcSortPid:
if self.showGroupedProcs {
if proc.showGroupedProcs {
sort.Sort(sort.Reverse(SortProcsByPid(*procs)))
} else {
sort.Sort(SortProcsByPid(*procs))
}
self.Header[0] += DOWN_ARROW
proc.Header[0] += _downArrow
case ProcSortMem:
sort.Sort(sort.Reverse(SortProcsByMem(*procs)))
self.Header[3] += DOWN_ARROW
proc.Header[3] += _downArrow
}
}
// convertProcsToTableRows converts a []Proc to a [][]string and sets it to the table Rows
func (self *ProcWidget) convertProcsToTableRows() {
func (proc *ProcWidget) convertProcsToTableRows() {
var procs *[]Proc
if self.showGroupedProcs {
procs = &self.groupedProcs
if proc.showGroupedProcs {
procs = &proc.groupedProcs
} else {
procs = &self.ungroupedProcs
procs = &proc.ungroupedProcs
}
strings := make([][]string, len(*procs))
for i := range *procs {
strings[i] = make([]string, 4)
strings[i][0] = strconv.Itoa(int((*procs)[i].Pid))
if self.showGroupedProcs {
if proc.showGroupedProcs {
strings[i][1] = (*procs)[i].CommandName
} else {
strings[i][1] = (*procs)[i].FullCommand
}
strings[i][2] = fmt.Sprintf("%4s", strconv.FormatFloat((*procs)[i].Cpu, 'f', 1, 64))
strings[i][2] = fmt.Sprintf("%4s", strconv.FormatFloat((*procs)[i].CPU, 'f', 1, 64))
strings[i][3] = fmt.Sprintf("%4s", strconv.FormatFloat(float64((*procs)[i].Mem), 'f', 1, 64))
}
self.Rows = strings
proc.Rows = strings
}
func (self *ProcWidget) ChangeProcSortMethod(method ProcSortMethod) {
if self.sortMethod != method {
self.sortMethod = method
self.ScrollTop()
self.sortProcs()
self.convertProcsToTableRows()
func (proc *ProcWidget) ChangeProcSortMethod(method ProcSortMethod) {
if proc.sortMethod != method {
proc.sortMethod = method
proc.ScrollTop()
proc.sortProcs()
proc.convertProcsToTableRows()
}
}
func (self *ProcWidget) ToggleShowingGroupedProcs() {
self.showGroupedProcs = !self.showGroupedProcs
if self.showGroupedProcs {
self.UniqueCol = 1
func (proc *ProcWidget) ToggleShowingGroupedProcs() {
proc.showGroupedProcs = !proc.showGroupedProcs
if proc.showGroupedProcs {
proc.UniqueCol = 1
} else {
self.UniqueCol = 0
proc.UniqueCol = 0
}
self.ScrollTop()
self.sortProcs()
self.convertProcsToTableRows()
proc.ScrollTop()
proc.sortProcs()
proc.convertProcsToTableRows()
}
// KillProc kills a process or group of processes depending on if we're
// displaying the processes grouped or not.
func (self *ProcWidget) KillProc(sigName string) {
self.SelectedItem = ""
func (proc *ProcWidget) KillProc(sigName string) {
proc.SelectedItem = ""
command := "kill"
if self.UniqueCol == 1 {
if proc.UniqueCol == 1 {
command = "pkill"
}
cmd := exec.Command(command, "--signal", sigName, self.Rows[self.SelectedRow][self.UniqueCol])
cmd := exec.Command(command, "--signal", sigName, proc.Rows[proc.SelectedRow][proc.UniqueCol])
cmd.Start()
cmd.Wait()
}
@ -257,7 +256,7 @@ func groupProcs(procs []Proc) []Proc {
val.Pid + 1,
val.CommandName,
"",
val.Cpu + proc.Cpu,
val.CPU + proc.CPU,
val.Mem + proc.Mem,
}
} else {
@ -265,7 +264,7 @@ func groupProcs(procs []Proc) []Proc {
1,
proc.CommandName,
"",
proc.Cpu,
proc.CPU,
proc.Mem,
}
}
@ -283,53 +282,53 @@ func groupProcs(procs []Proc) []Proc {
// []Proc Sorting //////////////////////////////////////////////////////////////
type SortProcsByCpu []Proc
type SortProcsByCPU []Proc
// Len implements Sort interface
func (self SortProcsByCpu) Len() int {
return len(self)
func (procs SortProcsByCPU) Len() int {
return len(procs)
}
// Swap implements Sort interface
func (self SortProcsByCpu) Swap(i, j int) {
self[i], self[j] = self[j], self[i]
func (procs SortProcsByCPU) Swap(i, j int) {
procs[i], procs[j] = procs[j], procs[i]
}
// Less implements Sort interface
func (self SortProcsByCpu) Less(i, j int) bool {
return self[i].Cpu < self[j].Cpu
func (procs SortProcsByCPU) Less(i, j int) bool {
return procs[i].CPU < procs[j].CPU
}
type SortProcsByPid []Proc
// Len implements Sort interface
func (self SortProcsByPid) Len() int {
return len(self)
func (procs SortProcsByPid) Len() int {
return len(procs)
}
// Swap implements Sort interface
func (self SortProcsByPid) Swap(i, j int) {
self[i], self[j] = self[j], self[i]
func (procs SortProcsByPid) Swap(i, j int) {
procs[i], procs[j] = procs[j], procs[i]
}
// Less implements Sort interface
func (self SortProcsByPid) Less(i, j int) bool {
return self[i].Pid < self[j].Pid
func (procs SortProcsByPid) Less(i, j int) bool {
return procs[i].Pid < procs[j].Pid
}
type SortProcsByMem []Proc
// Len implements Sort interface
func (self SortProcsByMem) Len() int {
return len(self)
func (procs SortProcsByMem) Len() int {
return len(procs)
}
// Swap implements Sort interface
func (self SortProcsByMem) Swap(i, j int) {
self[i], self[j] = self[j], self[i]
func (procs SortProcsByMem) Swap(i, j int) {
procs[i], procs[j] = procs[j], procs[i]
}
// Less implements Sort interface
func (self SortProcsByMem) Less(i, j int) bool {
return self[i].Mem < self[j].Mem
func (procs SortProcsByMem) Less(i, j int) bool {
return procs[i].Mem < procs[j].Mem
}

View File

@ -35,7 +35,7 @@ func getProcs() ([]Proc, error) {
Pid: pid,
CommandName: strings.TrimSpace(line[11:61]),
FullCommand: line[74:],
Cpu: cpu,
CPU: cpu,
Mem: mem,
}
procs = append(procs, proc)

View File

@ -19,8 +19,8 @@ func NewStatusBar() *StatusBar {
return self
}
func (self *StatusBar) Draw(buf *ui.Buffer) {
self.Block.Draw(buf)
func (sb *StatusBar) Draw(buf *ui.Buffer) {
sb.Block.Draw(buf)
hostname, err := os.Hostname()
if err != nil {
@ -30,7 +30,7 @@ func (self *StatusBar) Draw(buf *ui.Buffer) {
buf.SetString(
hostname,
ui.Theme.Default,
image.Pt(self.Inner.Min.X, self.Inner.Min.Y+(self.Inner.Dy()/2)),
image.Pt(sb.Inner.Min.X, sb.Inner.Min.Y+(sb.Inner.Dy()/2)),
)
currentTime := time.Now()
@ -39,8 +39,8 @@ func (self *StatusBar) Draw(buf *ui.Buffer) {
formattedTime,
ui.Theme.Default,
image.Pt(
self.Inner.Min.X+(self.Inner.Dx()/2)-len(formattedTime)/2,
self.Inner.Min.Y+(self.Inner.Dy()/2),
sb.Inner.Min.X+(sb.Inner.Dx()/2)-len(formattedTime)/2,
sb.Inner.Min.Y+(sb.Inner.Dy()/2),
),
)
@ -48,8 +48,8 @@ func (self *StatusBar) Draw(buf *ui.Buffer) {
"gotop",
ui.Theme.Default,
image.Pt(
self.Inner.Max.X-6,
self.Inner.Min.Y+(self.Inner.Dy()/2),
sb.Inner.Max.X-6,
sb.Inner.Min.Y+(sb.Inner.Dy()/2),
),
)
}

View File

@ -68,9 +68,9 @@ func NewTempWidget(tempScale TempScale, filter []string) *TempWidget {
return self
}
func (self *TempWidget) EnableMetric() {
self.tempsMetric = make(map[string]prometheus.Gauge)
for k, v := range self.Data {
func (temp *TempWidget) EnableMetric() {
temp.tempsMetric = make(map[string]prometheus.Gauge)
for k, v := range temp.Data {
gauge := prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: "gotop",
Subsystem: "temp",
@ -78,58 +78,58 @@ func (self *TempWidget) EnableMetric() {
})
gauge.Set(float64(v))
prometheus.MustRegister(gauge)
self.tempsMetric[k] = gauge
temp.tempsMetric[k] = gauge
}
}
// Custom Draw method instead of inheriting from a generic Widget.
func (self *TempWidget) Draw(buf *ui.Buffer) {
self.Block.Draw(buf)
func (temp *TempWidget) Draw(buf *ui.Buffer) {
temp.Block.Draw(buf)
var keys []string
for key := range self.Data {
for key := range temp.Data {
keys = append(keys, key)
}
sort.Strings(keys)
for y, key := range keys {
if y+1 > self.Inner.Dy() {
if y+1 > temp.Inner.Dy() {
break
}
var fg ui.Color
if self.Data[key] < self.TempThreshold {
fg = self.TempLowColor
if temp.Data[key] < temp.TempThreshold {
fg = temp.TempLowColor
} else {
fg = self.TempHighColor
fg = temp.TempHighColor
}
s := ui.TrimString(key, (self.Inner.Dx() - 4))
s := ui.TrimString(key, (temp.Inner.Dx() - 4))
buf.SetString(s,
ui.Theme.Default,
image.Pt(self.Inner.Min.X, self.Inner.Min.Y+y),
image.Pt(temp.Inner.Min.X, temp.Inner.Min.Y+y),
)
if self.tempsMetric != nil {
self.tempsMetric[key].Set(float64(self.Data[key]))
if temp.tempsMetric != nil {
temp.tempsMetric[key].Set(float64(temp.Data[key]))
}
temperature := fmt.Sprintf("%3d°%c", self.Data[key], self.TempScale)
temperature := fmt.Sprintf("%3d°%c", temp.Data[key], temp.TempScale)
buf.SetString(
temperature,
ui.NewStyle(fg),
image.Pt(self.Inner.Max.X-(len(temperature)-1), self.Inner.Min.Y+y),
image.Pt(temp.Inner.Max.X-(len(temperature)-1), temp.Inner.Min.Y+y),
)
}
}
func (self *TempWidget) update() {
devices.UpdateTemps(self.Data)
for name, val := range self.Data {
if self.TempScale == Fahrenheit {
self.Data[name] = utils.CelsiusToFahrenheit(val)
func (temp *TempWidget) update() {
devices.UpdateTemps(temp.Data)
for name, val := range temp.Data {
if temp.TempScale == Fahrenheit {
temp.Data[name] = utils.CelsiusToFahrenheit(val)
} else {
self.Data[name] = val
temp.Data[name] = val
}
}
}