1
2
3
4
5
6
7
8
9
10
11
12
13
14 package procfs
15
16 import (
17 "bufio"
18 "bytes"
19 "fmt"
20 "io"
21 "strconv"
22 "strings"
23
24 "github.com/prometheus/procfs/internal/util"
25 )
26
27
28 type Softirqs struct {
29 Hi []uint64
30 Timer []uint64
31 NetTx []uint64
32 NetRx []uint64
33 Block []uint64
34 IRQPoll []uint64
35 Tasklet []uint64
36 Sched []uint64
37 HRTimer []uint64
38 RCU []uint64
39 }
40
41 func (fs FS) Softirqs() (Softirqs, error) {
42 fileName := fs.proc.Path("softirqs")
43 data, err := util.ReadFileNoStat(fileName)
44 if err != nil {
45 return Softirqs{}, err
46 }
47
48 reader := bytes.NewReader(data)
49
50 return parseSoftirqs(reader)
51 }
52
53 func parseSoftirqs(r io.Reader) (Softirqs, error) {
54 var (
55 softirqs = Softirqs{}
56 scanner = bufio.NewScanner(r)
57 )
58
59 if !scanner.Scan() {
60 return Softirqs{}, fmt.Errorf("%w: softirqs empty", ErrFileRead)
61 }
62
63 for scanner.Scan() {
64 parts := strings.Fields(scanner.Text())
65 var err error
66
67
68 if len(parts) < 2 {
69 continue
70 }
71 switch {
72 case parts[0] == "HI:":
73 perCPU := parts[1:]
74 softirqs.Hi = make([]uint64, len(perCPU))
75 for i, count := range perCPU {
76 if softirqs.Hi[i], err = strconv.ParseUint(count, 10, 64); err != nil {
77 return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (HI%d): %w", ErrFileParse, count, i, err)
78 }
79 }
80 case parts[0] == "TIMER:":
81 perCPU := parts[1:]
82 softirqs.Timer = make([]uint64, len(perCPU))
83 for i, count := range perCPU {
84 if softirqs.Timer[i], err = strconv.ParseUint(count, 10, 64); err != nil {
85 return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (TIMER%d): %w", ErrFileParse, count, i, err)
86 }
87 }
88 case parts[0] == "NET_TX:":
89 perCPU := parts[1:]
90 softirqs.NetTx = make([]uint64, len(perCPU))
91 for i, count := range perCPU {
92 if softirqs.NetTx[i], err = strconv.ParseUint(count, 10, 64); err != nil {
93 return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (NET_TX%d): %w", ErrFileParse, count, i, err)
94 }
95 }
96 case parts[0] == "NET_RX:":
97 perCPU := parts[1:]
98 softirqs.NetRx = make([]uint64, len(perCPU))
99 for i, count := range perCPU {
100 if softirqs.NetRx[i], err = strconv.ParseUint(count, 10, 64); err != nil {
101 return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (NET_RX%d): %w", ErrFileParse, count, i, err)
102 }
103 }
104 case parts[0] == "BLOCK:":
105 perCPU := parts[1:]
106 softirqs.Block = make([]uint64, len(perCPU))
107 for i, count := range perCPU {
108 if softirqs.Block[i], err = strconv.ParseUint(count, 10, 64); err != nil {
109 return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (BLOCK%d): %w", ErrFileParse, count, i, err)
110 }
111 }
112 case parts[0] == "IRQ_POLL:":
113 perCPU := parts[1:]
114 softirqs.IRQPoll = make([]uint64, len(perCPU))
115 for i, count := range perCPU {
116 if softirqs.IRQPoll[i], err = strconv.ParseUint(count, 10, 64); err != nil {
117 return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (IRQ_POLL%d): %w", ErrFileParse, count, i, err)
118 }
119 }
120 case parts[0] == "TASKLET:":
121 perCPU := parts[1:]
122 softirqs.Tasklet = make([]uint64, len(perCPU))
123 for i, count := range perCPU {
124 if softirqs.Tasklet[i], err = strconv.ParseUint(count, 10, 64); err != nil {
125 return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (TASKLET%d): %w", ErrFileParse, count, i, err)
126 }
127 }
128 case parts[0] == "SCHED:":
129 perCPU := parts[1:]
130 softirqs.Sched = make([]uint64, len(perCPU))
131 for i, count := range perCPU {
132 if softirqs.Sched[i], err = strconv.ParseUint(count, 10, 64); err != nil {
133 return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (SCHED%d): %w", ErrFileParse, count, i, err)
134 }
135 }
136 case parts[0] == "HRTIMER:":
137 perCPU := parts[1:]
138 softirqs.HRTimer = make([]uint64, len(perCPU))
139 for i, count := range perCPU {
140 if softirqs.HRTimer[i], err = strconv.ParseUint(count, 10, 64); err != nil {
141 return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (HRTIMER%d): %w", ErrFileParse, count, i, err)
142 }
143 }
144 case parts[0] == "RCU:":
145 perCPU := parts[1:]
146 softirqs.RCU = make([]uint64, len(perCPU))
147 for i, count := range perCPU {
148 if softirqs.RCU[i], err = strconv.ParseUint(count, 10, 64); err != nil {
149 return Softirqs{}, fmt.Errorf("%s: couldn't parse %q (RCU%d): %w", ErrFileParse, count, i, err)
150 }
151 }
152 }
153 }
154
155 if err := scanner.Err(); err != nil {
156 return Softirqs{}, fmt.Errorf("%s: couldn't parse softirqs: %w", ErrFileParse, err)
157 }
158
159 return softirqs, scanner.Err()
160 }
161
View as plain text