Abstracts CPU & mem devices.

Finishes device refactoring: temps

Refactoring to allow updating maps. Simpler, and optimizable.
This commit is contained in:
Sean E. Russell 2020-02-27 18:51:28 -06:00
parent 4fce1654c5
commit 7a89225d72
25 changed files with 418 additions and 629 deletions

View File

@ -1,44 +1,34 @@
package devices
import (
"log"
"time"
)
var deviceCounts []func(bool) (int, error)
var devicePercents []func(time.Duration, bool) ([]float64, error)
var numDevices int
var cpuFuncs []func(map[string]float64, time.Duration, bool) map[string]error
// Counts returns the number of CPUs registered.
// RegisterCPU adds a new CPU device to the CPU widget. labels returns the
// names of the devices; they should be as short as possible, and the indexes
// of the returned slice should align with the values returned by the percents
// function. The percents function should return the percent CPU usage of the
// device(s), sliced over the time duration supplied. If the bool argument to
// percents is true, it is expected that the return slice
//
// logical tells Counts to count the logical cores; this may be ignored for
// some devices.
func Counts(logical bool) (int, error) {
var rv int
var re error
for _, d := range deviceCounts {
r, err := d(logical)
if err != nil {
return rv, re
}
rv += r
}
return rv, re
// labels may be called once and the value cached. This means the number of
// cores should not change dynamically.
func RegisterCPU(f func(map[string]float64, time.Duration, bool) map[string]error) {
cpuFuncs = append(cpuFuncs, f)
}
// Percent calculates the percentage of cpu used either per CPU or combined.
// CPUPercent calculates the percentage of cpu used either per CPU or combined.
// Returns one value per cpu, or a single value if percpu is set to false.
func Percent(interval time.Duration, combined bool) ([]float64, error) {
var rvs []float64
rvs = make([]float64, 0, numDevices)
for _, f := range devicePercents {
vs, err := f(interval, combined)
if err != nil {
return rvs, err
}
for _, v := range vs {
rvs = append(rvs, v)
func UpdateCPU(cpus map[string]float64, interval time.Duration, logical bool) {
for _, f := range cpuFuncs {
errs := f(cpus, interval, logical)
if errs != nil {
for k, e := range errs {
log.Printf("%s: %s", k, e)
}
}
}
numDevices = len(rvs)
return rvs, nil
}

View File

@ -1,10 +1,31 @@
package devices
import (
"fmt"
"time"
psCpu "github.com/shirou/gopsutil/cpu"
)
func init() {
deviceCounts = append(deviceCounts, psCpu.Counts)
devicePercents = append(devicePercents, psCpu.Percent)
f := func(cpus map[string]float64, iv time.Duration, l bool) map[string]error {
cpuCount, err := psCpu.Counts(l)
if err != nil {
return nil
}
formatString := "CPU%1d"
if cpuCount > 10 {
formatString = "CPU%02d"
}
vals, err := psCpu.Percent(iv, l)
if err != nil {
return map[string]error{"gopsutil": err}
}
for i := 0; i < len(vals); i++ {
key := fmt.Sprintf(formatString, i)
cpus[key] = vals[i]
}
return nil
}
RegisterCPU(f)
}

26
devices/mem.go Normal file
View File

@ -0,0 +1,26 @@
package devices
import "log"
var memFuncs []func(map[string]MemoryInfo) map[string]error
type MemoryInfo struct {
Total uint64
Used uint64
UsedPercent float64
}
func RegisterMem(f func(map[string]MemoryInfo) map[string]error) {
memFuncs = append(memFuncs, f)
}
func UpdateMem(mem map[string]MemoryInfo) {
for _, f := range memFuncs {
errs := f(mem)
if errs != nil {
for k, e := range errs {
log.Printf("%s: %s", k, e)
}
}
}
}

21
devices/mem_mem.go Normal file
View File

@ -0,0 +1,21 @@
package devices
import (
psMem "github.com/shirou/gopsutil/mem"
)
func init() {
mf := func(mems map[string]MemoryInfo) map[string]error {
mainMemory, err := psMem.VirtualMemory()
if err != nil {
return map[string]error{"Main": err}
}
mems["Main"] = MemoryInfo{
Total: mainMemory.Total,
Used: mainMemory.Used,
UsedPercent: mainMemory.UsedPercent,
}
return nil
}
RegisterMem(mf)
}

View File

@ -0,0 +1,44 @@
// +build freebsd
package devices
import (
"os/exec"
"strconv"
"strings"
)
func init() {
mf := func(mems map[string]MemoryInfo) map[string]error {
cmd := "swapinfo -k|sed -n '1!p'|awk '{print $2,$3,$5}'"
output, err := exec.Command("sh", "-c", cmd).Output()
if err != nil {
return map[string]error{"swapinfo": err}
}
s := strings.TrimSuffix(string(output), "\n")
s = strings.ReplaceAll(s, "\n", " ")
ss := strings.Split(s, " ")
ss = ss[((len(ss)/3)-1)*3:]
errors := make(map[string]error)
mem := MemoryInfo{}
mem.Total, err = strconv.ParseUint(ss[0], 10, 64)
if err != nil {
errors["swap total"] = err
}
mem.Used, err = strconv.ParseUint(ss[1], 10, 64)
if err != nil {
errors["swap used"] = err
}
mem.UsedPercent, err = strconv.ParseFloat(strings.TrimSuffix(ss[2], "%"), 64)
if err != nil {
errors["swap percent"] = err
}
mems["Swap"] = mem
return errors
}
RegisterMem(mf)
}

23
devices/mem_swap_other.go Normal file
View File

@ -0,0 +1,23 @@
// +build !freebsd
package devices
import (
psMem "github.com/shirou/gopsutil/mem"
)
func init() {
mf := func(mems map[string]MemoryInfo) map[string]error {
memory, err := psMem.SwapMemory()
if err != nil {
return map[string]error{"Swap": err}
}
mems["Swap"] = MemoryInfo{
Total: memory.Total,
Used: memory.Used,
UsedPercent: memory.UsedPercent,
}
return nil
}
RegisterMem(mf)
}

22
devices/temp.go Normal file
View File

@ -0,0 +1,22 @@
package devices
import (
"log"
)
var tempUpdates []func(map[string]int) map[string]error
func RegisterTemp(update func(map[string]int) map[string]error) {
tempUpdates = append(tempUpdates, update)
}
func UpdateTemps(temps map[string]int) {
for _, f := range tempUpdates {
errs := f(temps)
if errs != nil {
for k, e := range errs {
log.Printf("error updating temp for %s: %s", k, e)
}
}
}
}

View File

@ -1,22 +1,16 @@
// +build darwin
package widgets
package devices
// #cgo LDFLAGS: -framework IOKit
// #include "include/smc.c"
import "C"
import (
"log"
"github.com/xxxserxxx/gotop/utils"
)
type TemperatureStat struct {
SensorKey string `json:"sensorKey"`
Temperature float64 `json:"sensorTemperature"`
func init() {
RegisterTemp(update)
}
func SensorsTemperatures() ([]TemperatureStat, error) {
func update(temps map[string]int) map[string]error {
temperatureKeys := map[string]string{
C.AMBIENT_AIR_0: "ambient_air_0",
C.AMBIENT_AIR_1: "ambient_air_1",
@ -41,34 +35,12 @@ func SensorsTemperatures() ([]TemperatureStat, error) {
C.WIRELESS_MODULE: "wireless_module",
}
var temperatures []TemperatureStat
C.open_smc()
defer C.close_smc()
for key, val := range temperatureKeys {
temperatures = append(temperatures, TemperatureStat{
SensorKey: val,
Temperature: float64(C.get_tmp(C.CString(key), C.CELSIUS)),
})
temps[val] = int(C.get_tmp(C.CString(key), C.CELSIUS))
}
return temperatures, nil
}
func (self *TempWidget) update() {
sensors, err := SensorsTemperatures()
if err != nil {
log.Printf("failed to get sensors from CGO: %v", err)
return
}
for _, sensor := range sensors {
if sensor.Temperature != 0 {
switch self.TempScale {
case Fahrenheit:
self.Data[sensor.SensorKey] = utils.CelsiusToFahrenheit(int(sensor.Temperature))
case Celsius:
self.Data[sensor.SensorKey] = int(sensor.Temperature)
}
}
}
return nil
}

45
devices/temp_freebsd.go Normal file
View File

@ -0,0 +1,45 @@
// +build freebsd
package devices
import (
"os/exec"
"strconv"
"strings"
"github.com/xxxserxxx/gotop/utils"
)
func init() {
RegisterTemp(update)
}
var sensorOIDS = map[string]string{
"dev.cpu.0.temperature": "CPU 0 ",
"hw.acpi.thermal.tz0.temperature": "Thermal zone 0",
}
func update(temps map[string]int) map[string]error {
var errors map[string]error
for k, v := range sensorOIDS {
output, err := exec.Command("sysctl", "-n", k).Output()
if err != nil {
errors[v] = err
continue
}
s1 := strings.Replace(string(output), "C", "", 1)
s2 := strings.TrimSuffix(s1, "\n")
convertedOutput := utils.ConvertLocalizedString(s2)
value, err := strconv.ParseFloat(convertedOutput, 64)
if err != nil {
errors[v] = err
continue
}
temps[v] = int(value)
}
return errors
}

View File

@ -1,32 +1,29 @@
// +build linux
package widgets
package devices
import (
"log"
"strings"
psHost "github.com/shirou/gopsutil/host"
"github.com/xxxserxxx/gotop/utils"
)
func (self *TempWidget) update() {
func init() {
RegisterTemp(getTemps)
}
func getTemps(temps map[string]int) map[string]error {
sensors, err := psHost.SensorsTemperatures()
if err != nil {
log.Printf("error received from gopsutil: %v", err)
return map[string]error{"psHost": err}
}
for _, sensor := range sensors {
// only sensors with input in their name are giving us live temp info
if strings.Contains(sensor.SensorKey, "input") && sensor.Temperature != 0 {
// removes '_input' from the end of the sensor name
label := sensor.SensorKey[:strings.Index(sensor.SensorKey, "_input")]
switch self.TempScale {
case Fahrenheit:
self.Data[label] = utils.CelsiusToFahrenheit(int(sensor.Temperature))
case Celsius:
self.Data[label] = int(sensor.Temperature)
}
temps[label] = int(sensor.Temperature)
}
}
return nil
}

View File

@ -1,6 +1,6 @@
// +build openbsd
package widgets
package devices
// loosely based on https://github.com/openbsd/src/blob/master/sbin/sysctl/sysctl.c#L2517
@ -13,42 +13,13 @@ import (
"strconv"
"syscall"
"unsafe"
"github.com/xxxserxxx/gotop/utils"
)
func (self *TempWidget) getTemp(mib []C.int, mlen int, snsrdev *C.struct_sensordev, index int) {
switch mlen {
case 4:
k := mib[3]
var numt C.int
for numt = 0; numt < snsrdev.maxnumt[k]; numt++ {
mib[4] = numt
self.getTemp(mib, mlen+1, snsrdev, int(numt))
}
case 5:
var snsr C.struct_sensor
var slen C.size_t = C.sizeof_struct_sensor
if v, _ := C.sysctl(&mib[0], 5, unsafe.Pointer(&snsr), &slen, nil, 0); v == -1 {
return
}
if slen > 0 && (snsr.flags&C.SENSOR_FINVALID) == 0 {
key := C.GoString(&snsrdev.xname[0]) + ".temp" + strconv.Itoa(index)
temp := int((snsr.value - 273150000.0) / 1000000.0)
switch self.TempScale {
case Fahrenheit:
self.Data[key] = utils.CelsiusToFahrenheit(temp)
case Celsius:
self.Data[key] = temp
}
}
}
func init() {
RegisterTemp(update)
}
func (self *TempWidget) update() {
func update(temps map[string]int) map[string]error {
mib := []C.int{0, 1, 2, 3, 4}
var snsrdev C.struct_sensordev
@ -69,6 +40,33 @@ func (self *TempWidget) update() {
break
}
}
self.getTemp(mib, 4, &snsrdev, 0)
getTemp(temps, mib, 4, &snsrdev, 0)
}
return nil
}
func getTemp(temps map[string]int, mib []C.int, mlen int, snsrdev *C.struct_sensordev, index int) {
switch mlen {
case 4:
k := mib[3]
var numt C.int
for numt = 0; numt < snsrdev.maxnumt[k]; numt++ {
mib[4] = numt
getTemp(temps, mib, mlen+1, snsrdev, int(numt))
}
case 5:
var snsr C.struct_sensor
var slen C.size_t = C.sizeof_struct_sensor
if v, _ := C.sysctl(&mib[0], 5, unsafe.Pointer(&snsr), &slen, nil, 0); v == -1 {
return
}
if slen > 0 && (snsr.flags&C.SENSOR_FINVALID) == 0 {
key := C.GoString(&snsrdev.xname[0]) + ".temp" + strconv.Itoa(index)
temp := int((snsr.value - 273150000.0) / 1000000.0)
temps[key] = temp
}
}
}

24
devices/temp_windows.go Normal file
View File

@ -0,0 +1,24 @@
// +build windows
package devices
import (
psHost "github.com/shirou/gopsutil/host"
)
func init() {
RegisterTemp(update)
}
func update(temps map[string]int) map[string]error {
sensors, err := psHost.SensorsTemperatures()
if err != nil {
return map[string]error{"gopsutil": err}
}
for _, sensor := range sensors {
if sensor.Temperature != 0 {
temps[sensor.SensorKey] = int(sensor.Temperature)
}
}
return nil
}

11
go.mod
View File

@ -1,27 +1,18 @@
module github.com/xxxserxxx/gotop
require (
github.com/GeertJohan/go.rice v1.0.0 // indirect
github.com/NVIDIA/gpu-monitoring-tools v0.0.0-20200116003318-021662a21098
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
github.com/distatus/battery v0.9.0
github.com/docopt/docopt.go v0.0.0-20180111231733-ee0de3bc6815
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect
github.com/gizak/termui/v3 v3.0.0
github.com/go-ole/go-ole v1.2.1 // indirect
github.com/k0kubun/pp v3.0.1+incompatible // indirect
github.com/mailru/easyjson v0.7.1 // indirect
github.com/mattn/go-runewidth v0.0.4
github.com/mitchellh/go-wordwrap v1.0.0 // indirect
github.com/prometheus/client_golang v1.4.1
github.com/rai-project/config v0.0.0-20190926180509-3bd01e698aad // indirect
github.com/rai-project/logger v0.0.0-20190701163301-49978a80bf96 // indirect
github.com/rai-project/nvidia-smi v0.0.0-20190730061239-864eb441c9ae
github.com/rai-project/tegra v0.0.0-20181119122707-1d9901ca382b // indirect
github.com/shirou/gopsutil v2.18.11+incompatible
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 // indirect
github.com/stretchr/testify v1.4.0
howett.net/plist v0.0.0-20181124034731-591f970eefbb // indirect
)
go 1.12
go 1.13

124
go.sum
View File

@ -1,19 +1,9 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/GeertJohan/go-sourcepath v0.0.0-20150925135350-83e8b8723a9b/go.mod h1:X/dh6iyBHZUR+NSNoO9isIl7cRw4n09jwjK5tfr+Rno=
github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0=
github.com/GeertJohan/go.rice v0.0.0-20170420135705-c02ca9a983da/go.mod h1:DgrzXonpdQbfN3uYaGz1EG4Sbhyum/MMIn6Cphlh2bw=
github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0=
github.com/NVIDIA/gpu-monitoring-tools v0.0.0-20200116003318-021662a21098 h1:9qTpKR5TnUxu+ViqhxkpANee27meaoHYwV0f1SnRqgI=
github.com/NVIDIA/gpu-monitoring-tools v0.0.0-20200116003318-021662a21098/go.mod h1:nMOvShGpWaf0bXwXmeu4k+O4uziuaEI8pWzIj3BUrOA=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/Unknwon/com v0.0.0-20151008135407-28b053d5a292/go.mod h1:KYCjqMOeHpNuTOiFQU6WEcTG7poCJrUs0YgyHNtn1no=
github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@ -22,106 +12,63 @@ github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cjbassi/drawille-go v0.0.0-20190126131713-27dc511fe6fd h1:XtfPmj9tQRilnrEmI1HjQhxXWRhEM+m8CACtaMJE/kM=
github.com/cjbassi/drawille-go v0.0.0-20190126131713-27dc511fe6fd/go.mod h1:vjcQJUZJYD3MeVGhtZXSMnCHfUNZxsyYzJt90eCYxK4=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.8+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/daaku/go.zipexe v0.0.0-20150329023125-a5fe2436ffcb/go.mod h1:U0vRfAucUOohvdCxt5MWLF+TePIL0xbCkbKIiV8TQCE=
github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/distatus/battery v0.9.0 h1:8NS5o00/j3Oh2xgocA6pQROTp5guoR+s8CZlWzHC4QM=
github.com/distatus/battery v0.9.0/go.mod h1:gGO7GxHTi1zlRT+cAj8uGG0/8HFiqAeH0TJvoipnuPs=
github.com/docopt/docopt.go v0.0.0-20180111231733-ee0de3bc6815 h1:HMAfwOa33y82IaQEKQDfUCiwNlxtM1iw7HLM9ru0RNc=
github.com/docopt/docopt.go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:l7JNRynTRuqe45tpIyItHNqZWTxywYjp87MWTOnU5cg=
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/structs v1.0.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gizak/termui/v3 v3.0.0 h1:NYTUG6ig/sJK05O5FyhWemwlVPO8ilNpvS/PgRtrKAE=
github.com/gizak/termui/v3 v3.0.0/go.mod h1:uinu2dMdtMI+FTIdEFUJQT5y+KShnhQRshvPblXq3lY=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E=
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
github.com/k0kubun/pp v2.3.0+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg=
github.com/k0kubun/pp v3.0.1+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg=
github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/go-homedir v0.0.0-20180523094522-3864e76763d9/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/mapstructure v0.0.0-20180511142126-bb74f1db0675/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E=
github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d h1:x3S6kxmy49zXVVyhcnrFqxvNVCBPb2KZ9hV2RBdS840=
github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pquerna/ffjson v0.0.0-20181028064349-e517b90714f7/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.4.1 h1:FFSuS004yOQEtDdTq+TAOLP5xUq63KqAFYyOi8zA+Y8=
github.com/prometheus/client_golang v1.4.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
@ -129,98 +76,53 @@ github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U=
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/rai-project/config v0.0.0-20190926180509-3bd01e698aad/go.mod h1:NGYIJHnNhNRYvFYWqSCbPqsnwJ6uLC4q2eddpInHgVk=
github.com/rai-project/godotenv v0.0.0-20180619160704-a501614c3b8d/go.mod h1:91keR8FKb9xXErPghO6kMay+2MQb4g+gIZey/W/vv8w=
github.com/rai-project/logger v0.0.0-20190701163301-49978a80bf96/go.mod h1:aFDuHWECvho4yTAOeAgPjuLIeGiYrURMS16V//PDmi8=
github.com/rai-project/nvidia-smi v0.0.0-20190730061239-864eb441c9ae/go.mod h1:4LLEYSw0LpRcuOwqSpyeMextz9hqvPE4TU6IGmkT2mA=
github.com/rai-project/tegra v0.0.0-20181119122707-1d9901ca382b/go.mod h1:Fj5aBtW50UAsFCeS9X/t0eoGJvMQAW4w4PDAuRtZLMc=
github.com/rai-project/utils v0.0.0-20180619204045-c582bb171808/go.mod h1:I/Ti6TSU785mVLG5ybjSjFOnJI0u6IRjRVosnGbrFfg=
github.com/rai-project/vipertags v0.0.0-20180619160704-1b2055ebed22/go.mod h1:+2KFcVdODWrMQkdYtv7MrXCTpW2RNKXZzO/RsvEQnWc=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/shirou/gopsutil v2.18.11+incompatible h1:PMFTKnFTr/YTRW5rbLK4vWALV3a+IGXse5nvhSjztmg=
github.com/shirou/gopsutil v2.18.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 h1:udFKJ0aHUL60LboW/A+DfgoHVedieIzIXE8uylPue0U=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v0.0.0-20190306220146-200a235640ff/go.mod h1:KSQcGKpxUMHk3nbYzs/tIBAM2iDooCn0BmttHOJEbLs=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spf13/afero v1.1.1/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v0.0.0-20180507071007-15738813a09d/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v0.0.0-20171019201919-bdcc60b419d1/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.0-20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
golang.org/x/arch v0.0.0-20181203225421-5a4828bb7045/go.mod h1:cYlCBUl1MsqxdiKgmc4uh7TxZfWSFLOGSRR090WDxt8=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82 h1:ywK/j/KkyTHcdyYSZNXGjMwgmDSfjglYZ3vStQ/gSCU=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
howett.net/plist v0.0.0-20181124034731-591f970eefbb h1:jhnBjNi9UFpfpl8YZhA9CrOqpnJdvzuiHsl/dnxl11M=
howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0=

View File

@ -46,7 +46,6 @@ func Layout(wl layout, c gotop.Config) (*MyGrid, error) {
rgs := make([]interface{}, 0)
for i, ur := range uiRows {
rh := float64(heights[i]) / float64(maxHeight)
log.Printf("appending row %d with height %d", i, heights[i])
rgs = append(rgs, ui.NewRow(rh, ur...))
}
grid := &MyGrid{ui.NewGrid(), nil, nil}
@ -65,8 +64,6 @@ func Layout(wl layout, c gotop.Config) (*MyGrid, error) {
// rows as the largest row span object in the row, and produce an uber-row
// containing all that stuff. It returns a slice without the consumed elements.
func processRow(c gotop.Config, numRows int, rowDefs [][]widgetRule) (int, []interface{}, [][]widgetRule) {
log.Printf("got %d rows", len(rowDefs))
// Recursive function #3. See the comment in deepFindProc.
if len(rowDefs) < 1 {
return 0, nil, [][]widgetRule{}
@ -75,7 +72,6 @@ func processRow(c gotop.Config, numRows int, rowDefs [][]widgetRule) (int, []int
// will be consumed, and the overall height of the row that will be
// produced.
maxHeight := countMaxHeight([][]widgetRule{rowDefs[0]})
log.Printf("maxHeight %d", maxHeight)
var processing [][]widgetRule
if maxHeight < len(rowDefs) {
processing = rowDefs[0:maxHeight]
@ -84,7 +80,6 @@ func processRow(c gotop.Config, numRows int, rowDefs [][]widgetRule) (int, []int
processing = rowDefs[0:]
rowDefs = [][]widgetRule{}
}
log.Printf("consuming %d rows, %d remainder rows", len(processing), len(rowDefs))
var colWeights []float64
var columns [][]interface{}
numCols := len(processing[0])
@ -110,7 +105,6 @@ outer:
}
if full {
rowDefs = append(processing[i:], rowDefs...)
log.Printf("prepended early consumption; remainder now %d rows", len(rowDefs))
break
}
// Not all rows have been consumed, so go ahead and place the row's
@ -141,7 +135,6 @@ outer:
}
}
log.Printf("returning %d columns", len(uiColumns))
return maxHeight, uiColumns, rowDefs
}

View File

@ -92,6 +92,7 @@ function cdarwinz() {
cd darwin
else
cd darwin
git checkout -- .
git pull
fi
export CGO_ENABLED=1

View File

@ -1,14 +1,12 @@
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"
@ -20,27 +18,19 @@ type CpuWidget struct {
ShowAverageLoad bool
ShowPerCpuLoad bool
updateInterval time.Duration
formatString string
updateLock sync.Mutex
metric []prometheus.Gauge
metric map[string]prometheus.Gauge
}
var cpuLabels []string
func NewCpuWidget(updateInterval time.Duration, horizontalScale int, showAverageLoad bool, showPerCpuLoad bool) *CpuWidget {
cpuCount, err := devices.Counts(false)
if err != nil {
log.Printf("failed to get CPU count: %v", err)
}
formatString := "CPU%1d"
if cpuCount > 10 {
formatString = "CPU%02d"
}
self := &CpuWidget{
LineGraph: ui.NewLineGraph(),
CpuCount: cpuCount,
CpuCount: len(cpuLabels),
updateInterval: updateInterval,
ShowAverageLoad: showAverageLoad,
ShowPerCpuLoad: showPerCpuLoad,
formatString: formatString,
}
self.Title = " CPU Usage "
self.HorizontalScale = horizontalScale
@ -58,9 +48,10 @@ func NewCpuWidget(updateInterval time.Duration, horizontalScale int, showAverage
}
if self.ShowPerCpuLoad {
for i := 0; i < int(self.CpuCount); i++ {
key := fmt.Sprintf(formatString, i)
self.Data[key] = []float64{0}
cpus := make(map[string]float64)
devices.UpdateCPU(cpus, self.updateInterval, self.ShowPerCpuLoad)
for k, v := range cpus {
self.Data[k] = []float64{v}
}
}
@ -77,29 +68,24 @@ func NewCpuWidget(updateInterval time.Duration, horizontalScale int, showAverage
func (self *CpuWidget) EnableMetric() {
if self.ShowAverageLoad {
self.metric = make([]prometheus.Gauge, 1)
self.metric[0] = prometheus.NewGauge(prometheus.GaugeOpts{
self.metric = make(map[string]prometheus.Gauge)
self.metric["AVRG"] = 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 {
cpus := make(map[string]float64)
devices.UpdateCPU(cpus, self.updateInterval, self.ShowPerCpuLoad)
self.metric = make(map[string]prometheus.Gauge)
for key, perc := range cpus {
gauge := prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: "gotop",
Subsystem: "cpu",
Name: fmt.Sprintf("%d", i),
Name: key,
})
gauge.Set(perc)
prometheus.MustRegister(gauge)
self.metric[i] = gauge
self.metric[key] = gauge
}
}
}
@ -111,47 +97,41 @@ func (b *CpuWidget) Scale(i int) {
func (self *CpuWidget) update() {
if self.ShowAverageLoad {
go func() {
percent, err := devices.Percent(self.updateInterval, false)
if err != nil {
log.Printf("failed to get average CPU usage percent: %v. self.updateInterval: %v. percpu: %v", err, self.updateInterval, false)
} else {
self.Lock()
defer self.Unlock()
self.updateLock.Lock()
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])
}
cpus := make(map[string]float64)
devices.UpdateCPU(cpus, self.updateInterval, false)
self.Lock()
defer self.Unlock()
self.updateLock.Lock()
defer self.updateLock.Unlock()
var val float64
for _, v := range cpus {
val = 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)
}
}()
}
if self.ShowPerCpuLoad {
go func() {
percents, err := devices.Percent(self.updateInterval, true)
if err != nil {
log.Printf("failed to get CPU usage percents: %v. self.updateInterval: %v. percpu: %v", err, self.updateInterval, true)
} else {
if len(percents) != int(self.CpuCount) {
log.Printf("error: number of CPU usage percents doesn't match CPU count. percents: %v. self.Count: %v", percents, self.CpuCount)
} else {
self.Lock()
defer self.Unlock()
self.updateLock.Lock()
defer self.updateLock.Unlock()
for i, percent := range percents {
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)
}
}
cpus := make(map[string]float64)
devices.UpdateCPU(cpus, self.updateInterval, true)
self.Lock()
defer self.Unlock()
self.updateLock.Lock()
defer self.updateLock.Unlock()
for key, percent := range cpus {
self.Data[key] = append(self.Data[key], percent)
self.Labels[key] = fmt.Sprintf("%3.0f%%", percent)
if self.metric != nil {
if self.metric[key] == nil {
log.Printf("no metrics for %s", key)
} else {
self.metric[key].Set(percent)
}
}
}

View File

@ -2,12 +2,11 @@ package widgets
import (
"fmt"
"log"
"time"
"github.com/prometheus/client_golang/prometheus"
psMem "github.com/shirou/gopsutil/mem"
"github.com/xxxserxxx/gotop/devices"
ui "github.com/xxxserxxx/gotop/termui"
"github.com/xxxserxxx/gotop/utils"
)
@ -15,17 +14,60 @@ import (
type MemWidget struct {
*ui.LineGraph
updateInterval time.Duration
mainMetric prometheus.Gauge
swapMetric prometheus.Gauge
metrics map[string]prometheus.Gauge
}
type MemoryInfo struct {
Total uint64
Used uint64
UsedPercent float64
func NewMemWidget(updateInterval time.Duration, horizontalScale int) *MemWidget {
self := &MemWidget{
LineGraph: ui.NewLineGraph(),
updateInterval: updateInterval,
}
self.Title = " Memory Usage "
self.HorizontalScale = horizontalScale
mems := make(map[string]devices.MemoryInfo)
devices.UpdateMem(mems)
for name, mem := range mems {
self.Data[name] = []float64{mem.UsedPercent}
self.renderMemInfo(name, mem)
}
go func() {
for range time.NewTicker(self.updateInterval).C {
self.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)
}
}
self.Unlock()
}
}()
return self
}
func (self *MemWidget) renderMemInfo(line string, memoryInfo MemoryInfo) {
func (b *MemWidget) EnableMetric() {
b.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{
Namespace: "gotop",
Subsystem: "memory",
Name: l,
})
b.metrics[l].Set(mem.UsedPercent)
prometheus.MustRegister(b.metrics[l])
}
}
func (b *MemWidget) Scale(i int) {
b.LineGraph.HorizontalScale = i
}
func (self *MemWidget) renderMemInfo(line string, memoryInfo devices.MemoryInfo) {
self.Data[line] = append(self.Data[line], memoryInfo.UsedPercent)
memoryTotalBytes, memoryTotalMagnitude := utils.ConvertBytes(memoryInfo.Total)
memoryUsedBytes, memoryUsedMagnitude := utils.ConvertBytes(memoryInfo.Used)
@ -37,72 +79,3 @@ func (self *MemWidget) renderMemInfo(line string, memoryInfo MemoryInfo) {
memoryTotalMagnitude,
)
}
func (self *MemWidget) updateMainMemory() {
mainMemory, err := psMem.VirtualMemory()
if err != nil {
log.Printf("failed to get main memory info from gopsutil: %v", err)
} else {
self.renderMemInfo("Main", MemoryInfo{
Total: mainMemory.Total,
Used: mainMemory.Used,
UsedPercent: mainMemory.UsedPercent,
})
if self.mainMetric != nil {
self.mainMetric.Set(mainMemory.UsedPercent)
}
}
}
func NewMemWidget(updateInterval time.Duration, horizontalScale int) *MemWidget {
self := &MemWidget{
LineGraph: ui.NewLineGraph(),
updateInterval: updateInterval,
}
self.Title = " Memory Usage "
self.HorizontalScale = horizontalScale
self.Data["Main"] = []float64{0}
self.Data["Swap"] = []float64{0}
self.updateMainMemory()
self.updateSwapMemory()
go func() {
for range time.NewTicker(self.updateInterval).C {
self.Lock()
self.updateMainMemory()
self.updateSwapMemory()
self.Unlock()
}
}()
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
}

View File

@ -1,67 +0,0 @@
package widgets
import (
"fmt"
"log"
"os/exec"
"strconv"
"strings"
"github.com/xxxserxxx/gotop/utils"
)
func convert(s []string) (MemoryInfo, error) {
total, err := strconv.ParseUint(s[0], 10, 64)
if err != nil {
return MemoryInfo{}, fmt.Errorf("int converion failed %v", err)
}
used, err := strconv.ParseUint(s[1], 10, 64)
if err != nil {
return MemoryInfo{}, fmt.Errorf("int converion failed %v", err)
}
percentage, err := strconv.ParseFloat(strings.TrimSuffix(s[2], "%"), 64)
if err != nil {
return MemoryInfo{}, fmt.Errorf("float converion failed %v", err)
}
return MemoryInfo{
Total: total * utils.KB,
Used: used * utils.KB,
UsedPercent: percentage,
}, nil
}
func gatherSwapInfo() (MemoryInfo, error) {
cmd := "swapinfo -k|sed -n '1!p'|awk '{print $2,$3,$5}'"
output, err := exec.Command("sh", "-c", cmd).Output()
if err != nil {
if err != nil {
return MemoryInfo{}, fmt.Errorf("command failed %v", err)
}
}
s := strings.TrimSuffix(string(output), "\n")
s = strings.ReplaceAll(s, "\n", " ")
ss := strings.Split(s, " ")
ss = ss[((len(ss)/3)-1)*3:]
return convert(ss)
}
func (self *MemWidget) updateSwapMemory() {
swapMemory, err := gatherSwapInfo()
if err != nil {
log.Printf("failed to get swap memory info from gopsutil: %v", err)
} else {
self.renderMemInfo("Swap", MemoryInfo{
Total: swapMemory.Total,
Used: swapMemory.Used,
UsedPercent: swapMemory.UsedPercent,
})
if self.swapMetric != nil {
self.swapMetric.Set(swapMemory.UsedPercent)
}
}
}

View File

@ -1,25 +0,0 @@
// +build !freebsd
package widgets
import (
"log"
psMem "github.com/shirou/gopsutil/mem"
)
func (self *MemWidget) updateSwapMemory() {
swapMemory, err := psMem.SwapMemory()
if err != nil {
log.Printf("failed to get swap memory info from gopsutil: %v", err)
} else {
self.renderMemInfo("Swap", MemoryInfo{
Total: swapMemory.Total,
Used: swapMemory.Used,
UsedPercent: swapMemory.UsedPercent,
})
if self.swapMetric != nil {
self.swapMetric.Set(swapMemory.UsedPercent)
}
}
}

View File

@ -9,6 +9,7 @@ import (
ui "github.com/gizak/termui/v3"
"github.com/prometheus/client_golang/prometheus"
"github.com/xxxserxxx/gotop/devices"
"github.com/xxxserxxx/gotop/utils"
)
@ -100,7 +101,6 @@ func (self *TempWidget) Draw(buf *ui.Buffer) {
image.Pt(self.Inner.Min.X, self.Inner.Min.Y+y),
)
// TODO: state:merge #184 or #177 degree symbol (BartWillems/master, fleaz/master)
if self.tempsMetric != nil {
self.tempsMetric[key].Set(float64(self.Data[key]))
}
@ -113,3 +113,14 @@ func (self *TempWidget) Draw(buf *ui.Buffer) {
)
}
}
func (self *TempWidget) update() {
devices.UpdateTemps(self.Data)
for name, val := range self.Data {
if self.TempScale == Fahrenheit {
self.Data[name] = utils.CelsiusToFahrenheit(val)
} else {
self.Data[name] = val
}
}
}

View File

@ -1,124 +0,0 @@
// +build freebsd
package widgets
import (
"os/exec"
"strconv"
"strings"
"github.com/rai-project/nvidia-smi"
"github.com/xxxserxxx/gotop/utils"
)
var sensorOIDS = map[string]string{
"dev.cpu.0.temperature": "CPU 0 ",
"hw.acpi.thermal.tz0.temperature": "Thermal zone 0",
}
type sensorMeasurement struct {
name string
temperature float64
}
func removeUnusedChars(s string) string {
s1 := strings.Replace(s, "C", "", 1)
s2 := strings.TrimSuffix(s1, "\n")
return s2
}
func refineOutput(output []byte) (float64, error) {
convertedOutput := utils.ConvertLocalizedString(removeUnusedChars(string(output)))
value, err := strconv.ParseFloat(convertedOutput, 64)
if err != nil {
return 0, err
}
return value, nil
}
func collectSysctlSensors() []sensorMeasurement {
var measurements []sensorMeasurement
for k, v := range sensorOIDS {
output, err := exec.Command("sysctl", "-n", k).Output()
if err != nil {
continue
}
value, err := refineOutput(output)
if err != nil {
continue
}
measurements = append(measurements, sensorMeasurement{v, value})
}
return measurements
}
func collectNvidiaSensors() []sensorMeasurement {
var measurements []sensorMeasurement
info, _ := nvidiasmi.New()
if info.HasGPU() {
for i := range info.GPUS {
gpu := info.GPUS[i]
var s sensorMeasurement
s.name = gpu.ProductName + " " + strconv.Itoa(i)
s.temperature, _ = strconv.ParseFloat(strings.ReplaceAll(gpu.GpuTemp, " C", ""), 10)
measurements = append(measurements, s)
}
}
return measurements
}
func collectAMDGPUSensors() []sensorMeasurement {
var measurments []sensorMeasurement
return measurments
}
func collectGPUSensors() []sensorMeasurement {
var measurements []sensorMeasurement
measurements = append(measurements, collectSysctlSensors()...)
measurements = append(measurements, collectNvidiaSensors()...)
measurements = append(measurements, collectAMDGPUSensors()...)
return measurements
}
func collectSensors() []sensorMeasurement {
var measurements []sensorMeasurement
for k, v := range sensorOIDS {
output, err := exec.Command("sysctl", "-n", k).Output()
if err != nil {
continue
}
value, err := refineOutput(output)
if err != nil {
continue
}
measurements = append(measurements, sensorMeasurement{v, value})
}
measurements = append(measurements, collectGPUSensors()...)
return measurements
}
func (self *TempWidget) update() {
sensors := collectSensors()
for _, sensor := range sensors {
switch self.TempScale {
case Fahrenheit:
self.Data[sensor.name] = utils.CelsiusToFahrenheit(int(sensor.temperature))
case Celsius:
self.Data[sensor.name] = int(sensor.temperature)
}
}
}

View File

@ -1,29 +0,0 @@
// +build windows
package widgets
import (
"log"
psHost "github.com/shirou/gopsutil/host"
"github.com/xxxserxxx/gotop/utils"
)
func (self *TempWidget) update() {
sensors, err := psHost.SensorsTemperatures()
if err != nil {
log.Printf("failed to get sensors from gopsutil: %v", err)
return
}
for _, sensor := range sensors {
if sensor.Temperature != 0 {
switch self.TempScale {
case Fahrenheit:
self.Data[sensor.SensorKey] = utils.CelsiusToFahrenheit(int(sensor.Temperature))
case Celsius:
self.Data[sensor.SensorKey] = int(sensor.Temperature)
}
}
}
}