-// Open the cgroup stats file in /sys/fs corresponding to the target
-// cgroup, and return an *os.File. If no stats file is available,
-// return nil.
-//
-// TODO: Instead of trying all options, choose a process in the
-// container, and read /proc/PID/cgroup to determine the appropriate
-// cgroup root for the given statgroup. (This will avoid falling back
-// to host-level stats during container setup and teardown.)
-func OpenStatFile(stderr chan<- string, cgroup Cgroup, statgroup string, stat string) (*os.File, error) {
- var path string
- path = fmt.Sprintf("%s/%s/%s/%s/%s", cgroup.root, statgroup, cgroup.parent, cgroup.cid, stat)
- file, err := os.Open(path)
- if err != nil {
- path = fmt.Sprintf("%s/%s/%s/%s", cgroup.root, cgroup.parent, cgroup.cid, stat)
- file, err = os.Open(path)
- }
- if err != nil {
- path = fmt.Sprintf("%s/%s/%s", cgroup.root, statgroup, stat)
- file, err = os.Open(path)
- }
- if err != nil {
- path = fmt.Sprintf("%s/%s", cgroup.root, stat)
- file, err = os.Open(path)
- }
- if err != nil {
- file = nil
- path = ""
- }
- if pathWas, ok := reportedStatFile[stat]; !ok || pathWas != path {
- // Log whenever we start using a new/different cgroup
- // stat file for a given statistic. This typically
- // happens 1 to 3 times per statistic, depending on
- // whether we happen to collect stats [a] before any
- // processes have been created in the container and
- // [b] after all contained processes have exited.
- reportedStatFile[stat] = path
- if path == "" {
- stderr <- fmt.Sprintf("crunchstat: did not find stats file (root %s, parent %s, cid %s, statgroup %s, stat %s)", cgroup.root, cgroup.parent, cgroup.cid, statgroup, stat)
- } else {
- stderr <- fmt.Sprintf("crunchstat: reading stats from %s", path)
- }
- }
- return file, err
-}
-
-func GetContainerNetStats(stderr chan<- string, cgroup Cgroup) (io.Reader, error) {
- procsFile, err := OpenStatFile(stderr, cgroup, "cpuacct", "cgroup.procs")
- if err != nil {
- return nil, err
- }
- defer procsFile.Close()
- reader := bufio.NewScanner(procsFile)
- for reader.Scan() {
- taskPid := reader.Text()
- statsFilename := fmt.Sprintf("/proc/%s/net/dev", taskPid)
- stats, err := OpenAndReadAll(statsFilename, stderr)
- if err != nil {
- continue
- }
- return strings.NewReader(string(stats)), nil