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 }