summaryrefslogtreecommitdiff
path: root/cmd/podman/pod_stats.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/podman/pod_stats.go')
-rw-r--r--cmd/podman/pod_stats.go286
1 files changed, 0 insertions, 286 deletions
diff --git a/cmd/podman/pod_stats.go b/cmd/podman/pod_stats.go
deleted file mode 100644
index 297603410..000000000
--- a/cmd/podman/pod_stats.go
+++ /dev/null
@@ -1,286 +0,0 @@
-package main
-
-import (
- "fmt"
- "html/template"
- "os"
- "reflect"
- "strings"
- "text/tabwriter"
- "time"
-
- tm "github.com/buger/goterm"
- "github.com/containers/buildah/pkg/formats"
- "github.com/containers/libpod/cmd/podman/cliconfig"
- "github.com/containers/libpod/libpod"
- "github.com/containers/libpod/libpod/define"
- "github.com/containers/libpod/pkg/adapter"
- "github.com/containers/libpod/pkg/cgroups"
- "github.com/containers/libpod/pkg/rootless"
- "github.com/pkg/errors"
- "github.com/spf13/cobra"
-)
-
-var (
- podStatsCommand cliconfig.PodStatsValues
- podStatsDescription = `For each specified pod this command will display percentage of CPU, memory, network I/O, block I/O and PIDs for containers in one the pods.`
-
- _podStatsCommand = &cobra.Command{
- Use: "stats [flags] [POD...]",
- Short: "Display a live stream of resource usage statistics for the containers in one or more pods",
- Long: podStatsDescription,
- RunE: func(cmd *cobra.Command, args []string) error {
- podStatsCommand.InputArgs = args
- podStatsCommand.GlobalFlags = MainGlobalOpts
- podStatsCommand.Remote = remoteclient
- return podStatsCmd(&podStatsCommand)
- },
- Example: `podman stats -a --no-stream
- podman stats --no-reset ctrID
- podman stats --no-stream --format "table {{.ID}} {{.Name}} {{.MemUsage}}" ctrID`,
- }
-)
-
-func init() {
- podStatsCommand.Command = _podStatsCommand
- podStatsCommand.SetHelpTemplate(HelpTemplate())
- podStatsCommand.SetUsageTemplate(UsageTemplate())
- flags := podStatsCommand.Flags()
- flags.BoolVarP(&podStatsCommand.All, "all", "a", false, "Provide stats for all running pods")
- flags.StringVar(&podStatsCommand.Format, "format", "", "Pretty-print container statistics to JSON or using a Go template")
- flags.BoolVarP(&podStatsCommand.Latest, "latest", "l", false, "Provide stats on the latest pod podman is aware of")
- flags.BoolVar(&podStatsCommand.NoStream, "no-stream", false, "Disable streaming stats and only pull the first result, default setting is false")
- flags.BoolVar(&podStatsCommand.NoReset, "no-reset", false, "Disable resetting the screen between intervals")
- markFlagHiddenForRemoteClient("latest", flags)
-}
-
-func podStatsCmd(c *cliconfig.PodStatsValues) error {
- if rootless.IsRootless() {
- unified, err := cgroups.IsCgroup2UnifiedMode()
- if err != nil {
- return err
- }
- if !unified {
- return errors.New("stats is not supported in rootless mode without cgroups v2")
- }
- }
-
- format := c.Format
- all := c.All
- latest := c.Latest
- ctr := 0
- if all {
- ctr += 1
- }
- if latest {
- ctr += 1
- }
- if len(c.InputArgs) > 0 {
- ctr += 1
- }
-
- if ctr > 1 {
- return errors.Errorf("--all, --latest and containers cannot be used together")
- }
-
- runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand)
- if err != nil {
- return errors.Wrapf(err, "could not get runtime")
- }
- defer runtime.DeferredShutdown(false)
-
- times := -1
- if c.NoStream {
- times = 1
- }
-
- pods, err := runtime.GetStatPods(c)
- if err != nil {
- return errors.Wrapf(err, "unable to get a list of pods")
- }
-
- // Create empty container stat results for our first pass
- var previousPodStats []*adapter.PodContainerStats
- for _, p := range pods {
- cs := make(map[string]*libpod.ContainerStats)
- pcs := adapter.PodContainerStats{
- Pod: p,
- ContainerStats: cs,
- }
- previousPodStats = append(previousPodStats, &pcs)
- }
-
- step := 1
- if times == -1 {
- times = 1
- step = 0
- }
-
- headerNames := make(map[string]string)
- if c.Format != "" {
- // Make a map of the field names for the headers
- v := reflect.ValueOf(podStatOut{})
- t := v.Type()
- for i := 0; i < t.NumField(); i++ {
- value := strings.ToUpper(splitCamelCase(t.Field(i).Name))
- switch value {
- case "CPU", "MEM":
- value += " %"
- case "MEM USAGE":
- value = "MEM USAGE / LIMIT"
- }
- headerNames[t.Field(i).Name] = value
- }
- }
-
- for i := 0; i < times; i += step {
- var newStats []*adapter.PodContainerStats
- for _, p := range pods {
- prevStat := getPreviousPodContainerStats(p.ID(), previousPodStats)
- newPodStats, err := p.GetPodStats(prevStat)
- if errors.Cause(err) == define.ErrNoSuchPod {
- continue
- }
- if err != nil {
- return err
- }
- newPod := adapter.PodContainerStats{
- Pod: p,
- ContainerStats: newPodStats,
- }
- newStats = append(newStats, &newPod)
- }
- //Output
- if strings.ToLower(format) != formats.JSONString && !c.NoReset {
- tm.Clear()
- tm.MoveCursor(1, 1)
- tm.Flush()
- }
- if strings.ToLower(format) == formats.JSONString {
- if err := outputJson(newStats); err != nil {
- return err
- }
-
- } else {
- results := podContainerStatsToPodStatOut(newStats)
- if len(format) == 0 {
- outputToStdOut(results)
- } else if err := printPSFormat(c.Format, results, headerNames); err != nil {
- return err
- }
- }
- time.Sleep(time.Second)
- previousPodStats := new([]*libpod.PodContainerStats)
- if err := libpod.JSONDeepCopy(newStats, previousPodStats); err != nil {
- return err
- }
- pods, err = runtime.GetStatPods(c)
- if err != nil {
- return err
- }
- }
-
- return nil
-}
-
-func podContainerStatsToPodStatOut(stats []*adapter.PodContainerStats) []*podStatOut {
- var out []*podStatOut
- for _, p := range stats {
- for _, c := range p.ContainerStats {
- o := podStatOut{
- CPU: floatToPercentString(c.CPU),
- MemUsage: combineHumanValues(c.MemUsage, c.MemLimit),
- Mem: floatToPercentString(c.MemPerc),
- NetIO: combineHumanValues(c.NetInput, c.NetOutput),
- BlockIO: combineHumanValues(c.BlockInput, c.BlockOutput),
- PIDS: pidsToString(c.PIDs),
- CID: c.ContainerID[:12],
- Name: c.Name,
- Pod: p.Pod.ID()[:12],
- }
- out = append(out, &o)
- }
- }
- return out
-}
-
-type podStatOut struct {
- CPU string
- MemUsage string
- Mem string
- NetIO string
- BlockIO string
- PIDS string
- Pod string
- CID string
- Name string
-}
-
-func printPSFormat(format string, stats []*podStatOut, headerNames map[string]string) error {
- if len(stats) == 0 {
- return nil
- }
-
- // Use a tabwriter to align column format
- w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
- // Spit out the header if "table" is present in the format
- if strings.HasPrefix(format, "table") {
- hformat := strings.Replace(strings.TrimSpace(format[5:]), " ", "\t", -1)
- format = hformat
- headerTmpl, err := template.New("header").Parse(hformat)
- if err != nil {
- return err
- }
- if err := headerTmpl.Execute(w, headerNames); err != nil {
- return err
- }
- fmt.Fprintln(w, "")
- }
-
- // Spit out the data rows now
- dataTmpl, err := template.New("data").Parse(format)
- if err != nil {
- return err
- }
- for _, container := range stats {
- if err := dataTmpl.Execute(w, container); err != nil {
- return err
- }
- fmt.Fprintln(w, "")
- }
- // Flush the writer
- return w.Flush()
-
-}
-
-func outputToStdOut(stats []*podStatOut) {
- w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
- outFormat := "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n"
- fmt.Fprintf(w, outFormat, "POD", "CID", "NAME", "CPU %", "MEM USAGE/ LIMIT", "MEM %", "NET IO", "BLOCK IO", "PIDS")
- for _, i := range stats {
- if len(stats) == 0 {
- fmt.Fprintf(w, outFormat, i.Pod, "--", "--", "--", "--", "--", "--", "--", "--")
- } else {
- fmt.Fprintf(w, outFormat, i.Pod, i.CID, i.Name, i.CPU, i.MemUsage, i.Mem, i.NetIO, i.BlockIO, i.PIDS)
- }
- }
- w.Flush()
-}
-
-func getPreviousPodContainerStats(podID string, prev []*adapter.PodContainerStats) map[string]*libpod.ContainerStats {
- for _, p := range prev {
- if podID == p.Pod.ID() {
- return p.ContainerStats
- }
- }
- return map[string]*libpod.ContainerStats{}
-}
-
-func outputJson(stats []*adapter.PodContainerStats) error {
- b, err := json.MarshalIndent(&stats, "", " ")
- if err != nil {
- return err
- }
- fmt.Println(string(b))
- return nil
-}