Add ttop example
This commit is contained in:
parent
9ec1539ccc
commit
e62b592964
@ -3,33 +3,35 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"bufio"
|
"bufio"
|
||||||
"os"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"errors"
|
|
||||||
"runtime"
|
"github.com/gizak/termui"
|
||||||
"github.com/marigs/termui"
|
"github.com/gizak/termui/extra"
|
||||||
)
|
)
|
||||||
|
|
||||||
const statFilePath = "/proc/stat"
|
const statFilePath = "/proc/stat"
|
||||||
const meminfoFilePath = "/proc/meminfo"
|
const meminfoFilePath = "/proc/meminfo"
|
||||||
|
|
||||||
type CpuStat struct {
|
type CpuStat struct {
|
||||||
user float32
|
user float32
|
||||||
nice float32
|
nice float32
|
||||||
system float32
|
system float32
|
||||||
idle float32
|
idle float32
|
||||||
}
|
}
|
||||||
|
|
||||||
type CpusStats struct {
|
type CpusStats struct {
|
||||||
stat map[string]CpuStat
|
stat map[string]CpuStat
|
||||||
proc map[string]CpuStat
|
proc map[string]CpuStat
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCpusStats(s map[string]CpuStat) *CpusStats {
|
func NewCpusStats(s map[string]CpuStat) *CpusStats {
|
||||||
@ -45,17 +47,17 @@ func (cs *CpusStats) String() (ret string) {
|
|||||||
|
|
||||||
func subCpuStat(m CpuStat, s CpuStat) CpuStat {
|
func subCpuStat(m CpuStat, s CpuStat) CpuStat {
|
||||||
return CpuStat{user: m.user - s.user,
|
return CpuStat{user: m.user - s.user,
|
||||||
nice: m.nice - s.nice,
|
nice: m.nice - s.nice,
|
||||||
system: m.system - s.system,
|
system: m.system - s.system,
|
||||||
idle: m.idle - s.idle}
|
idle: m.idle - s.idle}
|
||||||
}
|
}
|
||||||
|
|
||||||
func procCpuStat(c CpuStat) CpuStat {
|
func procCpuStat(c CpuStat) CpuStat {
|
||||||
sum := c.user + c.nice + c.system + c.idle
|
sum := c.user + c.nice + c.system + c.idle
|
||||||
return CpuStat{user: c.user/sum*100,
|
return CpuStat{user: c.user / sum * 100,
|
||||||
nice: c.nice/sum*100,
|
nice: c.nice / sum * 100,
|
||||||
system: c.system/sum*100,
|
system: c.system / sum * 100,
|
||||||
idle: c.idle/sum*100}
|
idle: c.idle / sum * 100}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *CpusStats) tick(ns map[string]CpuStat) {
|
func (cs *CpusStats) tick(ns map[string]CpuStat) {
|
||||||
@ -80,7 +82,7 @@ func (eip *errIntParser) parse(s string) (ret int64) {
|
|||||||
|
|
||||||
type LineProcessor interface {
|
type LineProcessor interface {
|
||||||
process(string) error
|
process(string) error
|
||||||
finalize() interface {}
|
finalize() interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
type CpuLineProcessor struct {
|
type CpuLineProcessor struct {
|
||||||
@ -98,9 +100,9 @@ func (clp *CpuLineProcessor) process(line string) (err error) {
|
|||||||
}
|
}
|
||||||
parser := errIntParser{}
|
parser := errIntParser{}
|
||||||
cs := CpuStat{user: float32(parser.parse(tab[1])),
|
cs := CpuStat{user: float32(parser.parse(tab[1])),
|
||||||
nice: float32(parser.parse(tab[2])),
|
nice: float32(parser.parse(tab[2])),
|
||||||
system: float32(parser.parse(tab[3])),
|
system: float32(parser.parse(tab[3])),
|
||||||
idle: float32(parser.parse(tab[4]))}
|
idle: float32(parser.parse(tab[4]))}
|
||||||
clp.m[tab[0]] = cs
|
clp.m[tab[0]] = cs
|
||||||
err = parser.err
|
err = parser.err
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -110,13 +112,13 @@ func (clp *CpuLineProcessor) process(line string) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (clp *CpuLineProcessor) finalize() interface {} {
|
func (clp *CpuLineProcessor) finalize() interface{} {
|
||||||
return clp.m
|
return clp.m
|
||||||
}
|
}
|
||||||
|
|
||||||
type MemStat struct {
|
type MemStat struct {
|
||||||
total int64
|
total int64
|
||||||
free int64
|
free int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ms MemStat) String() (ret string) {
|
func (ms MemStat) String() (ret string) {
|
||||||
@ -149,11 +151,11 @@ func (ms *MemStat) process(line string) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ms *MemStat) finalize() interface {} {
|
func (ms *MemStat) finalize() interface{} {
|
||||||
return *ms
|
return *ms
|
||||||
}
|
}
|
||||||
|
|
||||||
func processFileLines(filePath string, lp LineProcessor) (ret interface {}, err error) {
|
func processFileLines(filePath string, lp LineProcessor) (ret interface{}, err error) {
|
||||||
var statFile *os.File
|
var statFile *os.File
|
||||||
statFile, err = os.Open(filePath)
|
statFile, err = os.Open(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -184,19 +186,19 @@ func processFileLines(filePath string, lp LineProcessor) (ret interface {}, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getCpusStatsMap() (m map[string]CpuStat, err error) {
|
func getCpusStatsMap() (m map[string]CpuStat, err error) {
|
||||||
var aux interface {}
|
var aux interface{}
|
||||||
aux, err = processFileLines(statFilePath, &CpuLineProcessor{m: make(map[string]CpuStat)})
|
aux, err = processFileLines(statFilePath, &CpuLineProcessor{m: make(map[string]CpuStat)})
|
||||||
return aux.(map[string]CpuStat), err
|
return aux.(map[string]CpuStat), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func getMemStats() (ms MemStat, err error) {
|
func getMemStats() (ms MemStat, err error) {
|
||||||
var aux interface {}
|
var aux interface{}
|
||||||
aux, err = processFileLines(meminfoFilePath, &MemStat{})
|
aux, err = processFileLines(meminfoFilePath, &MemStat{})
|
||||||
return aux.(MemStat), err
|
return aux.(MemStat), err
|
||||||
}
|
}
|
||||||
|
|
||||||
type CpuTabElems struct {
|
type CpuTabElems struct {
|
||||||
GMap map[string]*termui.Gauge
|
GMap map[string]*termui.Gauge
|
||||||
LChart *termui.LineChart
|
LChart *termui.LineChart
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,17 +210,16 @@ func NewCpuTabElems(width int) *CpuTabElems {
|
|||||||
lc.Mode = "dot"
|
lc.Mode = "dot"
|
||||||
lc.Border.Label = "CPU"
|
lc.Border.Label = "CPU"
|
||||||
return &CpuTabElems{GMap: make(map[string]*termui.Gauge),
|
return &CpuTabElems{GMap: make(map[string]*termui.Gauge),
|
||||||
LChart: lc}
|
LChart: lc}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (cte *CpuTabElems) AddGauge(key string, Y int, width int) *termui.Gauge {
|
func (cte *CpuTabElems) AddGauge(key string, Y int, width int) *termui.Gauge {
|
||||||
cte.GMap[key] = termui.NewGauge()
|
cte.GMap[key] = termui.NewGauge()
|
||||||
cte.GMap[key].Width = width
|
cte.GMap[key].Width = width
|
||||||
cte.GMap[key].Height = 3
|
cte.GMap[key].Height = 3
|
||||||
cte.GMap[key].Y = Y
|
cte.GMap[key].Y = Y
|
||||||
cte.GMap[key].Border.Label = key
|
cte.GMap[key].Border.Label = key
|
||||||
cte.GMap[key].Percent = 0//int(val.user + val.nice + val.system)
|
cte.GMap[key].Percent = 0 //int(val.user + val.nice + val.system)
|
||||||
return cte.GMap[key]
|
return cte.GMap[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,7 +236,7 @@ func (cte *CpuTabElems) Update(cs CpusStats) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type MemTabElems struct {
|
type MemTabElems struct {
|
||||||
Gauge *termui.Gauge
|
Gauge *termui.Gauge
|
||||||
SLines *termui.Sparklines
|
SLines *termui.Sparklines
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,7 +264,7 @@ func (mte *MemTabElems) Update(ms MemStat) {
|
|||||||
copy(mte.SLines.Lines[0].Data[1:], mte.SLines.Lines[0].Data[0:])
|
copy(mte.SLines.Lines[0].Data[1:], mte.SLines.Lines[0].Data[0:])
|
||||||
mte.SLines.Lines[0].Data[0] = used
|
mte.SLines.Lines[0].Data[0] = used
|
||||||
if len(mte.SLines.Lines[0].Data) > mte.SLines.Width-2 {
|
if len(mte.SLines.Lines[0].Data) > mte.SLines.Width-2 {
|
||||||
mte.SLines.Lines[0].Data = mte.SLines.Lines[0].Data[0:mte.SLines.Width-2]
|
mte.SLines.Lines[0].Data = mte.SLines.Lines[0].Data[0 : mte.SLines.Width-2]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,11 +272,11 @@ func main() {
|
|||||||
if runtime.GOOS != "linux" {
|
if runtime.GOOS != "linux" {
|
||||||
panic("Currently works only on Linux")
|
panic("Currently works only on Linux")
|
||||||
}
|
}
|
||||||
err := termui.Init()
|
err := termui.Init()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
defer termui.Close()
|
defer termui.Close()
|
||||||
|
|
||||||
termWidth := 70
|
termWidth := 70
|
||||||
|
|
||||||
@ -287,13 +288,13 @@ func main() {
|
|||||||
header.HasBorder = false
|
header.HasBorder = false
|
||||||
header.TextBgColor = termui.ColorBlue
|
header.TextBgColor = termui.ColorBlue
|
||||||
|
|
||||||
tabCpu := termui.NewTab("CPU")
|
tabCpu := extra.NewTab("CPU")
|
||||||
tabMem := termui.NewTab("MEM")
|
tabMem := extra.NewTab("MEM")
|
||||||
|
|
||||||
tabpane := termui.NewTabpane()
|
tabpane := extra.NewTabpane()
|
||||||
tabpane.Y = 1
|
tabpane.Y = 1
|
||||||
tabpane.Width = 30
|
tabpane.Width = 30
|
||||||
tabpane.HasBorder = false
|
tabpane.HasBorder = false
|
||||||
|
|
||||||
cs, errcs := getCpusStatsMap()
|
cs, errcs := getCpusStatsMap()
|
||||||
cpusStats := NewCpusStats(cs)
|
cpusStats := NewCpusStats(cs)
|
||||||
@ -327,9 +328,9 @@ func main() {
|
|||||||
tabMem.AddBlocks(memTabElems.Gauge)
|
tabMem.AddBlocks(memTabElems.Gauge)
|
||||||
tabMem.AddBlocks(memTabElems.SLines)
|
tabMem.AddBlocks(memTabElems.SLines)
|
||||||
|
|
||||||
tabpane.SetTabs(*tabCpu, *tabMem)
|
tabpane.SetTabs(*tabCpu, *tabMem)
|
||||||
|
|
||||||
termui.Render(header, tabpane)
|
termui.Render(header, tabpane)
|
||||||
|
|
||||||
evt := termui.EventCh()
|
evt := termui.EventCh()
|
||||||
for {
|
for {
|
||||||
@ -365,4 +366,3 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user