diff options
author | Sean E. Russell <ser@ser1.net> | 2020-02-27 16:13:23 -0600 |
---|---|---|
committer | Sean E. Russell <ser@ser1.net> | 2020-02-27 16:13:23 -0600 |
commit | 4fce1654c5c263797205997e7635c7d06c393a85 (patch) | |
tree | 06a0e382b9cfc292d978d45033f26aaaaa28fa12 /widgets | |
parent | e38f6fc8c488ed9379efc32060be18f45b18329b (diff) | |
parent | a5b039cd923270683a777c7e3851116076a663e9 (diff) |
Merge branch 'v3.4.x' into nvidia
Diffstat (limited to 'widgets')
-rw-r--r-- | widgets/battery.go | 27 | ||||
-rw-r--r-- | widgets/batterygauge.go | 86 | ||||
-rw-r--r-- | widgets/cpu.go | 44 | ||||
-rw-r--r-- | widgets/disk.go | 24 | ||||
-rw-r--r-- | widgets/mem.go | 30 | ||||
-rw-r--r-- | widgets/mem_freebsd.go | 3 | ||||
-rw-r--r-- | widgets/mem_other.go | 3 | ||||
-rw-r--r-- | widgets/net.go | 23 | ||||
-rw-r--r-- | widgets/proc.go | 4 | ||||
-rw-r--r-- | widgets/temp.go | 45 |
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), + ) } } |