github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/runsc/boot/events.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package boot 16 17 import ( 18 "github.com/SagerNet/gvisor/pkg/sentry/control" 19 "github.com/SagerNet/gvisor/pkg/sentry/usage" 20 ) 21 22 // EventOut is the return type of the Event command. 23 type EventOut struct { 24 Event Event `json:"event"` 25 26 // ContainerUsage maps each container ID to its total CPU usage. 27 ContainerUsage map[string]uint64 `json:"containerUsage"` 28 } 29 30 // Event struct for encoding the event data to JSON. Corresponds to runc's 31 // main.event struct. 32 type Event struct { 33 Type string `json:"type"` 34 ID string `json:"id"` 35 Data Stats `json:"data"` 36 } 37 38 // Stats is the runc specific stats structure for stability when encoding and 39 // decoding stats. 40 type Stats struct { 41 CPU CPU `json:"cpu"` 42 Memory Memory `json:"memory"` 43 Pids Pids `json:"pids"` 44 } 45 46 // Pids contains stats on processes. 47 type Pids struct { 48 Current uint64 `json:"current,omitempty"` 49 Limit uint64 `json:"limit,omitempty"` 50 } 51 52 // MemoryEntry contains stats on a kind of memory. 53 type MemoryEntry struct { 54 Limit uint64 `json:"limit"` 55 Usage uint64 `json:"usage,omitempty"` 56 Max uint64 `json:"max,omitempty"` 57 Failcnt uint64 `json:"failcnt"` 58 } 59 60 // Memory contains stats on memory. 61 type Memory struct { 62 Cache uint64 `json:"cache,omitempty"` 63 Usage MemoryEntry `json:"usage,omitempty"` 64 Swap MemoryEntry `json:"swap,omitempty"` 65 Kernel MemoryEntry `json:"kernel,omitempty"` 66 KernelTCP MemoryEntry `json:"kernelTCP,omitempty"` 67 Raw map[string]uint64 `json:"raw,omitempty"` 68 } 69 70 // CPU contains stats on the CPU. 71 type CPU struct { 72 Usage CPUUsage `json:"usage"` 73 } 74 75 // CPUUsage contains stats on CPU usage. 76 type CPUUsage struct { 77 Kernel uint64 `json:"kernel,omitempty"` 78 User uint64 `json:"user,omitempty"` 79 Total uint64 `json:"total,omitempty"` 80 PerCPU []uint64 `json:"percpu,omitempty"` 81 } 82 83 // Event gets the events from the container. 84 func (cm *containerManager) Event(_ *struct{}, out *EventOut) error { 85 *out = EventOut{ 86 Event: Event{ 87 Type: "stats", 88 }, 89 } 90 91 // Memory usage. 92 // TODO(github.com/SagerNet/issue/172): Per-container accounting. 93 mem := cm.l.k.MemoryFile() 94 mem.UpdateUsage() 95 _, totalUsage := usage.MemoryAccounting.Copy() 96 out.Event.Data.Memory.Usage = MemoryEntry{ 97 Usage: totalUsage, 98 } 99 100 // PIDs. 101 // TODO(github.com/SagerNet/issue/172): Per-container accounting. 102 out.Event.Data.Pids.Current = uint64(len(cm.l.k.TaskSet().Root.ThreadGroups())) 103 104 // CPU usage by container. 105 out.ContainerUsage = control.ContainerUsage(cm.l.k) 106 107 return nil 108 }