1// 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 186 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} 206