mirror of
https://github.com/bcicen/ctop.git
synced 2024-08-30 18:23:19 +00:00
add container state checks, set status icon based on state string
This commit is contained in:
@ -7,6 +7,9 @@ import (
|
|||||||
// Docker collector
|
// Docker collector
|
||||||
type Docker struct {
|
type Docker struct {
|
||||||
Metrics
|
Metrics
|
||||||
|
id string
|
||||||
|
client *api.Client
|
||||||
|
running bool
|
||||||
stream chan Metrics
|
stream chan Metrics
|
||||||
done chan bool
|
done chan bool
|
||||||
lastCpu float64
|
lastCpu float64
|
||||||
@ -14,22 +17,27 @@ type Docker struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewDocker(client *api.Client, id string) *Docker {
|
func NewDocker(client *api.Client, id string) *Docker {
|
||||||
c := &Docker{
|
return &Docker{
|
||||||
Metrics: Metrics{},
|
Metrics: Metrics{},
|
||||||
|
id: id,
|
||||||
|
client: client,
|
||||||
stream: make(chan Metrics),
|
stream: make(chan Metrics),
|
||||||
done: make(chan bool),
|
done: make(chan bool),
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Docker) Start() {
|
||||||
stats := make(chan *api.Stats)
|
stats := make(chan *api.Stats)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
opts := api.StatsOptions{
|
opts := api.StatsOptions{
|
||||||
ID: id,
|
ID: c.id,
|
||||||
Stats: stats,
|
Stats: stats,
|
||||||
Stream: true,
|
Stream: true,
|
||||||
Done: c.done,
|
Done: c.done,
|
||||||
}
|
}
|
||||||
client.Stats(opts)
|
c.client.Stats(opts)
|
||||||
|
c.running = false
|
||||||
}()
|
}()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
@ -42,7 +50,11 @@ func NewDocker(client *api.Client, id string) *Docker {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return c
|
c.running = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Docker) Running() bool {
|
||||||
|
return c.running
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Docker) Stream() chan Metrics {
|
func (c *Docker) Stream() chan Metrics {
|
||||||
|
@ -15,6 +15,8 @@ type Metrics struct {
|
|||||||
|
|
||||||
type Collector interface {
|
type Collector interface {
|
||||||
Stream() chan Metrics
|
Stream() chan Metrics
|
||||||
|
Running() bool
|
||||||
|
Start()
|
||||||
Stop()
|
Stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ func (c *Container) Collapse() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) Collect() {
|
func (c *Container) Collect() {
|
||||||
|
c.collect.Start()
|
||||||
go func() {
|
go func() {
|
||||||
for metrics := range c.collect.Stream() {
|
for metrics := range c.collect.Stream() {
|
||||||
c.metrics = metrics
|
c.metrics = metrics
|
||||||
|
@ -11,10 +11,6 @@ import (
|
|||||||
"github.com/fsouza/go-dockerclient"
|
"github.com/fsouza/go-dockerclient"
|
||||||
)
|
)
|
||||||
|
|
||||||
var filters = map[string][]string{
|
|
||||||
"status": []string{"running"},
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewContainerMap() *ContainerMap {
|
func NewContainerMap() *ContainerMap {
|
||||||
// init docker client
|
// init docker client
|
||||||
client, err := docker.NewClient(GlobalConfig["dockerHost"])
|
client, err := docker.NewClient(GlobalConfig["dockerHost"])
|
||||||
@ -37,17 +33,17 @@ type ContainerMap struct {
|
|||||||
func (cm *ContainerMap) Refresh() {
|
func (cm *ContainerMap) Refresh() {
|
||||||
var id, name string
|
var id, name string
|
||||||
|
|
||||||
opts := docker.ListContainersOptions{
|
opts := docker.ListContainersOptions{All: true}
|
||||||
Filters: filters,
|
|
||||||
}
|
|
||||||
containers, err := cm.client.ListContainers(opts)
|
containers, err := cm.client.ListContainers(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// add new containers
|
// add new containers
|
||||||
|
states := make(map[string]string)
|
||||||
for _, c := range containers {
|
for _, c := range containers {
|
||||||
id = c.ID[:12]
|
id = c.ID[:12]
|
||||||
|
states[id] = c.State
|
||||||
if _, ok := cm.containers[id]; ok == false {
|
if _, ok := cm.containers[id]; ok == false {
|
||||||
name = strings.Replace(c.Names[0], "/", "", 1) // use primary container name
|
name = strings.Replace(c.Names[0], "/", "", 1) // use primary container name
|
||||||
cm.containers[id] = &Container{
|
cm.containers[id] = &Container{
|
||||||
@ -56,19 +52,25 @@ func (cm *ContainerMap) Refresh() {
|
|||||||
collect: collector.NewDocker(cm.client, id),
|
collect: collector.NewDocker(cm.client, id),
|
||||||
widgets: widgets.NewCompact(id, name),
|
widgets: widgets.NewCompact(id, name),
|
||||||
}
|
}
|
||||||
cm.containers[id].Collect()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var removeIDs []string
|
||||||
|
for id, c := range cm.containers {
|
||||||
|
// mark stale internal containers
|
||||||
|
if _, ok := states[id]; ok == false {
|
||||||
|
removeIDs = append(removeIDs, id)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// start collector if necessary
|
||||||
|
if states[id] == "running" && !c.collect.Running() {
|
||||||
|
c.Collect()
|
||||||
|
}
|
||||||
|
c.widgets.SetStatus(states[id])
|
||||||
|
}
|
||||||
|
|
||||||
// remove dead containers
|
// remove dead containers
|
||||||
var removeIDs []string
|
|
||||||
for id, c := range cm.containers {
|
|
||||||
if c.dead {
|
|
||||||
removeIDs = append(removeIDs, id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cm.Del(removeIDs...)
|
cm.Del(removeIDs...)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kill a container by ID
|
// Kill a container by ID
|
||||||
|
2
grid.go
2
grid.go
@ -135,7 +135,7 @@ func Display(g *Grid) bool {
|
|||||||
// calculate layout
|
// calculate layout
|
||||||
ui.Body.Align()
|
ui.Body.Align()
|
||||||
g.redrawCursor()
|
g.redrawCursor()
|
||||||
ui.Render(ui.Body)
|
g.redrawRows()
|
||||||
|
|
||||||
ui.Handle("/sys/kbd/<up>", func(ui.Event) {
|
ui.Handle("/sys/kbd/<up>", func(ui.Event) {
|
||||||
g.cursorUp()
|
g.cursorUp()
|
||||||
|
@ -8,7 +8,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
mark = '\u25C9'
|
mark = '\u25C9'
|
||||||
|
pause = '\u25AE'
|
||||||
)
|
)
|
||||||
|
|
||||||
type ContainerWidgets interface {
|
type ContainerWidgets interface {
|
||||||
@ -16,7 +17,7 @@ type ContainerWidgets interface {
|
|||||||
Render()
|
Render()
|
||||||
Highlight()
|
Highlight()
|
||||||
UnHighlight()
|
UnHighlight()
|
||||||
SetStatus(int)
|
SetStatus(string)
|
||||||
SetCPU(int)
|
SetCPU(int)
|
||||||
SetNet(int64, int64)
|
SetNet(int64, int64)
|
||||||
SetMem(int64, int64, int)
|
SetMem(int64, int64, int)
|
||||||
@ -33,7 +34,7 @@ type Compact struct {
|
|||||||
|
|
||||||
func NewCompact(id string, name string) *Compact {
|
func NewCompact(id string, name string) *Compact {
|
||||||
return &Compact{
|
return &Compact{
|
||||||
Status: slimPar(string(mark)),
|
Status: slimPar(""),
|
||||||
Cid: slimPar(id),
|
Cid: slimPar(id),
|
||||||
Net: slimPar("-"),
|
Net: slimPar("-"),
|
||||||
Name: slimPar(name),
|
Name: slimPar(name),
|
||||||
@ -67,11 +68,19 @@ func (w *Compact) UnHighlight() {
|
|||||||
w.Name.TextBgColor = ui.ColorDefault
|
w.Name.TextBgColor = ui.ColorDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Compact) SetStatus(val int) {
|
func (w *Compact) SetStatus(val string) {
|
||||||
switch val {
|
switch val {
|
||||||
case 0:
|
case "running":
|
||||||
|
w.Status.Text = string(mark)
|
||||||
w.Status.TextFgColor = ui.ColorGreen
|
w.Status.TextFgColor = ui.ColorGreen
|
||||||
|
case "exited":
|
||||||
|
w.Status.Text = string(mark)
|
||||||
|
w.Status.TextFgColor = ui.ColorRed
|
||||||
|
case "paused":
|
||||||
|
w.Status.Text = fmt.Sprintf("%s%s", string(pause), string(pause))
|
||||||
|
w.Status.TextFgColor = ui.ColorDefault
|
||||||
default:
|
default:
|
||||||
|
w.Status.Text = string(mark)
|
||||||
w.Status.TextFgColor = ui.ColorRed
|
w.Status.TextFgColor = ui.ColorRed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -109,6 +118,7 @@ func centerParText(p *ui.Par) {
|
|||||||
for i, ch := range p.Text {
|
for i, ch := range p.Text {
|
||||||
if string(ch) != " " {
|
if string(ch) != " " {
|
||||||
text = p.Text[i:]
|
text = p.Text[i:]
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ func (w *Expanded) Highlight() {
|
|||||||
func (w *Expanded) UnHighlight() {
|
func (w *Expanded) UnHighlight() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Expanded) SetStatus(val int) {
|
func (w *Expanded) SetStatus(val string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Expanded) SetCPU(val int) {
|
func (w *Expanded) SetCPU(val int) {
|
||||||
|
Reference in New Issue
Block a user