summaryrefslogtreecommitdiffstats
path: root/widgets
diff options
context:
space:
mode:
authorSean E. Russell <ser@ser1.net>2020-02-27 16:13:23 -0600
committerSean E. Russell <ser@ser1.net>2020-02-27 16:13:23 -0600
commit4fce1654c5c263797205997e7635c7d06c393a85 (patch)
tree06a0e382b9cfc292d978d45033f26aaaaa28fa12 /widgets
parente38f6fc8c488ed9379efc32060be18f45b18329b (diff)
parenta5b039cd923270683a777c7e3851116076a663e9 (diff)
Merge branch 'v3.4.x' into nvidia
Diffstat (limited to 'widgets')
-rw-r--r--widgets/battery.go27
-rw-r--r--widgets/batterygauge.go86
-rw-r--r--widgets/cpu.go44
-rw-r--r--widgets/disk.go24
-rw-r--r--widgets/mem.go30
-rw-r--r--widgets/mem_freebsd.go3
-rw-r--r--widgets/mem_other.go3
-rw-r--r--widgets/net.go23
-rw-r--r--widgets/proc.go4
-rw-r--r--widgets/temp.go45
10 files changed, 271 insertions, 18 deletions
diff --git a/widgets/battery.go b/widgets/battery.go
index 00764c0..b47cac4 100644
--- a/widgets/battery.go
+++ b/widgets/battery.go
@@ -8,6 +8,7 @@ import (
"time"
"github.com/distatus/battery"
+ "github.com/prometheus/client_golang/prometheus"
ui "github.com/xxxserxxx/gotop/termui"
)
@@ -15,6 +16,7 @@ import (
type BatteryWidget struct {
*ui.LineGraph
updateInterval time.Duration
+ metric []prometheus.Gauge
}
func NewBatteryWidget(horizontalScale int) *BatteryWidget {
@@ -41,6 +43,25 @@ func NewBatteryWidget(horizontalScale int) *BatteryWidget {
return self
}
+func (b *BatteryWidget) EnableMetric() {
+ bats, err := battery.GetAll()
+ if err != nil {
+ log.Printf("error setting up metrics: %v", err)
+ return
+ }
+ b.metric = make([]prometheus.Gauge, len(bats))
+ for i, bat := range bats {
+ gauge := prometheus.NewGauge(prometheus.GaugeOpts{
+ Namespace: "gotop",
+ Subsystem: "battery",
+ Name: fmt.Sprintf("%d", i),
+ })
+ gauge.Set(bat.Current / bat.Full)
+ b.metric[i] = gauge
+ prometheus.MustRegister(gauge)
+ }
+}
+
func makeId(i int) string {
return "Batt" + strconv.Itoa(i)
}
@@ -74,8 +95,12 @@ func (self *BatteryWidget) update() {
}
for i, battery := range batteries {
id := makeId(i)
- percentFull := math.Abs(battery.Current/battery.Full) * 100.0
+ 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)
+ }
}
}
diff --git a/widgets/batterygauge.go b/widgets/batterygauge.go
new file mode 100644
index 0000000..59accfb
--- /dev/null
+++ b/widgets/batterygauge.go
@@ -0,0 +1,86 @@
+package widgets
+
+import (
+ "fmt"
+ "log"
+
+ "time"
+
+ "github.com/distatus/battery"
+ "github.com/prometheus/client_golang/prometheus"
+
+ . "github.com/xxxserxxx/gotop/termui"
+)
+
+type BatteryGauge struct {
+ *Gauge
+ metric prometheus.Gauge
+}
+
+func NewBatteryGauge() *BatteryGauge {
+ self := &BatteryGauge{Gauge: NewGauge()}
+ self.Title = " Power Level "
+
+ self.update()
+
+ go func() {
+ for range time.NewTicker(time.Second).C {
+ self.Lock()
+ self.update()
+ self.Unlock()
+ }
+ }()
+
+ return self
+}
+
+func (b *BatteryGauge) EnableMetric() {
+ bats, err := battery.GetAll()
+ if err != nil {
+ log.Printf("error setting up metrics: %v", err)
+ return
+ }
+ mx := 0.0
+ cu := 0.0
+ for _, bat := range bats {
+ mx += bat.Full
+ cu += bat.Current
+ gauge := prometheus.NewGauge(prometheus.GaugeOpts{
+ Namespace: "gotop",
+ Subsystem: "battery",
+ Name: "total",
+ })
+ gauge.Set(cu / mx)
+ b.metric = gauge
+ prometheus.MustRegister(gauge)
+ }
+}
+
+func (self *BatteryGauge) update() {
+ bats, err := battery.GetAll()
+ if err != nil {
+ log.Printf("error setting up batteries: %v", err)
+ return
+ }
+ mx := 0.0
+ cu := 0.0
+ charging := "%d%% ⚡%s"
+ rate := 0.0
+ for _, bat := range bats {
+ mx += bat.Full
+ cu += bat.Current
+ if rate < bat.ChargeRate {
+ rate = bat.ChargeRate
+ }
+ if bat.State == battery.Charging {
+ charging = "%d%% 🔌%s"
+ }
+ }
+ 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)
+ }
+}
diff --git a/widgets/cpu.go b/widgets/cpu.go
index 937aa8f..c0f25bc 100644
--- a/widgets/cpu.go
+++ b/widgets/cpu.go
@@ -1,12 +1,16 @@
package widgets
import (
+ "context"
"fmt"
"log"
"sync"
"time"
+ "github.com/prometheus/client_golang/prometheus"
+ psCpu "github.com/shirou/gopsutil/cpu"
"github.com/xxxserxxx/gotop/devices"
+
ui "github.com/xxxserxxx/gotop/termui"
)
@@ -18,6 +22,7 @@ type CpuWidget struct {
updateInterval time.Duration
formatString string
updateLock sync.Mutex
+ metric []prometheus.Gauge
}
func NewCpuWidget(updateInterval time.Duration, horizontalScale int, showAverageLoad bool, showPerCpuLoad bool) *CpuWidget {
@@ -70,6 +75,35 @@ func NewCpuWidget(updateInterval time.Duration, horizontalScale int, showAverage
return self
}
+func (self *CpuWidget) EnableMetric() {
+ if self.ShowAverageLoad {
+ self.metric = make([]prometheus.Gauge, 1)
+ self.metric[0] = prometheus.NewGauge(prometheus.GaugeOpts{
+ Subsystem: "cpu",
+ Name: "avg",
+ })
+ } else {
+ ctx, ccl := context.WithTimeout(context.Background(), time.Second*5)
+ defer ccl()
+ percents, err := psCpu.PercentWithContext(ctx, self.updateInterval, true)
+ if err != nil {
+ log.Printf("error setting up metrics: %v", err)
+ return
+ }
+ self.metric = make([]prometheus.Gauge, self.CpuCount)
+ for i, perc := range percents {
+ gauge := prometheus.NewGauge(prometheus.GaugeOpts{
+ Namespace: "gotop",
+ Subsystem: "cpu",
+ Name: fmt.Sprintf("%d", i),
+ })
+ gauge.Set(perc)
+ prometheus.MustRegister(gauge)
+ self.metric[i] = gauge
+ }
+ }
+}
+
func (b *CpuWidget) Scale(i int) {
b.LineGraph.HorizontalScale = i
}
@@ -87,6 +121,9 @@ func (self *CpuWidget) update() {
defer self.updateLock.Unlock()
self.Data["AVRG"] = append(self.Data["AVRG"], percent[0])
self.Labels["AVRG"] = fmt.Sprintf("%3.0f%%", percent[0])
+ if self.metric != nil {
+ self.metric[0].Set(percent[0])
+ }
}
}()
}
@@ -108,6 +145,13 @@ func (self *CpuWidget) update() {
key := fmt.Sprintf(self.formatString, i)
self.Data[key] = append(self.Data[key], percent)
self.Labels[key] = fmt.Sprintf("%3.0f%%", percent)
+ if self.metric != nil {
+ if self.metric[i] == nil {
+ log.Printf("ERROR: not enough metrics %d", i)
+ } else {
+ self.metric[i].Set(percent)
+ }
+ }
}
}
}
diff --git a/widgets/disk.go b/widgets/disk.go
index d20b078..d1da7a6 100644
--- a/widgets/disk.go
+++ b/widgets/disk.go
@@ -7,6 +7,7 @@ import (
"strings"
"time"
+ "github.com/prometheus/client_golang/prometheus"
psDisk "github.com/shirou/gopsutil/disk"
ui "github.com/xxxserxxx/gotop/termui"
@@ -28,6 +29,7 @@ type DiskWidget struct {
*ui.Table
updateInterval time.Duration
Partitions map[string]*Partition
+ metric map[string]prometheus.Gauge
}
func NewDiskWidget() *DiskWidget {
@@ -60,6 +62,21 @@ func NewDiskWidget() *DiskWidget {
return self
}
+func (self *DiskWidget) EnableMetric() {
+ self.metric = make(map[string]prometheus.Gauge)
+ for key, part := range self.Partitions {
+ gauge := prometheus.NewGauge(prometheus.GaugeOpts{
+ Namespace: "gotop",
+ Subsystem: "disk",
+ Name: strings.ReplaceAll(key, "/", ":"),
+ //Name: strings.Replace(strings.Replace(part.Device, "/dev/", "", -1), "mapper/", "", -1),
+ })
+ gauge.Set(float64(part.UsedPercent) / 100.0)
+ prometheus.MustRegister(gauge)
+ self.metric[key] = gauge
+ }
+}
+
func (self *DiskWidget) update() {
partitions, err := psDisk.Partitions(false)
if err != nil {
@@ -158,5 +175,12 @@ func (self *DiskWidget) update() {
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 {
+ log.Printf("ERROR: missing metric %s", key)
+ } else {
+ self.metric[key].Set(float64(partition.UsedPercent) / 100.0)
+ }
+ }
}
}
diff --git a/widgets/mem.go b/widgets/mem.go
index d5bd67d..1c85f3b 100644
--- a/widgets/mem.go
+++ b/widgets/mem.go
@@ -5,6 +5,7 @@ import (
"log"
"time"
+ "github.com/prometheus/client_golang/prometheus"
psMem "github.com/shirou/gopsutil/mem"
ui "github.com/xxxserxxx/gotop/termui"
@@ -14,6 +15,8 @@ import (
type MemWidget struct {
*ui.LineGraph
updateInterval time.Duration
+ mainMetric prometheus.Gauge
+ swapMetric prometheus.Gauge
}
type MemoryInfo struct {
@@ -45,6 +48,9 @@ func (self *MemWidget) updateMainMemory() {
Used: mainMemory.Used,
UsedPercent: mainMemory.UsedPercent,
})
+ if self.mainMetric != nil {
+ self.mainMetric.Set(mainMemory.UsedPercent)
+ }
}
}
@@ -73,6 +79,30 @@ func NewMemWidget(updateInterval time.Duration, horizontalScale int) *MemWidget
return self
}
+func (b *MemWidget) EnableMetric() {
+ b.mainMetric = prometheus.NewGauge(prometheus.GaugeOpts{
+ Namespace: "gotop",
+ Subsystem: "memory",
+ Name: "main",
+ })
+ mainMemory, err := psMem.VirtualMemory()
+ if err == nil {
+ b.mainMetric.Set(mainMemory.UsedPercent)
+ }
+ prometheus.MustRegister(b.mainMetric)
+
+ b.swapMetric = prometheus.NewGauge(prometheus.GaugeOpts{
+ Namespace: "gotop",
+ Subsystem: "memory",
+ Name: "swap",
+ })
+ swapMemory, err := psMem.SwapMemory()
+ if err == nil {
+ b.swapMetric.Set(swapMemory.UsedPercent)
+ }
+ prometheus.MustRegister(b.swapMetric)
+}
+
func (b *MemWidget) Scale(i int) {
b.LineGraph.HorizontalScale = i
}
diff --git a/widgets/mem_freebsd.go b/widgets/mem_freebsd.go
index 7d2472a..c0151c2 100644
--- a/widgets/mem_freebsd.go
+++ b/widgets/mem_freebsd.go
@@ -60,5 +60,8 @@ func (self *MemWidget) updateSwapMemory() {
Used: swapMemory.Used,
UsedPercent: swapMemory.UsedPercent,
})
+ if self.swapMetric != nil {
+ self.swapMetric.Set(swapMemory.UsedPercent)
+ }
}
}
diff --git a/widgets/mem_other.go b/widgets/mem_other.go
index 6b78acb..c42ef5a 100644
--- a/widgets/mem_other.go
+++ b/widgets/mem_other.go
@@ -18,5 +18,8 @@ func (self *MemWidget) updateSwapMemory() {
Used: swapMemory.Used,
UsedPercent: swapMemory.UsedPercent,
})
+ if self.swapMetric != nil {
+ self.swapMetric.Set(swapMemory.UsedPercent)
+ }
}
}
diff --git a/widgets/net.go b/widgets/net.go
index ba2660d..1326fdc 100644
--- a/widgets/net.go
+++ b/widgets/net.go
@@ -6,6 +6,7 @@ import (
"strings"
"time"
+ "github.com/prometheus/client_golang/prometheus"
psNet "github.com/shirou/gopsutil/net"
ui "github.com/xxxserxxx/gotop/termui"
@@ -25,6 +26,8 @@ type NetWidget struct {
totalBytesRecv uint64
totalBytesSent uint64
NetInterface []string
+ sentMetric prometheus.Counter
+ recvMetric prometheus.Counter
}
// TODO: state:merge #169 % option for network use (jrswab/networkPercentage)
@@ -59,6 +62,22 @@ func NewNetWidget(netInterface string) *NetWidget {
return self
}
+func (b *NetWidget) EnableMetric() {
+ b.recvMetric = prometheus.NewCounter(prometheus.CounterOpts{
+ Namespace: "gotop",
+ Subsystem: "net",
+ Name: "recv",
+ })
+ prometheus.MustRegister(b.recvMetric)
+
+ b.sentMetric = prometheus.NewCounter(prometheus.CounterOpts{
+ Namespace: "gotop",
+ Subsystem: "net",
+ Name: "sent",
+ })
+ prometheus.MustRegister(b.sentMetric)
+}
+
func (self *NetWidget) update() {
interfaces, err := psNet.IOCounters(true)
if err != nil {
@@ -115,6 +134,10 @@ func (self *NetWidget) update() {
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))
+ }
}
// used in later calls to update
diff --git a/widgets/proc.go b/widgets/proc.go
index 9fed067..e4a8ace 100644
--- a/widgets/proc.go
+++ b/widgets/proc.go
@@ -100,6 +100,10 @@ func NewProcWidget() *ProcWidget {
return self
}
+func (p *ProcWidget) EnableMetric() {
+ // There's (currently) no metric for this
+}
+
func (self *ProcWidget) SetEditingFilter(editing bool) {
self.entry.SetEditing(editing)
}
diff --git a/widgets/temp.go b/widgets/temp.go
index 7c0a358..ec0292e 100644
--- a/widgets/temp.go
+++ b/widgets/temp.go
@@ -7,16 +7,16 @@ import (
"time"
ui "github.com/gizak/termui/v3"
+ "github.com/prometheus/client_golang/prometheus"
"github.com/xxxserxxx/gotop/utils"
)
-type TempScale int
+type TempScale rune
const (
- Celsius TempScale = 0
- Fahrenheit = 1
- Disabled = 2
+ Celsius TempScale = 'C'
+ Fahrenheit = 'F'
)
type TempWidget struct {
@@ -27,6 +27,7 @@ type TempWidget struct {
TempLowColor ui.Color
TempHighColor ui.Color
TempScale TempScale
+ tempsMetric map[string]prometheus.Gauge
}
// TODO: state:deferred 156 Added temperatures for NVidia GPUs (azak-azkaran/master). Crashes on non-nvidia machines.
@@ -57,6 +58,20 @@ func NewTempWidget(tempScale TempScale) *TempWidget {
return self
}
+func (self *TempWidget) EnableMetric() {
+ self.tempsMetric = make(map[string]prometheus.Gauge)
+ for k, v := range self.Data {
+ gauge := prometheus.NewGauge(prometheus.GaugeOpts{
+ Namespace: "gotop",
+ Subsystem: "temp",
+ Name: k,
+ })
+ gauge.Set(float64(v))
+ prometheus.MustRegister(gauge)
+ self.tempsMetric[k] = gauge
+ }
+}
+
// Custom Draw method instead of inheriting from a generic Widget.
func (self *TempWidget) Draw(buf *ui.Buffer) {
self.Block.Draw(buf)
@@ -86,19 +101,15 @@ func (self *TempWidget) Draw(buf *ui.Buffer) {
)
// TODO: state:merge #184 or #177 degree symbol (BartWillems/master, fleaz/master)
- switch self.TempScale {
- case Fahrenheit:
- buf.SetString(
- fmt.Sprintf("%3dF", self.Data[key]),
- ui.NewStyle(fg),
- image.Pt(self.Inner.Max.X-4, self.Inner.Min.Y+y),
- )
- case Celsius:
- buf.SetString(
- fmt.Sprintf("%3dC", self.Data[key]),
- ui.NewStyle(fg),
- image.Pt(self.Inner.Max.X-4, self.Inner.Min.Y+y),
- )
+ if self.tempsMetric != nil {
+ self.tempsMetric[key].Set(float64(self.Data[key]))
}
+ temperature := fmt.Sprintf("%3d°%c", self.Data[key], self.TempScale)
+
+ buf.SetString(
+ temperature,
+ ui.NewStyle(fg),
+ image.Pt(self.Inner.Max.X-(len(temperature)-1), self.Inner.Min.Y+y),
+ )
}
}