@@ -2,27 +2,86 @@ package usage
22
33import (
44 "context"
5+ "encoding/json"
56 "fmt"
67
8+ "github.com/charmbracelet/bubbles/table"
9+ "github.com/docker/docker/api/types"
710 "github.com/docker/docker/client"
11+ "github.com/sourcegraph/sourcegraph/lib/errors"
12+ "github.com/sourcegraph/src-cli/internal/scout/style"
813)
914
1015func Docker (ctx context.Context , client client.Client , opts ... Option ) error {
1116 cfg := & Config {
12- namespace : "default" ,
13- docker : true ,
14- pod : "" ,
15- container : "" ,
16- spy : false ,
17- k8sClient : nil ,
18- dockerClient : & client ,
19- metricsClient : nil ,
17+ namespace : "default" ,
18+ docker : true ,
19+ pod : "" ,
20+ container : "" ,
21+ spy : false ,
22+ dockerClient : & client ,
2023 }
2124
2225 for _ , opt := range opts {
2326 opt (cfg )
2427 }
2528
26- fmt .Println ("Command is routed, but not yet fixed." )
29+ containers , err := cfg .dockerClient .ContainerList (ctx , types.ContainerListOptions {})
30+ if err != nil {
31+ return errors .Wrap (err , "could not get list of containers" )
32+ }
33+
34+ return renderDockerUsageTable (ctx , cfg , containers )
35+ }
36+
37+ // renderDockerUsageTable renders a table displaying CPU and memory usage for Docker containers.
38+ func renderDockerUsageTable (ctx context.Context , cfg * Config , containers []types.Container ) error {
39+ columns := []table.Column {
40+ {Title : "Container" , Width : 20 },
41+ {Title : "Cores" , Width : 10 },
42+ {Title : "Usage" , Width : 10 },
43+ {Title : "Memory" , Width : 10 },
44+ {Title : "Usage" , Width : 10 },
45+ }
46+ rows := []table.Row {}
47+
48+ for _ , container := range containers {
49+ containerInfo , err := cfg .dockerClient .ContainerInspect (ctx , container .ID )
50+ if err != nil {
51+ return errors .Wrap (err , "failed to get container info" )
52+ }
53+
54+ stats , err := cfg .dockerClient .ContainerStats (ctx , container .ID , false )
55+ if err != nil {
56+ return errors .Wrap (err , "could not get container stats" )
57+ }
58+ defer stats .Body .Close ()
59+
60+ var usage types.StatsJSON
61+ if err := json .NewDecoder (stats .Body ).Decode (& usage ); err != nil {
62+ return errors .Wrap (err , "could not decode container stats" )
63+ }
64+
65+ row := makeDockerUsageRow (usage , containerInfo )
66+ rows = append (rows , row )
67+ }
68+
69+ style .ResourceTable (columns , rows )
2770 return nil
2871}
72+
73+ // makeDockerUsageRow generates a table row displaying CPU and memory usage for a Docker container.
74+ func makeDockerUsageRow (containerUsage types.StatsJSON , containerInfo types.ContainerJSON ) table.Row {
75+ cpuCores := float64 (containerInfo .HostConfig .NanoCPUs )
76+ memory := float64 (containerInfo .HostConfig .Memory )
77+ cpuUsage := float64 (containerUsage .CPUStats .CPUUsage .TotalUsage )
78+ memoryUsage := float64 (containerUsage .MemoryStats .Usage )
79+
80+ return table.Row {
81+ containerInfo .Name ,
82+ fmt .Sprintf ("%.2f" , cpuCores / 1_000_000_000 ),
83+ fmt .Sprintf ("%.2f%%" , getPercentage (cpuUsage , cpuCores )),
84+ fmt .Sprintf ("%.2fG" , memory / 1_000_000_000 ),
85+ fmt .Sprintf ("%.2f%%" , getPercentage (memoryUsage , memory )),
86+ }
87+ }
0 commit comments