github.com/demonoid81/containerd@v1.3.4/cmd/ctr/commands/tasks/metrics.go (about)

     1  // +build linux
     2  
     3  /*
     4     Copyright The containerd Authors.
     5  
     6     Licensed under the Apache License, Version 2.0 (the "License");
     7     you may not use this file except in compliance with the License.
     8     You may obtain a copy of the License at
     9  
    10         http://www.apache.org/licenses/LICENSE-2.0
    11  
    12     Unless required by applicable law or agreed to in writing, software
    13     distributed under the License is distributed on an "AS IS" BASIS,
    14     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15     See the License for the specific language governing permissions and
    16     limitations under the License.
    17  */
    18  
    19  package tasks
    20  
    21  import (
    22  	"encoding/json"
    23  	"errors"
    24  	"fmt"
    25  	"os"
    26  	"text/tabwriter"
    27  
    28  	"github.com/containerd/cgroups"
    29  	"github.com/containerd/containerd/cmd/ctr/commands"
    30  	"github.com/containerd/typeurl"
    31  	"github.com/urfave/cli"
    32  )
    33  
    34  func init() {
    35  	// metricsCommand is only added on Linux as github.com/containerd/cgroups
    36  	// does not compile on darwin or windows
    37  	Command.Subcommands = append(Command.Subcommands, metricsCommand)
    38  }
    39  
    40  const (
    41  	formatFlag  = "format"
    42  	formatTable = "table"
    43  	formatJSON  = "json"
    44  )
    45  
    46  var metricsCommand = cli.Command{
    47  	Name:      "metrics",
    48  	Usage:     "get a single data point of metrics for a task with the built-in Linux runtime",
    49  	ArgsUsage: "CONTAINER",
    50  	Aliases:   []string{"metric"},
    51  	Flags: []cli.Flag{
    52  		cli.StringFlag{
    53  			Name:  formatFlag,
    54  			Usage: `"table" or "json"`,
    55  			Value: formatTable,
    56  		},
    57  	},
    58  	Action: func(context *cli.Context) error {
    59  		client, ctx, cancel, err := commands.NewClient(context)
    60  		if err != nil {
    61  			return err
    62  		}
    63  		defer cancel()
    64  		container, err := client.LoadContainer(ctx, context.Args().First())
    65  		if err != nil {
    66  			return err
    67  		}
    68  		task, err := container.Task(ctx, nil)
    69  		if err != nil {
    70  			return err
    71  		}
    72  		metric, err := task.Metrics(ctx)
    73  		if err != nil {
    74  			return nil
    75  		}
    76  		anydata, err := typeurl.UnmarshalAny(metric.Data)
    77  		if err != nil {
    78  			return err
    79  		}
    80  		data, ok := anydata.(*cgroups.Metrics)
    81  		if !ok {
    82  			return errors.New("cannot convert metric data to cgroups.Metrics")
    83  		}
    84  
    85  		switch context.String(formatFlag) {
    86  		case formatTable:
    87  			w := tabwriter.NewWriter(os.Stdout, 1, 8, 4, ' ', 0)
    88  			fmt.Fprintf(w, "ID\tTIMESTAMP\t\n")
    89  			fmt.Fprintf(w, "%s\t%s\t\n\n", metric.ID, metric.Timestamp)
    90  
    91  			fmt.Fprintf(w, "METRIC\tVALUE\t\n")
    92  			if data.Memory != nil {
    93  				fmt.Fprintf(w, "memory.usage_in_bytes\t%d\t\n", data.Memory.Usage.Usage)
    94  				fmt.Fprintf(w, "memory.limit_in_bytes\t%d\t\n", data.Memory.Usage.Limit)
    95  				fmt.Fprintf(w, "memory.stat.cache\t%d\t\n", data.Memory.TotalCache)
    96  			}
    97  			if data.CPU != nil {
    98  				fmt.Fprintf(w, "cpuacct.usage\t%d\t\n", data.CPU.Usage.Total)
    99  				fmt.Fprintf(w, "cpuacct.usage_percpu\t%v\t\n", data.CPU.Usage.PerCPU)
   100  			}
   101  			if data.Pids != nil {
   102  				fmt.Fprintf(w, "pids.current\t%v\t\n", data.Pids.Current)
   103  				fmt.Fprintf(w, "pids.limit\t%v\t\n", data.Pids.Limit)
   104  			}
   105  			return w.Flush()
   106  		case formatJSON:
   107  			marshaledJSON, err := json.MarshalIndent(data, "", "  ")
   108  			if err != nil {
   109  				return err
   110  			}
   111  			fmt.Println(string(marshaledJSON))
   112  			return nil
   113  		default:
   114  			return errors.New("format must be table or json")
   115  		}
   116  	},
   117  }