mirror of
https://github.com/bcicen/ctop.git
synced 2025-11-12 22:25:40 +01:00
refactor compact widgets into subpackage
This commit is contained in:
20
container.go
20
container.go
@@ -1,6 +1,9 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/bcicen/ctop/widgets"
|
||||||
"github.com/fsouza/go-dockerclient"
|
"github.com/fsouza/go-dockerclient"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -9,10 +12,23 @@ type Container struct {
|
|||||||
name string
|
name string
|
||||||
done chan bool
|
done chan bool
|
||||||
stats chan *docker.Stats
|
stats chan *docker.Stats
|
||||||
widgets *Widgets
|
widgets *widgets.Compact
|
||||||
reader *StatReader
|
reader *StatReader
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewContainer(c docker.APIContainers) *Container {
|
||||||
|
id := c.ID[:12]
|
||||||
|
name := strings.Replace(c.Names[0], "/", "", 1) // use primary container name
|
||||||
|
return &Container{
|
||||||
|
id: id,
|
||||||
|
name: name,
|
||||||
|
done: make(chan bool),
|
||||||
|
stats: make(chan *docker.Stats),
|
||||||
|
widgets: widgets.NewCompact(id, name),
|
||||||
|
reader: &StatReader{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Container) Collect(client *docker.Client) {
|
func (c *Container) Collect(client *docker.Client) {
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
@@ -28,7 +44,7 @@ func (c *Container) Collect(client *docker.Client) {
|
|||||||
go func() {
|
go func() {
|
||||||
for s := range c.stats {
|
for s := range c.stats {
|
||||||
c.reader.Read(s)
|
c.reader.Read(s)
|
||||||
c.widgets.cpu.Set(c.reader.CPUUtil)
|
c.widgets.SetCPU(c.reader.CPUUtil)
|
||||||
c.widgets.SetMem(c.reader.MemUsage, c.reader.MemLimit)
|
c.widgets.SetMem(c.reader.MemUsage, c.reader.MemLimit)
|
||||||
c.widgets.SetNet(c.reader.NetRx, c.reader.NetTx)
|
c.widgets.SetNet(c.reader.NetRx, c.reader.NetTx)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/fsouza/go-dockerclient"
|
"github.com/fsouza/go-dockerclient"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -35,6 +33,7 @@ type ContainerMap struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cm *ContainerMap) Refresh() {
|
func (cm *ContainerMap) Refresh() {
|
||||||
|
var id string
|
||||||
opts := docker.ListContainersOptions{
|
opts := docker.ListContainersOptions{
|
||||||
Filters: filters,
|
Filters: filters,
|
||||||
}
|
}
|
||||||
@@ -43,8 +42,10 @@ func (cm *ContainerMap) Refresh() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
for _, c := range containers {
|
for _, c := range containers {
|
||||||
if _, ok := cm.containers[c.ID[:12]]; ok == false {
|
id = c.ID[:12]
|
||||||
cm.Add(c)
|
if _, ok := cm.containers[id]; ok == false {
|
||||||
|
cm.containers[id] = NewContainer(c)
|
||||||
|
cm.containers[id].Collect(cm.client)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,20 +55,6 @@ func (cm *ContainerMap) Len() uint {
|
|||||||
return uint(len(cm.containers))
|
return uint(len(cm.containers))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cm *ContainerMap) Add(c docker.APIContainers) {
|
|
||||||
id := c.ID[:12]
|
|
||||||
name := strings.Replace(c.Names[0], "/", "", 1) // use primary container name
|
|
||||||
cm.containers[id] = &Container{
|
|
||||||
id: id,
|
|
||||||
name: name,
|
|
||||||
done: make(chan bool),
|
|
||||||
stats: make(chan *docker.Stats),
|
|
||||||
widgets: NewWidgets(id, name),
|
|
||||||
reader: &StatReader{},
|
|
||||||
}
|
|
||||||
cm.containers[id].Collect(cm.client)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a single container, by ID
|
// Get a single container, by ID
|
||||||
func (cm *ContainerMap) Get(id string) *Container {
|
func (cm *ContainerMap) Get(id string) *Container {
|
||||||
return cm.containers[id]
|
return cm.containers[id]
|
||||||
|
|||||||
10
grid.go
10
grid.go
@@ -54,11 +54,11 @@ func (g *Grid) cursorDown() {
|
|||||||
func (g *Grid) redrawCursor() {
|
func (g *Grid) redrawCursor() {
|
||||||
for _, c := range g.containers {
|
for _, c := range g.containers {
|
||||||
if c.id == g.cursorID {
|
if c.id == g.cursorID {
|
||||||
c.widgets.name.TextFgColor = ui.ColorDefault
|
c.widgets.Name.TextFgColor = ui.ColorDefault
|
||||||
c.widgets.name.TextBgColor = ui.ColorWhite
|
c.widgets.Name.TextBgColor = ui.ColorWhite
|
||||||
} else {
|
} else {
|
||||||
c.widgets.name.TextFgColor = ui.ColorWhite
|
c.widgets.Name.TextFgColor = ui.ColorWhite
|
||||||
c.widgets.name.TextBgColor = ui.ColorDefault
|
c.widgets.Name.TextBgColor = ui.ColorDefault
|
||||||
}
|
}
|
||||||
ui.Render(ui.Body)
|
ui.Render(ui.Body)
|
||||||
}
|
}
|
||||||
@@ -71,7 +71,7 @@ func (g *Grid) redrawRows() {
|
|||||||
// build layout
|
// build layout
|
||||||
ui.Body.AddRows(header())
|
ui.Body.AddRows(header())
|
||||||
for _, c := range g.containers {
|
for _, c := range g.containers {
|
||||||
ui.Body.AddRows(c.widgets.MakeRow())
|
ui.Body.AddRows(c.widgets.Row())
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.Body.Align()
|
ui.Body.Align()
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type StatReader struct {
|
type StatReader struct {
|
||||||
CPUUtil int
|
CPUUtil float64
|
||||||
NetTx int64
|
NetTx int64
|
||||||
NetRx int64
|
NetRx int64
|
||||||
MemUsage int64
|
MemUsage int64
|
||||||
@@ -28,7 +28,7 @@ func (s *StatReader) ReadCPU(stats *docker.Stats) {
|
|||||||
|
|
||||||
cpudiff := total - s.lastCpu
|
cpudiff := total - s.lastCpu
|
||||||
syscpudiff := system - s.lastSysCpu
|
syscpudiff := system - s.lastSysCpu
|
||||||
s.CPUUtil = round((cpudiff / syscpudiff * 100) * ncpus)
|
s.CPUUtil = (cpudiff / syscpudiff * 100) * ncpus
|
||||||
s.lastCpu = total
|
s.lastCpu = total
|
||||||
s.lastSysCpu = system
|
s.lastSysCpu = system
|
||||||
}
|
}
|
||||||
|
|||||||
33
util.go
33
util.go
@@ -1,33 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"math"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
kb = 1024
|
|
||||||
mb = kb * 1024
|
|
||||||
gb = mb * 1024
|
|
||||||
)
|
|
||||||
|
|
||||||
func byteFormat(n int64) string {
|
|
||||||
if n < kb {
|
|
||||||
return fmt.Sprintf("%sB", strconv.FormatInt(n, 10))
|
|
||||||
}
|
|
||||||
if n < mb {
|
|
||||||
n = n / kb
|
|
||||||
return fmt.Sprintf("%sK", strconv.FormatInt(n, 10))
|
|
||||||
}
|
|
||||||
if n < gb {
|
|
||||||
n = n / mb
|
|
||||||
return fmt.Sprintf("%sM", strconv.FormatInt(n, 10))
|
|
||||||
}
|
|
||||||
n = n / gb
|
|
||||||
return fmt.Sprintf("%sG", strconv.FormatInt(n, 10))
|
|
||||||
}
|
|
||||||
|
|
||||||
func round(num float64) int {
|
|
||||||
return int(num + math.Copysign(0.5, num))
|
|
||||||
}
|
|
||||||
76
widgets.go
76
widgets.go
@@ -1,76 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/bcicen/ctop/widgets"
|
|
||||||
ui "github.com/gizak/termui"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Widgets struct {
|
|
||||||
cid *ui.Par
|
|
||||||
net *ui.Par
|
|
||||||
name *ui.Par
|
|
||||||
cpu *widgets.CPU
|
|
||||||
memory *ui.Gauge
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Widgets) MakeRow() *ui.Row {
|
|
||||||
return ui.NewRow(
|
|
||||||
ui.NewCol(2, 0, w.name),
|
|
||||||
ui.NewCol(2, 0, w.cid),
|
|
||||||
ui.NewCol(2, 0, w.cpu),
|
|
||||||
ui.NewCol(2, 0, w.memory),
|
|
||||||
ui.NewCol(2, 0, w.net),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Widgets) SetNet(rx int64, tx int64) {
|
|
||||||
w.net.Text = fmt.Sprintf("%s / %s", byteFormat(rx), byteFormat(tx))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Widgets) SetMem(val int64, limit int64) {
|
|
||||||
percent := round((float64(val) / float64(limit)) * 100)
|
|
||||||
w.memory.Label = fmt.Sprintf("%s / %s", byteFormat(val), byteFormat(limit))
|
|
||||||
if percent < 5 {
|
|
||||||
percent = 5
|
|
||||||
w.memory.BarColor = ui.ColorBlack
|
|
||||||
} else {
|
|
||||||
w.memory.BarColor = ui.ColorGreen
|
|
||||||
}
|
|
||||||
w.memory.Percent = percent
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewWidgets(id string, names string) *Widgets {
|
|
||||||
|
|
||||||
cid := ui.NewPar(id)
|
|
||||||
cid.Border = false
|
|
||||||
cid.Height = 1
|
|
||||||
cid.Width = 20
|
|
||||||
cid.TextFgColor = ui.ColorWhite
|
|
||||||
|
|
||||||
name := ui.NewPar(names)
|
|
||||||
name.Border = false
|
|
||||||
name.Height = 1
|
|
||||||
name.Width = 20
|
|
||||||
name.TextFgColor = ui.ColorWhite
|
|
||||||
|
|
||||||
net := ui.NewPar("-")
|
|
||||||
net.Border = false
|
|
||||||
net.Height = 1
|
|
||||||
net.Width = 20
|
|
||||||
net.TextFgColor = ui.ColorWhite
|
|
||||||
|
|
||||||
return &Widgets{cid, net, name, widgets.NewCPU(), mkGauge()}
|
|
||||||
}
|
|
||||||
|
|
||||||
func mkGauge() *ui.Gauge {
|
|
||||||
g := ui.NewGauge()
|
|
||||||
g.Height = 1
|
|
||||||
g.Border = false
|
|
||||||
g.Percent = 0
|
|
||||||
g.PaddingBottom = 0
|
|
||||||
g.BarColor = ui.ColorGreen
|
|
||||||
g.Label = "-"
|
|
||||||
return g
|
|
||||||
}
|
|
||||||
63
widgets/compact.go
Normal file
63
widgets/compact.go
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package widgets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
ui "github.com/gizak/termui"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Compact struct {
|
||||||
|
Cid *ui.Par
|
||||||
|
Net *ui.Par
|
||||||
|
Name *ui.Par
|
||||||
|
Cpu *ui.Gauge
|
||||||
|
Memory *ui.Gauge
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCompact(id string, name string) *Compact {
|
||||||
|
return &Compact{
|
||||||
|
Cid: compactPar(id),
|
||||||
|
Net: compactPar("-"),
|
||||||
|
Name: compactPar(name),
|
||||||
|
Cpu: mkGauge(),
|
||||||
|
Memory: mkGauge(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Compact) Row() *ui.Row {
|
||||||
|
return ui.NewRow(
|
||||||
|
ui.NewCol(2, 0, w.Name),
|
||||||
|
ui.NewCol(2, 0, w.Cid),
|
||||||
|
ui.NewCol(2, 0, w.Cpu),
|
||||||
|
ui.NewCol(2, 0, w.Memory),
|
||||||
|
ui.NewCol(2, 0, w.Net),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Compact) SetCPU(val float64) {
|
||||||
|
intVal := round(val)
|
||||||
|
w.Cpu.BarColor = colorScale(intVal)
|
||||||
|
w.Cpu.Label = fmt.Sprintf("%s%%", strconv.Itoa(intVal))
|
||||||
|
if intVal < 5 {
|
||||||
|
intVal = 5
|
||||||
|
w.Cpu.BarColor = ui.ColorBlack
|
||||||
|
}
|
||||||
|
w.Cpu.Percent = intVal
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Compact) SetNet(rx int64, tx int64) {
|
||||||
|
w.Net.Text = fmt.Sprintf("%s / %s", byteFormat(rx), byteFormat(tx))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Compact) SetMem(val int64, limit int64) {
|
||||||
|
percent := round((float64(val) / float64(limit)) * 100)
|
||||||
|
w.Memory.Label = fmt.Sprintf("%s / %s", byteFormat(val), byteFormat(limit))
|
||||||
|
if percent < 5 {
|
||||||
|
percent = 5
|
||||||
|
w.Memory.BarColor = ui.ColorBlack
|
||||||
|
} else {
|
||||||
|
w.Memory.BarColor = ui.ColorGreen
|
||||||
|
}
|
||||||
|
w.Memory.Percent = percent
|
||||||
|
}
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
package widgets
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
ui "github.com/gizak/termui"
|
|
||||||
)
|
|
||||||
|
|
||||||
type CPU struct {
|
|
||||||
*ui.Gauge
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewCPU() *CPU {
|
|
||||||
return &CPU{mkGauge()}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *CPU) Set(val int) {
|
|
||||||
c.BarColor = colorScale(val)
|
|
||||||
c.Label = fmt.Sprintf("%s%%", strconv.Itoa(val))
|
|
||||||
if val < 5 {
|
|
||||||
val = 5
|
|
||||||
c.BarColor = ui.ColorBlack
|
|
||||||
}
|
|
||||||
c.Percent = val
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,48 @@
|
|||||||
package widgets
|
package widgets
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
ui "github.com/gizak/termui"
|
ui "github.com/gizak/termui"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
kb = 1024
|
||||||
|
mb = kb * 1024
|
||||||
|
gb = mb * 1024
|
||||||
|
)
|
||||||
|
|
||||||
|
func byteFormat(n int64) string {
|
||||||
|
if n < kb {
|
||||||
|
return fmt.Sprintf("%sB", strconv.FormatInt(n, 10))
|
||||||
|
}
|
||||||
|
if n < mb {
|
||||||
|
n = n / kb
|
||||||
|
return fmt.Sprintf("%sK", strconv.FormatInt(n, 10))
|
||||||
|
}
|
||||||
|
if n < gb {
|
||||||
|
n = n / mb
|
||||||
|
return fmt.Sprintf("%sM", strconv.FormatInt(n, 10))
|
||||||
|
}
|
||||||
|
n = n / gb
|
||||||
|
return fmt.Sprintf("%sG", strconv.FormatInt(n, 10))
|
||||||
|
}
|
||||||
|
|
||||||
|
func round(num float64) int {
|
||||||
|
return int(num + math.Copysign(0.5, num))
|
||||||
|
}
|
||||||
|
|
||||||
|
func compactPar(s string) *ui.Par {
|
||||||
|
p := ui.NewPar(s)
|
||||||
|
p.Border = false
|
||||||
|
p.Height = 1
|
||||||
|
p.Width = 20
|
||||||
|
p.TextFgColor = ui.ColorWhite
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
func mkGauge() *ui.Gauge {
|
func mkGauge() *ui.Gauge {
|
||||||
g := ui.NewGauge()
|
g := ui.NewGauge()
|
||||||
g.Height = 1
|
g.Height = 1
|
||||||
|
|||||||
Reference in New Issue
Block a user