Add ttop example

This commit is contained in:
gizak 2015-10-21 11:11:08 -04:00
parent 9ec1539ccc
commit e62b592964

View File

@ -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() {
} }
} }
} }