Path: blob/main/components/common-go/cgroups/cgroup.go
2496 views
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.1// Licensed under the GNU Affero General Public License (AGPL).2// See License.AGPL.txt in the project root for license information.34package cgroups56import (7"bufio"8"fmt"9"math"10"os"11"regexp"12"strconv"13"strings"1415"github.com/containerd/cgroups"16v2 "github.com/containerd/cgroups/v2"17)1819const DefaultMountPoint = "/sys/fs/cgroup"2021func IsUnifiedCgroupSetup() (bool, error) {22return cgroups.Mode() == cgroups.Unified, nil23}2425func EnsureCpuControllerEnabled(basePath, cgroupPath string) error {26c, err := v2.NewManager(basePath, cgroupPath, &v2.Resources{})27if err != nil {28return err29}3031err = c.ToggleControllers([]string{"cpu"}, v2.Enable)32if err != nil {33return err34}3536return nil37}3839type CpuStats struct {40UsageTotal uint6441UsageUser uint6442UsageSystem uint6443}4445type MemoryStats struct {46InactiveFileTotal uint6447}4849func ReadSingleValue(path string) (uint64, error) {50content, err := os.ReadFile(path)51if err != nil {52return 0, err53}5455value := strings.TrimSpace(string(content))56if value == "max" || value == "-1" {57return math.MaxUint64, nil58}5960max, err := strconv.ParseUint(value, 10, 64)61if err != nil {62return 0, err63}6465return max, nil66}6768func ReadFlatKeyedFile(path string) (map[string]uint64, error) {69content, err := os.ReadFile(path)70if err != nil {71return nil, err72}7374entries := strings.Split(strings.TrimSpace(string(content)), "\n")75kv := make(map[string]uint64, len(entries))76for _, entry := range entries {77tokens := strings.Split(entry, " ")78if len(tokens) < 2 {79continue80}81v, err := strconv.ParseUint(tokens[1], 10, 64)82if err != nil {83continue84}85kv[tokens[0]] = v86}8788return kv, nil89}9091// Read the total stalled time in microseconds for full and some92// It is not necessary to read avg10, avg60 and avg300 as these93// are only for convenience. They are calculated as the rate during94// the desired time frame.95func ReadPSIValue(path string) (PSI, error) {96file, err := os.Open(path)97if err != nil {98return PSI{}, err99}100defer file.Close()101102scanner := bufio.NewScanner(file)103var psi PSI104for scanner.Scan() {105line := scanner.Text()106if err = scanner.Err(); err != nil {107return PSI{}, fmt.Errorf("could not read psi file: %w", err)108}109110i := strings.LastIndex(line, "total=")111if i == -1 {112return PSI{}, fmt.Errorf("could not find total stalled time")113}114115total, err := strconv.ParseUint(line[i+6:], 10, 64)116if err != nil {117return PSI{}, fmt.Errorf("could not parse total stalled time: %w", err)118}119120if strings.HasPrefix(line, "some") {121psi.Some = total122}123124if strings.HasPrefix(line, "full") {125psi.Full = total126}127}128129return psi, nil130}131132type PSI struct {133Some uint64134Full uint64135}136137var (138deviceIORegex = regexp.MustCompile(`([0-9]+):([0-9]+) rbps=([0-9]+) wbps=([0-9]+)`)139)140141type DeviceIOMax struct {142Major uint64143Minor uint64144Read uint64145Write uint64146}147148func ReadIOMax(path string) ([]DeviceIOMax, error) {149content, err := os.ReadFile(path)150if err != nil {151return nil, err152}153154var devices []DeviceIOMax155for _, line := range strings.Split(string(content), "\n") {156line = strings.TrimSpace(line)157if line == "" {158continue159}160161matches := deviceIORegex.FindStringSubmatch(line)162if len(matches) != 5 {163return nil, fmt.Errorf("invalid line in %s: %s", path, line)164}165166major, err := strconv.ParseUint(matches[1], 10, 64)167if err != nil {168return nil, fmt.Errorf("cannot parse major number: %w", err)169}170minor, err := strconv.ParseUint(matches[2], 10, 64)171if err != nil {172return nil, fmt.Errorf("cannot parse minor number: %w", err)173}174read, err := strconv.ParseUint(matches[3], 10, 64)175if err != nil {176return nil, fmt.Errorf("cannot parse read bytes: %w", err)177}178write, err := strconv.ParseUint(matches[4], 10, 64)179if err != nil {180return nil, fmt.Errorf("cannot parse write bytes: %w", err)181}182devices = append(devices, DeviceIOMax{183Major: major,184Minor: minor,185Read: read,186Write: write,187})188}189190return devices, nil191}192193194