diff --git a/container.go b/container.go index 27dd3f9..bcfc152 100644 --- a/container.go +++ b/container.go @@ -1,22 +1,77 @@ package main import ( + "fmt" + "math" + + "github.com/fsouza/go-dockerclient" ui "github.com/gizak/termui" ) -type Container struct { +type Widgets 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 NewWidgets(id string) *Widgets { + cid := ui.NewPar(id) + cid.Border = false + cid.Height = 2 + cid.Width = 10 + cid.TextFgColor = ui.ColorWhite + return &Widgets{cid, mkGauge(), mkGauge()} } -func (c *Container) UpdateMem(n int) { - c.memory.Percent = n +type Container struct { + id string + widgets *Widgets + stats chan *docker.Stats + done chan bool +} + +func NewContainer(cid string) *Container { + return &Container{ + id: cid, + widgets: NewWidgets(cid), + stats: make(chan *docker.Stats), + done: make(chan bool), + } +} + +func (c *Container) Collect(client *docker.Client) { + + go func() { + fmt.Sprintf("starting collector for container: %s\n", c.id) + opts := docker.StatsOptions{ + ID: c.id, + Stats: c.stats, + Stream: true, + Done: c.done, + } + client.Stats(opts) + fmt.Sprintf("stopping collector for container: %s\n", c.id) + }() + + go func() { + for s := range c.stats { + c.UpdateMem(s.MemoryStats.Usage, s.MemoryStats.Limit) + } + }() + +} + +func (c *Container) UpdateCPU(n int) { + c.widgets.cpu.BarColor = colorScale(n) + c.widgets.cpu.Percent = n +} + +func (c *Container) UpdateMem(cur uint64, limit uint64) { + c.widgets.memory.Percent = round((float64(cur) / float64(limit)) * 100) +} + +func round(num float64) int { + return int(num + math.Copysign(0.5, num)) } func colorScale(n int) ui.Attribute { diff --git a/grid.go b/grid.go index 74e4d5d..c0ce5b0 100644 --- a/grid.go +++ b/grid.go @@ -11,12 +11,7 @@ type Grid struct { } 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()} + g.containers[id] = NewContainer(id) } // Return sorted list of active container IDs @@ -33,9 +28,9 @@ 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), + ui.NewCol(1, 0, c.widgets.cid), + ui.NewCol(2, 0, c.widgets.cpu), + ui.NewCol(2, 0, c.widgets.memory), )) } return rows @@ -87,25 +82,14 @@ func header() *ui.Row { ) } -func NewGrid() { +func Display(g *Grid) { 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(), - ) + ui.Body.AddRows(header()) for _, row := range g.Rows() { ui.Body.AddRows(row) @@ -120,17 +104,12 @@ func NewGrid() { 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) - } + // t := e.Data.(ui.EvtTimer) + // i := t.Count + // if i > 103 { + // ui.StopLoop() + // return + // } ui.Render(ui.Body) }) @@ -144,7 +123,3 @@ func NewGrid() { ui.Loop() } - -func main() { - NewGrid() -} diff --git a/main.go b/main.go new file mode 100644 index 0000000..e0b79d1 --- /dev/null +++ b/main.go @@ -0,0 +1,30 @@ +package main + +import ( + "fmt" + "os" + + "github.com/fsouza/go-dockerclient" +) + +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) + } + + g := &Grid{make(map[string]*Container)} + g.AddContainer(os.Args[1]) + + for _, c := range g.containers { + c.Collect(client) + } + + Display(g) + +}