summaryrefslogtreecommitdiffstats
path: root/widgets/cpu.go
blob: 2668b3abae600dc3f406825492f94fc87531b434 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package widgets

import (
	"fmt"
	"time"

	"github.com/VictoriaMetrics/metrics"
	"github.com/VividCortex/ewma"
	"github.com/xxxserxxx/gotop/v4/devices"

	"github.com/gizak/termui/v3"
	ui "github.com/xxxserxxx/gotop/v4/termui"
)

type CPUWidget struct {
	*ui.LineGraph
	CPUCount        int
	ShowAverageLoad bool
	ShowPerCPULoad  bool
	updateInterval  time.Duration
	cpuLoads        map[string]float64
	average         ewma.MovingAverage
}

var cpuLabels []string

func NewCPUWidget(updateInterval time.Duration, horizontalScale int, showAverageLoad bool, showPerCPULoad bool) *CPUWidget {
	self := &CPUWidget{
		LineGraph:       ui.NewLineGraph(),
		CPUCount:        len(cpuLabels),
		updateInterval:  updateInterval,
		ShowAverageLoad: showAverageLoad,
		ShowPerCPULoad:  showPerCPULoad,
		cpuLoads:        make(map[string]float64),
		average:         ewma.NewMovingAverage(),
	}
	self.LabelStyles[AVRG] = termui.ModifierBold
	self.Title = " CPU Usage "
	self.HorizontalScale = horizontalScale

	if !(self.ShowAverageLoad || self.ShowPerCPULoad) {
		if self.CPUCount <= 8 {
			self.ShowPerCPULoad = true
		} else {
			self.ShowAverageLoad = true
		}
	}

	if self.ShowAverageLoad {
		self.Data[AVRG] = []float64{0}
	}

	if self.ShowPerCPULoad {
		cpus := make(map[string]int)
		devices.UpdateCPU(cpus, self.updateInterval, self.ShowPerCPULoad)
		for k, v := range cpus {
			self.Data[k] = []float64{float64(v)}
		}
	}

	self.update()

	go func() {
		for range time.NewTicker(self.updateInterval).C {
			self.update()
		}
	}()

	return self
}

const AVRG = "AVRG"

func (cpu *CPUWidget) EnableMetric() {
	if cpu.ShowAverageLoad {
		metrics.NewGauge(makeName("cpu", " avg"), func() float64 {
			return cpu.cpuLoads[AVRG]
		})
	} else {
		cpus := make(map[string]int)
		devices.UpdateCPU(cpus, cpu.updateInterval, cpu.ShowPerCPULoad)
		for key, perc := range cpus {
			kc := key
			cpu.cpuLoads[key] = float64(perc)
			metrics.NewGauge(makeName("cpu", key), func() float64 {
				return cpu.cpuLoads[kc]
			})
		}
	}
}

func (cpu *CPUWidget) Scale(i int) {
	cpu.LineGraph.HorizontalScale = i
}

func (cpu *CPUWidget) update() {
	go func() {
		cpus := make(map[string]int)
		devices.UpdateCPU(cpus, cpu.updateInterval, true)
		cpu.Lock()
		defer cpu.Unlock()
		// AVG = ((AVG*i)+n)/(i+1)
		var sum int
		for key, percent := range cpus {
			sum += percent
			if cpu.ShowPerCPULoad {
				cpu.Data[key] = append(cpu.Data[key], float64(percent))
				cpu.Labels[key] = fmt.Sprintf("%d%%", percent)
				cpu.cpuLoads[key] = float64(percent)
			}
		}
		if cpu.ShowAverageLoad {
			cpu.average.Add(float64(sum) / float64(len(cpus)))
			avg := cpu.average.Value()
			cpu.Data[AVRG] = append(cpu.Data[AVRG], avg)
			cpu.Labels[AVRG] = fmt.Sprintf("%3.0f%%", avg)
			cpu.cpuLoads[AVRG] = avg
		}
	}()
}