// Copyright 2021 The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package procfs import ( "bufio" "bytes" "fmt" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) // CgroupSummary models one line from /proc/cgroups. // This file contains information about the controllers that are compiled into the kernel. // // Also see http://man7.org/linux/man-pages/man7/cgroups.7.html type CgroupSummary struct { // The name of the controller. controller is also known as subsystem. SubsysName string // The unique ID of the cgroup hierarchy on which this controller is mounted. Hierarchy int // The number of control groups in this hierarchy using this controller. Cgroups int // This field contains the value 1 if this controller is enabled, or 0 if it has been disabled Enabled int } // parseCgroupSummary parses each line of the /proc/cgroup file // Line format is `subsys_name hierarchy num_cgroups enabled`. func parseCgroupSummaryString(CgroupSummaryStr string) (*CgroupSummary, error) { var err error fields := strings.Fields(CgroupSummaryStr) // require at least 4 fields if len(fields) < 4 { return nil, fmt.Errorf("at least 4 fields required, found %d fields in cgroup info string: %s", len(fields), CgroupSummaryStr) } CgroupSummary := &CgroupSummary{ SubsysName: fields[0], } CgroupSummary.Hierarchy, err = strconv.Atoi(fields[1]) if err != nil { return nil, fmt.Errorf("failed to parse hierarchy ID") } CgroupSummary.Cgroups, err = strconv.Atoi(fields[2]) if err != nil { return nil, fmt.Errorf("failed to parse Cgroup Num") } CgroupSummary.Enabled, err = strconv.Atoi(fields[3]) if err != nil { return nil, fmt.Errorf("failed to parse Enabled") } return CgroupSummary, nil } // parseCgroupSummary reads each line of the /proc/cgroup file. func parseCgroupSummary(data []byte) ([]CgroupSummary, error) { var CgroupSummarys []CgroupSummary scanner := bufio.NewScanner(bytes.NewReader(data)) for scanner.Scan() { CgroupSummaryString := scanner.Text() // ignore comment lines if strings.HasPrefix(CgroupSummaryString, "#") { continue } CgroupSummary, err := parseCgroupSummaryString(CgroupSummaryString) if err != nil { return nil, err } CgroupSummarys = append(CgroupSummarys, *CgroupSummary) } err := scanner.Err() return CgroupSummarys, err } // CgroupSummarys returns information about current /proc/cgroups. func (fs FS) CgroupSummarys() ([]CgroupSummary, error) { data, err := util.ReadFileNoStat(fs.proc.Path("cgroups")) if err != nil { return nil, err } return parseCgroupSummary(data) }