mirror of
https://gitea.elkins.co/Networking/ccl.git
synced 2025-03-09 12:41:40 -05:00
ls enhancement: show running stats
Mainly for zabbix, but why not. Format of both json and text output of ls has changed.
This commit is contained in:
parent
13e35e9c4d
commit
139ea8707c
58
cmd/ls.go
58
cmd/ls.go
@ -48,6 +48,20 @@ type lsContainerObj struct {
|
||||
Running bool `json:"running"`
|
||||
}
|
||||
|
||||
type lsContainerStatsObj struct {
|
||||
CPU float64 `json:"cpu_usage_pct"`
|
||||
CPUNano uint64 `json:"cpu_nano"`
|
||||
MemUsage uint64 `json:"mem_usage_bytes"`
|
||||
MemLimit uint64 `json:"mem_limit_bytes"`
|
||||
MemPerc float64 `json:"mem_usage_pct"`
|
||||
NetInput uint64 `json:"net_input_bytes"`
|
||||
NetOutput uint64 `json:"net_output_bytes"`
|
||||
BlockInput uint64 `json:"block_input_bytes"`
|
||||
BlockOutput uint64 `json:"block_output_bytes"`
|
||||
UpTime uint64 `json:"uptime_sec"`
|
||||
lsContainerObj
|
||||
}
|
||||
|
||||
// lsCmd represents the ls command
|
||||
var lsCmd = &cobra.Command{
|
||||
Use: "ls",
|
||||
@ -90,20 +104,41 @@ ccl ls squid`,
|
||||
}
|
||||
|
||||
if lsJsonFormat {
|
||||
out := make([]lsContainerObj, 0)
|
||||
out := make([]interface{}, 0)
|
||||
for _, c := range conts {
|
||||
run, cre := false, false
|
||||
if conn != nil {
|
||||
run, cre = c.IsRunning(), c.IsCreated()
|
||||
}
|
||||
out = append(out, lsContainerObj{
|
||||
baseObj := lsContainerObj{
|
||||
Category: c.Category,
|
||||
StartGroup: c.StartGroup,
|
||||
Name: c.Name,
|
||||
Image: c.Image,
|
||||
Running: run,
|
||||
Created: cre,
|
||||
})
|
||||
}
|
||||
if run {
|
||||
if stats := c.GetStats(); stats != nil {
|
||||
out = append(out, lsContainerStatsObj{
|
||||
CPUNano: stats.CPUNano,
|
||||
CPU: stats.CPU,
|
||||
MemUsage: stats.MemUsage,
|
||||
MemLimit: stats.MemLimit,
|
||||
MemPerc: stats.MemPerc,
|
||||
NetInput: stats.NetInput,
|
||||
NetOutput: stats.NetOutput,
|
||||
BlockInput: stats.BlockInput,
|
||||
BlockOutput: stats.BlockOutput,
|
||||
UpTime: uint64(c.RunningTime().Seconds()),
|
||||
lsContainerObj: baseObj,
|
||||
})
|
||||
} else {
|
||||
out = append(out, baseObj)
|
||||
}
|
||||
} else {
|
||||
out = append(out, baseObj)
|
||||
}
|
||||
}
|
||||
val, err := json.Marshal(out)
|
||||
if err != nil {
|
||||
@ -117,7 +152,8 @@ ccl ls squid`,
|
||||
defer tw.Flush()
|
||||
|
||||
if conn != nil {
|
||||
titlemsg := "CATEGORY\tGROUP\tNAME\tIMAGE\tCREATED\tRUNNING"
|
||||
titlemsg := "CATEGORY\tGROUP\tNAME\tIMAGE\tCREATED\t RUNNING\tCPU%\tMEM%"
|
||||
block := "%s\t%5d\t%s\t%s\t%s\t%s\t%.1f\t%.1f\n"
|
||||
fmt.Fprintf(tw, "%s\n", titlemsg)
|
||||
for _, c := range conts {
|
||||
data := []interface{}{c.Category, c.StartGroup, c.Name, c.Image}
|
||||
@ -127,11 +163,21 @@ ccl ls squid`,
|
||||
data = append(data, "")
|
||||
}
|
||||
if c.IsRunning() {
|
||||
data = append(data, " ✓")
|
||||
raw := int64(c.RunningTime().Seconds())
|
||||
seconds := raw % 60
|
||||
minutes := (raw / 60) % 60
|
||||
hours := (raw / 60) / 60
|
||||
disp := fmt.Sprintf("%3d:%02d:%02d", hours, minutes, seconds)
|
||||
data = append(data, disp)
|
||||
} else {
|
||||
data = append(data, "")
|
||||
}
|
||||
fmt.Fprintf(tw, "%s\t%5d\t%s\t%s\t%s\t%s\n", data...)
|
||||
if stats := c.GetStats(); c.IsRunning() && stats != nil {
|
||||
data = append(data, stats.CPU, stats.MemPerc)
|
||||
} else {
|
||||
data = append(data, 0.0, 0.0)
|
||||
}
|
||||
fmt.Fprintf(tw, block, data...)
|
||||
}
|
||||
} else {
|
||||
titlemsg := "CATEGORY\tGROUP\tNAME\tIMAGE"
|
||||
|
@ -28,8 +28,10 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
cmd "gitea.elkins.co/Networking/ccl/internal/pkg/command"
|
||||
"gitea.elkins.co/Networking/ccl/internal/pkg/network"
|
||||
@ -390,6 +392,14 @@ func (c *Container) IsCreated() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *Container) RunningTime() time.Duration {
|
||||
cdata := c.getCData()
|
||||
if cdata == nil || cdata.State == nil {
|
||||
return 0
|
||||
}
|
||||
return time.Since(cdata.State.StartedAt)
|
||||
}
|
||||
|
||||
// UpdateCommands will pull the image (to force updates) and then recreate the
|
||||
// container. It will be stopped first.
|
||||
func (c *Container) UpdateCommands() cmd.Set {
|
||||
@ -503,6 +513,26 @@ func (c *Container) watchCData() {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Container) GetStats() *define.ContainerStats {
|
||||
no := false
|
||||
reportChan, err := containers.Stats(c.conn, []string{c.getCData().ID}, &containers.StatsOptions{Stream: &no})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "containers.stats returned error (%s): %s\n", c.Name, err)
|
||||
return nil
|
||||
}
|
||||
select {
|
||||
case report := <-reportChan:
|
||||
if report.Error != nil {
|
||||
fmt.Fprintf(os.Stderr, "containers.stats returned error in the channel (%s): %s\n", c.Name, report.Error)
|
||||
break
|
||||
}
|
||||
return &report.Stats[0]
|
||||
case <-time.After(250 * time.Millisecond):
|
||||
break
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Pid will return the host process id of the main container process (pid
|
||||
// 1 inside the container)
|
||||
func (c *Container) Pid() int {
|
||||
|
Loading…
x
Reference in New Issue
Block a user