diff --git a/container.go b/container.go new file mode 100644 index 0000000..27dd3f9 --- /dev/null +++ b/container.go @@ -0,0 +1,30 @@ +package main + +import ( + ui "github.com/gizak/termui" +) + +type Container struct { + cid *ui.Par + cpu *ui.Gauge + memory *ui.Gauge +} + +func (c *Container) UpdateCPU(n int) { + c.cpu.BarColor = colorScale(n) + c.cpu.Percent = n +} + +func (c *Container) UpdateMem(n int) { + c.memory.Percent = n +} + +func colorScale(n int) ui.Attribute { + if n > 70 { + return ui.ColorRed + } + if n > 30 { + return ui.ColorYellow + } + return ui.ColorGreen +} diff --git a/grid.go b/grid.go new file mode 100644 index 0000000..74e4d5d --- /dev/null +++ b/grid.go @@ -0,0 +1,150 @@ +package main + +import ( + "sort" + + ui "github.com/gizak/termui" +) + +type Grid struct { + containers map[string]*Container +} + +func (g *Grid) AddContainer(id string) { + cid := ui.NewPar(id) + cid.Border = false + cid.Height = 2 + cid.Width = 10 + cid.TextFgColor = ui.ColorWhite + g.containers[id] = &Container{cid, mkGauge(), mkGauge()} +} + +// Return sorted list of active container IDs +func (g *Grid) CIDs() []string { + var ids []string + for id, _ := range g.containers { + ids = append(ids, id) + } + sort.Strings(ids) + return ids +} + +func (g *Grid) Rows() (rows []*ui.Row) { + for _, cid := range g.CIDs() { + c := g.containers[cid] + rows = append(rows, ui.NewRow( + ui.NewCol(1, 0, c.cid), + ui.NewCol(2, 0, c.cpu), + ui.NewCol(2, 0, c.memory), + )) + } + return rows +} + +func mkGauge() *ui.Gauge { + g := ui.NewGauge() + g.Height = 1 + g.Border = false + g.Percent = 5 + g.PaddingBottom = 0 + g.BarColor = ui.ColorGreen + return g +} + +func header() *ui.Row { + //cid + c1 := ui.NewPar(" CID") + c1.Border = false + c1.Height = 2 + c1.Width = 10 + c1.TextFgColor = ui.ColorWhite + + //cpu + c2 := ui.NewPar(" CPU") + c2.Border = false + c2.Height = 2 + c2.Width = 10 + c2.TextFgColor = ui.ColorWhite + + //mem + c3 := ui.NewPar(" MEM") + c3.Border = false + c3.Height = 2 + c3.Width = 10 + c3.TextFgColor = ui.ColorWhite + + //misc + c4 := ui.NewPar(" MISC") + c4.Border = false + c4.Height = 2 + c4.Width = 10 + c4.TextFgColor = ui.ColorWhite + return ui.NewRow( + ui.NewCol(1, 0, c1), + ui.NewCol(2, 0, c2), + ui.NewCol(2, 0, c3), + ui.NewCol(2, 0, c4), + ) +} + +func NewGrid() { + if err := ui.Init(); err != nil { + panic(err) + } + defer ui.Close() + + g := &Grid{make(map[string]*Container)} + for _, id := range []string{" 12345", " 56789", " 00001"} { + g.AddContainer(id) + } + + par := ui.NewPar("<> This row has 3 columns\n<- Widgets can be stacked up like left side\n<- Stacked widgets are treated as a single widget") + par.Height = 5 + par.BorderLabel = "Demonstration" + + // build layout + ui.Body.AddRows( + header(), + ) + + for _, row := range g.Rows() { + ui.Body.AddRows(row) + } + + // calculate layout + ui.Body.Align() + + ui.Render(ui.Body) + + ui.Handle("/sys/kbd/q", func(ui.Event) { + ui.StopLoop() + }) + ui.Handle("/timer/1s", func(e ui.Event) { + t := e.Data.(ui.EvtTimer) + i := t.Count + if i > 103 { + ui.StopLoop() + return + } + + for _, c := range g.containers { + c.UpdateCPU((c.cpu.Percent + 5) % 100) + c.UpdateMem((c.memory.Percent + 12) % 100) + } + + ui.Render(ui.Body) + }) + + ui.Handle("/sys/wnd/resize", func(e ui.Event) { + ui.Body.Width = ui.TermWidth() + ui.Body.Align() + ui.Clear() + ui.Render(ui.Body) + }) + + ui.Loop() +} + +func main() { + NewGrid() +} diff --git a/main.go b/main.go deleted file mode 100644 index dadd084..0000000 --- a/main.go +++ /dev/null @@ -1,49 +0,0 @@ -package main - -import ( - "fmt" - "os" - - "github.com/fsouza/go-dockerclient" -) - -type DTop struct { - client *docker.Client - stats chan *docker.Stats -} - -func (dt *DTop) output() { - for s := range dt.stats { - fmt.Println(s) - } -} - -func (dt *DTop) collect(containerID string) { - done := make(chan bool) - - fmt.Sprintf("starting collector for container: %s\n", containerID) - opts := docker.StatsOptions{ - ID: containerID, - Stats: dt.stats, - Stream: true, - Done: done, - } - dt.client.Stats(opts) - fmt.Sprintf("stopping collector for container: %s\n", containerID) -} - -func main() { - if len(os.Args) < 2 { - fmt.Println("no container provided") - os.Exit(1) - } - - client, err := docker.NewClient("tcp://127.0.0.1:4243") - if err != nil { - panic(err) - } - - d := &DTop{client, make(chan *docker.Stats)} - go d.collect(os.Args[1]) - d.output() -}