blob: 47a710befb93fbefd9e552d706cc5f8b7f1a4c67 [file] [log] [blame]
khenaidoo59ce9dd2019-11-11 13:05:32 -05001// Copyright 2018 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 "sort"
21 "strconv"
22 "strings"
23)
24
25// NetDevLine is single line parsed from /proc/net/dev or /proc/[pid]/net/dev.
26type NetDevLine struct {
27 Name string `json:"name"` // The name of the interface.
28 RxBytes uint64 `json:"rx_bytes"` // Cumulative count of bytes received.
29 RxPackets uint64 `json:"rx_packets"` // Cumulative count of packets received.
30 RxErrors uint64 `json:"rx_errors"` // Cumulative count of receive errors encountered.
31 RxDropped uint64 `json:"rx_dropped"` // Cumulative count of packets dropped while receiving.
32 RxFIFO uint64 `json:"rx_fifo"` // Cumulative count of FIFO buffer errors.
33 RxFrame uint64 `json:"rx_frame"` // Cumulative count of packet framing errors.
34 RxCompressed uint64 `json:"rx_compressed"` // Cumulative count of compressed packets received by the device driver.
35 RxMulticast uint64 `json:"rx_multicast"` // Cumulative count of multicast frames received by the device driver.
36 TxBytes uint64 `json:"tx_bytes"` // Cumulative count of bytes transmitted.
37 TxPackets uint64 `json:"tx_packets"` // Cumulative count of packets transmitted.
38 TxErrors uint64 `json:"tx_errors"` // Cumulative count of transmit errors encountered.
39 TxDropped uint64 `json:"tx_dropped"` // Cumulative count of packets dropped while transmitting.
40 TxFIFO uint64 `json:"tx_fifo"` // Cumulative count of FIFO buffer errors.
41 TxCollisions uint64 `json:"tx_collisions"` // Cumulative count of collisions detected on the interface.
42 TxCarrier uint64 `json:"tx_carrier"` // Cumulative count of carrier losses detected by the device driver.
43 TxCompressed uint64 `json:"tx_compressed"` // Cumulative count of compressed packets transmitted by the device driver.
44}
45
46// NetDev is parsed from /proc/net/dev or /proc/[pid]/net/dev. The map keys
47// are interface names.
48type NetDev map[string]NetDevLine
49
50// NetDev returns kernel/system statistics read from /proc/net/dev.
51func (fs FS) NetDev() (NetDev, error) {
52 return newNetDev(fs.proc.Path("net/dev"))
53}
54
55// NetDev returns kernel/system statistics read from /proc/[pid]/net/dev.
56func (p Proc) NetDev() (NetDev, error) {
57 return newNetDev(p.path("net/dev"))
58}
59
60// newNetDev creates a new NetDev from the contents of the given file.
61func newNetDev(file string) (NetDev, error) {
62 f, err := os.Open(file)
63 if err != nil {
64 return NetDev{}, err
65 }
66 defer f.Close()
67
68 netDev := NetDev{}
69 s := bufio.NewScanner(f)
70 for n := 0; s.Scan(); n++ {
71 // Skip the 2 header lines.
72 if n < 2 {
73 continue
74 }
75
76 line, err := netDev.parseLine(s.Text())
77 if err != nil {
78 return netDev, err
79 }
80
81 netDev[line.Name] = *line
82 }
83
84 return netDev, s.Err()
85}
86
87// parseLine parses a single line from the /proc/net/dev file. Header lines
88// must be filtered prior to calling this method.
89func (netDev NetDev) parseLine(rawLine string) (*NetDevLine, error) {
90 parts := strings.SplitN(rawLine, ":", 2)
91 if len(parts) != 2 {
92 return nil, errors.New("invalid net/dev line, missing colon")
93 }
94 fields := strings.Fields(strings.TrimSpace(parts[1]))
95
96 var err error
97 line := &NetDevLine{}
98
99 // Interface Name
100 line.Name = strings.TrimSpace(parts[0])
101 if line.Name == "" {
102 return nil, errors.New("invalid net/dev line, empty interface name")
103 }
104
105 // RX
106 line.RxBytes, err = strconv.ParseUint(fields[0], 10, 64)
107 if err != nil {
108 return nil, err
109 }
110 line.RxPackets, err = strconv.ParseUint(fields[1], 10, 64)
111 if err != nil {
112 return nil, err
113 }
114 line.RxErrors, err = strconv.ParseUint(fields[2], 10, 64)
115 if err != nil {
116 return nil, err
117 }
118 line.RxDropped, err = strconv.ParseUint(fields[3], 10, 64)
119 if err != nil {
120 return nil, err
121 }
122 line.RxFIFO, err = strconv.ParseUint(fields[4], 10, 64)
123 if err != nil {
124 return nil, err
125 }
126 line.RxFrame, err = strconv.ParseUint(fields[5], 10, 64)
127 if err != nil {
128 return nil, err
129 }
130 line.RxCompressed, err = strconv.ParseUint(fields[6], 10, 64)
131 if err != nil {
132 return nil, err
133 }
134 line.RxMulticast, err = strconv.ParseUint(fields[7], 10, 64)
135 if err != nil {
136 return nil, err
137 }
138
139 // TX
140 line.TxBytes, err = strconv.ParseUint(fields[8], 10, 64)
141 if err != nil {
142 return nil, err
143 }
144 line.TxPackets, err = strconv.ParseUint(fields[9], 10, 64)
145 if err != nil {
146 return nil, err
147 }
148 line.TxErrors, err = strconv.ParseUint(fields[10], 10, 64)
149 if err != nil {
150 return nil, err
151 }
152 line.TxDropped, err = strconv.ParseUint(fields[11], 10, 64)
153 if err != nil {
154 return nil, err
155 }
156 line.TxFIFO, err = strconv.ParseUint(fields[12], 10, 64)
157 if err != nil {
158 return nil, err
159 }
160 line.TxCollisions, err = strconv.ParseUint(fields[13], 10, 64)
161 if err != nil {
162 return nil, err
163 }
164 line.TxCarrier, err = strconv.ParseUint(fields[14], 10, 64)
165 if err != nil {
166 return nil, err
167 }
168 line.TxCompressed, err = strconv.ParseUint(fields[15], 10, 64)
169 if err != nil {
170 return nil, err
171 }
172
173 return line, nil
174}
175
176// Total aggregates the values across interfaces and returns a new NetDevLine.
177// The Name field will be a sorted comma separated list of interface names.
178func (netDev NetDev) Total() NetDevLine {
179 total := NetDevLine{}
180
181 names := make([]string, 0, len(netDev))
182 for _, ifc := range netDev {
183 names = append(names, ifc.Name)
184 total.RxBytes += ifc.RxBytes
185 total.RxPackets += ifc.RxPackets
khenaidoo59ce9dd2019-11-11 13:05:32 -0500186 total.RxErrors += ifc.RxErrors
187 total.RxDropped += ifc.RxDropped
188 total.RxFIFO += ifc.RxFIFO
189 total.RxFrame += ifc.RxFrame
190 total.RxCompressed += ifc.RxCompressed
191 total.RxMulticast += ifc.RxMulticast
192 total.TxBytes += ifc.TxBytes
193 total.TxPackets += ifc.TxPackets
194 total.TxErrors += ifc.TxErrors
195 total.TxDropped += ifc.TxDropped
196 total.TxFIFO += ifc.TxFIFO
197 total.TxCollisions += ifc.TxCollisions
198 total.TxCarrier += ifc.TxCarrier
199 total.TxCompressed += ifc.TxCompressed
200 }
201 sort.Strings(names)
202 total.Name = strings.Join(names, ", ")
203
204 return total
205}