From 310a6d084d5ff56ebb26cd667f46f578b39c737a Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Tue, 12 May 2020 18:42:45 -0500 Subject: Replaces the Prometheus client with VictoriaMetrics/metrics --- widgets/battery.go | 23 +++++++++-------------- widgets/batterygauge.go | 29 +++++------------------------ widgets/cpu.go | 42 +++++++++++++++--------------------------- widgets/disk.go | 22 ++++------------------ widgets/mem.go | 41 ++++++++++++++++++----------------------- widgets/metrics.go | 19 +++++++++++++++++++ widgets/net.go | 25 +++++++------------------ widgets/temp.go | 21 +++++++-------------- 8 files changed, 84 insertions(+), 138 deletions(-) create mode 100644 widgets/metrics.go (limited to 'widgets') diff --git a/widgets/battery.go b/widgets/battery.go index 7167668..77b102f 100644 --- a/widgets/battery.go +++ b/widgets/battery.go @@ -7,8 +7,8 @@ import ( "strconv" "time" + "github.com/VictoriaMetrics/metrics" "github.com/distatus/battery" - "github.com/prometheus/client_golang/prometheus" ui "github.com/xxxserxxx/gotop/v4/termui" ) @@ -16,7 +16,6 @@ import ( type BatteryWidget struct { *ui.LineGraph updateInterval time.Duration - metric []prometheus.Gauge } func NewBatteryWidget(horizontalScale int) *BatteryWidget { @@ -49,16 +48,14 @@ func (b *BatteryWidget) EnableMetric() { 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), + for i, _ := range bats { + id := makeID(i) + metrics.NewGauge(makeName("battery", i), func() float64 { + if ds, ok := b.Data[id]; ok { + return ds[len(ds)-1] + } + return 0.0 }) - gauge.Set(bat.Current / bat.Full) - b.metric[i] = gauge - prometheus.MustRegister(gauge) } } @@ -97,10 +94,8 @@ func (b *BatteryWidget) update() { id := makeID(i) perc := battery.Current / battery.Full percentFull := math.Abs(perc) * 100.0 + // TODO: look into this sort of thing; doesn't the array grow forever? Is the widget library truncating it? 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) - } } } diff --git a/widgets/batterygauge.go b/widgets/batterygauge.go index 45fec1c..3a89707 100644 --- a/widgets/batterygauge.go +++ b/widgets/batterygauge.go @@ -6,15 +6,15 @@ import ( "time" + "github.com/VictoriaMetrics/metrics" "github.com/distatus/battery" - "github.com/prometheus/client_golang/prometheus" "github.com/xxxserxxx/gotop/v4/termui" ) type BatteryGauge struct { *termui.Gauge - metric prometheus.Gauge + metric *metrics.Gauge } func NewBatteryGauge() *BatteryGauge { @@ -35,25 +35,9 @@ func NewBatteryGauge() *BatteryGauge { } 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) - } + metrics.NewGauge(makeName("battery", "total"), func() float64 { + return float64(b.Percent) + }) } func (b *BatteryGauge) update() { @@ -80,7 +64,4 @@ func (b *BatteryGauge) update() { d, _ := time.ParseDuration(fmt.Sprintf("%fh", tn)) 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) - } } diff --git a/widgets/cpu.go b/widgets/cpu.go index 03346bf..d8d9a50 100644 --- a/widgets/cpu.go +++ b/widgets/cpu.go @@ -2,11 +2,10 @@ package widgets import ( "fmt" - "log" "sync" "time" - "github.com/prometheus/client_golang/prometheus" + "github.com/VictoriaMetrics/metrics" "github.com/xxxserxxx/gotop/v4/devices" ui "github.com/xxxserxxx/gotop/v4/termui" @@ -19,7 +18,7 @@ type CPUWidget struct { ShowPerCPULoad bool updateInterval time.Duration updateLock sync.Mutex - metric map[string]prometheus.Gauge + cpuLoads map[string]float64 } var cpuLabels []string @@ -31,6 +30,7 @@ func NewCPUWidget(updateInterval time.Duration, horizontalScale int, showAverage updateInterval: updateInterval, ShowAverageLoad: showAverageLoad, ShowPerCPULoad: showPerCPULoad, + cpuLoads: make(map[string]float64), } self.Title = " CPU Usage " self.HorizontalScale = horizontalScale @@ -66,26 +66,22 @@ func NewCPUWidget(updateInterval time.Duration, horizontalScale int, showAverage return self } +const AVRG = "AVRG" + 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", + metrics.NewGauge(makeName("cpu", " avg"), func() float64 { + return cpu.cpuLoads[AVRG] }) } else { cpus := make(map[string]int) 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", - Subsystem: "cpu", - Name: key, + kc := key + cpu.cpuLoads[key] = float64(perc) + metrics.NewGauge(makeName("cpu", key), func() float64 { + return cpu.cpuLoads[kc] }) - gauge.Set(float64(perc)) - prometheus.MustRegister(gauge) - cpu.metric[key] = gauge } } } @@ -108,11 +104,9 @@ func (cpu *CPUWidget) update() { val = float64(v) break } - 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) - } + cpu.Data[AVRG] = append(cpu.Data[AVRG], val) + cpu.Labels[AVRG] = fmt.Sprintf("%3.0f%%", val) + cpu.cpuLoads[AVRG] = val }() } @@ -127,13 +121,7 @@ func (cpu *CPUWidget) update() { for key, percent := range cpus { 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 { - cpu.metric[key].Set(float64(percent)) - } - } + cpu.cpuLoads[key] = float64(percent) } }() } diff --git a/widgets/disk.go b/widgets/disk.go index fb77ace..dd49b9a 100644 --- a/widgets/disk.go +++ b/widgets/disk.go @@ -7,7 +7,7 @@ import ( "strings" "time" - "github.com/prometheus/client_golang/prometheus" + "github.com/VictoriaMetrics/metrics" psDisk "github.com/shirou/gopsutil/disk" ui "github.com/xxxserxxx/gotop/v4/termui" @@ -29,7 +29,6 @@ type DiskWidget struct { *ui.Table updateInterval time.Duration Partitions map[string]*Partition - metric map[string]prometheus.Gauge } // TODO: Add filtering @@ -65,17 +64,11 @@ func NewDiskWidget() *DiskWidget { } 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", - Name: strings.ReplaceAll(key, "/", ":"), - //Name: strings.Replace(strings.Replace(part.Device, "/dev/", "", -1), "mapper/", "", -1), + pc := part + metrics.NewGauge(makeName("disk", strings.ReplaceAll(key, "/", ":")), func() float64 { + return float64(pc.UsedPercent) / 100.0 }) - gauge.Set(float64(part.UsedPercent) / 100.0) - prometheus.MustRegister(gauge) - disk.metric[key] = gauge } } @@ -176,12 +169,5 @@ func (disk *DiskWidget) update() { 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 { - disk.metric[key].Set(float64(partition.UsedPercent) / 100.0) - } - } } } diff --git a/widgets/mem.go b/widgets/mem.go index 6b5d326..b994276 100644 --- a/widgets/mem.go +++ b/widgets/mem.go @@ -4,7 +4,7 @@ import ( "fmt" "time" - "github.com/prometheus/client_golang/prometheus" + "github.com/VictoriaMetrics/metrics" "github.com/xxxserxxx/gotop/v4/devices" ui "github.com/xxxserxxx/gotop/v4/termui" @@ -14,52 +14,47 @@ import ( type MemWidget struct { *ui.LineGraph updateInterval time.Duration - metrics map[string]prometheus.Gauge } func NewMemWidget(updateInterval time.Duration, horizontalScale int) *MemWidget { - self := &MemWidget{ + widg := &MemWidget{ LineGraph: ui.NewLineGraph(), updateInterval: updateInterval, } - self.Title = " Memory Usage " - self.HorizontalScale = horizontalScale + widg.Title = " Memory Usage " + widg.HorizontalScale = horizontalScale mems := make(map[string]devices.MemoryInfo) devices.UpdateMem(mems) for name, mem := range mems { - self.Data[name] = []float64{0} - self.renderMemInfo(name, mem) + widg.Data[name] = []float64{0} + widg.renderMemInfo(name, mem) } go func() { - for range time.NewTicker(self.updateInterval).C { - self.Lock() + for range time.NewTicker(widg.updateInterval).C { + widg.Lock() devices.UpdateMem(mems) for label, mi := range mems { - self.renderMemInfo(label, mi) - if self.metrics != nil && self.metrics[label] != nil { - self.metrics[label].Set(mi.UsedPercent) - } + widg.renderMemInfo(label, mi) } - self.Unlock() + widg.Unlock() } }() - return self + return widg } func (mem *MemWidget) EnableMetric() { - mem.metrics = make(map[string]prometheus.Gauge) mems := make(map[string]devices.MemoryInfo) devices.UpdateMem(mems) - for l, m := range mems { - mem.metrics[l] = prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: "gotop", - Subsystem: "memory", - Name: l, + for l, _ := range mems { + lc := l + metrics.NewGauge(makeName("memory", l), func() float64 { + if ds, ok := mem.Data[lc]; ok { + return ds[len(ds)-1] + } + return 0.0 }) - mem.metrics[l].Set(m.UsedPercent) - prometheus.MustRegister(mem.metrics[l]) } } diff --git a/widgets/metrics.go b/widgets/metrics.go new file mode 100644 index 0000000..683b196 --- /dev/null +++ b/widgets/metrics.go @@ -0,0 +1,19 @@ +package widgets + +import ( + "fmt" + "strings" +) + +// makeName creates a prometheus metric name in the gotop space +// This function doesn't have to be very efficient because it's only +// called at init time, and only a few dozen times... and it isn't +// (very efficient). +func makeName(parts ...interface{}) string { + args := make([]string, len(parts)+1) + args[0] = "gotop" + for i, v := range parts { + args[i+1] = fmt.Sprintf("%v", v) + } + return strings.Join(args, "_") +} diff --git a/widgets/net.go b/widgets/net.go index 9cd4211..b76d6b4 100644 --- a/widgets/net.go +++ b/widgets/net.go @@ -6,7 +6,7 @@ import ( "strings" "time" - "github.com/prometheus/client_golang/prometheus" + "github.com/VictoriaMetrics/metrics" psNet "github.com/shirou/gopsutil/net" ui "github.com/xxxserxxx/gotop/v4/termui" @@ -28,8 +28,8 @@ type NetWidget struct { totalBytesRecv uint64 totalBytesSent uint64 NetInterface []string - sentMetric prometheus.Counter - recvMetric prometheus.Counter + sentMetric *metrics.Counter + recvMetric *metrics.Counter Mbps bool } @@ -66,19 +66,8 @@ func NewNetWidget(netInterface string) *NetWidget { } func (net *NetWidget) EnableMetric() { - net.recvMetric = prometheus.NewCounter(prometheus.CounterOpts{ - Namespace: "gotop", - Subsystem: "net", - Name: "recv", - }) - prometheus.MustRegister(net.recvMetric) - - net.sentMetric = prometheus.NewCounter(prometheus.CounterOpts{ - Namespace: "gotop", - Subsystem: "net", - Name: "sent", - }) - prometheus.MustRegister(net.sentMetric) + net.recvMetric = metrics.NewCounter(makeName("net", "recv")) + net.sentMetric = metrics.NewCounter(makeName("net", "sent")) } func (net *NetWidget) update() { @@ -138,8 +127,8 @@ func (net *NetWidget) update() { 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)) + net.sentMetric.Add(int(recentBytesSent)) + net.recvMetric.Add(int(recentBytesRecv)) } } diff --git a/widgets/temp.go b/widgets/temp.go index f2b0f93..5a22897 100644 --- a/widgets/temp.go +++ b/widgets/temp.go @@ -6,8 +6,8 @@ import ( "sort" "time" + "github.com/VictoriaMetrics/metrics" ui "github.com/gizak/termui/v3" - "github.com/prometheus/client_golang/prometheus" "github.com/xxxserxxx/gotop/v4/devices" "github.com/xxxserxxx/gotop/v4/utils" @@ -28,7 +28,7 @@ type TempWidget struct { TempLowColor ui.Color TempHighColor ui.Color TempScale TempScale - tempsMetric map[string]prometheus.Gauge + temps map[string]float64 } func NewTempWidget(tempScale TempScale, filter []string) *TempWidget { @@ -68,16 +68,12 @@ func NewTempWidget(tempScale TempScale, filter []string) *TempWidget { } 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", - Name: k, + temp.temps = make(map[string]float64) + for k, _ := range temp.Data { + kc := k + metrics.NewGauge(makeName("temp", k), func() float64 { + return float64(temp.Data[kc]) }) - gauge.Set(float64(v)) - prometheus.MustRegister(gauge) - temp.tempsMetric[k] = gauge } } @@ -109,9 +105,6 @@ func (temp *TempWidget) Draw(buf *ui.Buffer) { image.Pt(temp.Inner.Min.X, temp.Inner.Min.Y+y), ) - if temp.tempsMetric != nil { - temp.tempsMetric[key].Set(float64(temp.Data[key])) - } temperature := fmt.Sprintf("%3d°%c", temp.Data[key], temp.TempScale) buf.SetString( -- cgit v1.2.3 From f5fc8b18547bcd71e60190a9c408d482c33bcb00 Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Wed, 13 May 2020 10:08:43 -0500 Subject: Missed a no-longer-used attribute --- widgets/batterygauge.go | 1 - 1 file changed, 1 deletion(-) (limited to 'widgets') diff --git a/widgets/batterygauge.go b/widgets/batterygauge.go index 3a89707..c2cab1d 100644 --- a/widgets/batterygauge.go +++ b/widgets/batterygauge.go @@ -14,7 +14,6 @@ import ( type BatteryGauge struct { *termui.Gauge - metric *metrics.Gauge } func NewBatteryGauge() *BatteryGauge { -- cgit v1.2.3 From 5123568b923991f9fba318954ea3e8cf6785e252 Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Sun, 31 May 2020 14:45:24 -0500 Subject: Only report battery sensor errors once; closes #117 --- widgets/batterygauge.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'widgets') diff --git a/widgets/batterygauge.go b/widgets/batterygauge.go index f28dd34..135f223 100644 --- a/widgets/batterygauge.go +++ b/widgets/batterygauge.go @@ -39,11 +39,16 @@ func (b *BatteryGauge) EnableMetric() { }) } +// Only report battery errors once. +var errLogged = false + func (b *BatteryGauge) update() { - // FIXME: Getting a lot of these in the logs bats, err := battery.GetAll() if err != nil { - log.Printf("error setting up batteries: %v", err) + if !errLogged { + log.Printf("error setting up batteries: %v", err) + errLogged = true + } return } mx := 0.0 -- cgit v1.2.3