blob: 28228164efbaa442d70986473873528b208f37c9 [file] [log] [blame]
khenaidood948f772021-08-11 17:49:24 -04001// Copyright 2019 The Prometheus Authors
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14package procfs
15
16import (
17 "bufio"
18 "errors"
19 "os"
20 "regexp"
21 "strconv"
22)
23
24var (
25 cpuLineRE = regexp.MustCompile(`cpu(\d+) (\d+) (\d+) (\d+) (\d+) (\d+) (\d+) (\d+) (\d+) (\d+)`)
26 procLineRE = regexp.MustCompile(`(\d+) (\d+) (\d+)`)
27)
28
29// Schedstat contains scheduler statistics from /proc/schedstat
30//
31// See
32// https://www.kernel.org/doc/Documentation/scheduler/sched-stats.txt
33// for a detailed description of what these numbers mean.
34//
35// Note the current kernel documentation claims some of the time units are in
36// jiffies when they are actually in nanoseconds since 2.6.23 with the
37// introduction of CFS. A fix to the documentation is pending. See
38// https://lore.kernel.org/patchwork/project/lkml/list/?series=403473
39type Schedstat struct {
40 CPUs []*SchedstatCPU
41}
42
43// SchedstatCPU contains the values from one "cpu<N>" line
44type SchedstatCPU struct {
45 CPUNum string
46
47 RunningNanoseconds uint64
48 WaitingNanoseconds uint64
49 RunTimeslices uint64
50}
51
52// ProcSchedstat contains the values from /proc/<pid>/schedstat
53type ProcSchedstat struct {
54 RunningNanoseconds uint64
55 WaitingNanoseconds uint64
56 RunTimeslices uint64
57}
58
59// Schedstat reads data from /proc/schedstat
60func (fs FS) Schedstat() (*Schedstat, error) {
61 file, err := os.Open(fs.proc.Path("schedstat"))
62 if err != nil {
63 return nil, err
64 }
65 defer file.Close()
66
67 stats := &Schedstat{}
68 scanner := bufio.NewScanner(file)
69
70 for scanner.Scan() {
71 match := cpuLineRE.FindStringSubmatch(scanner.Text())
72 if match != nil {
73 cpu := &SchedstatCPU{}
74 cpu.CPUNum = match[1]
75
76 cpu.RunningNanoseconds, err = strconv.ParseUint(match[8], 10, 64)
77 if err != nil {
78 continue
79 }
80
81 cpu.WaitingNanoseconds, err = strconv.ParseUint(match[9], 10, 64)
82 if err != nil {
83 continue
84 }
85
86 cpu.RunTimeslices, err = strconv.ParseUint(match[10], 10, 64)
87 if err != nil {
88 continue
89 }
90
91 stats.CPUs = append(stats.CPUs, cpu)
92 }
93 }
94
95 return stats, nil
96}
97
98func parseProcSchedstat(contents string) (ProcSchedstat, error) {
99 var (
100 stats ProcSchedstat
101 err error
102 )
103 match := procLineRE.FindStringSubmatch(contents)
104
105 if match != nil {
106 stats.RunningNanoseconds, err = strconv.ParseUint(match[1], 10, 64)
107 if err != nil {
108 return stats, err
109 }
110
111 stats.WaitingNanoseconds, err = strconv.ParseUint(match[2], 10, 64)
112 if err != nil {
113 return stats, err
114 }
115
116 stats.RunTimeslices, err = strconv.ParseUint(match[3], 10, 64)
117 return stats, err
118 }
119
120 return stats, errors.New("could not parse schedstat")
121}