/ vendor / github.com / prometheus / procfs / net_dev.go
net_dev.go
  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  
 14  package procfs
 15  
 16  import (
 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.
 26  type 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.
 48  type NetDev map[string]NetDevLine
 49  
 50  // NewNetDev returns kernel/system statistics read from /proc/net/dev.
 51  func NewNetDev() (NetDev, error) {
 52  	fs, err := NewFS(DefaultMountPoint)
 53  	if err != nil {
 54  		return nil, err
 55  	}
 56  
 57  	return fs.NewNetDev()
 58  }
 59  
 60  // NewNetDev returns kernel/system statistics read from /proc/net/dev.
 61  func (fs FS) NewNetDev() (NetDev, error) {
 62  	return newNetDev(fs.Path("net/dev"))
 63  }
 64  
 65  // NewNetDev returns kernel/system statistics read from /proc/[pid]/net/dev.
 66  func (p Proc) NewNetDev() (NetDev, error) {
 67  	return newNetDev(p.path("net/dev"))
 68  }
 69  
 70  // newNetDev creates a new NetDev from the contents of the given file.
 71  func newNetDev(file string) (NetDev, error) {
 72  	f, err := os.Open(file)
 73  	if err != nil {
 74  		return NetDev{}, err
 75  	}
 76  	defer f.Close()
 77  
 78  	nd := NetDev{}
 79  	s := bufio.NewScanner(f)
 80  	for n := 0; s.Scan(); n++ {
 81  		// Skip the 2 header lines.
 82  		if n < 2 {
 83  			continue
 84  		}
 85  
 86  		line, err := nd.parseLine(s.Text())
 87  		if err != nil {
 88  			return nd, err
 89  		}
 90  
 91  		nd[line.Name] = *line
 92  	}
 93  
 94  	return nd, s.Err()
 95  }
 96  
 97  // parseLine parses a single line from the /proc/net/dev file. Header lines
 98  // must be filtered prior to calling this method.
 99  func (nd NetDev) parseLine(rawLine string) (*NetDevLine, error) {
100  	parts := strings.SplitN(rawLine, ":", 2)
101  	if len(parts) != 2 {
102  		return nil, errors.New("invalid net/dev line, missing colon")
103  	}
104  	fields := strings.Fields(strings.TrimSpace(parts[1]))
105  
106  	var err error
107  	line := &NetDevLine{}
108  
109  	// Interface Name
110  	line.Name = strings.TrimSpace(parts[0])
111  	if line.Name == "" {
112  		return nil, errors.New("invalid net/dev line, empty interface name")
113  	}
114  
115  	// RX
116  	line.RxBytes, err = strconv.ParseUint(fields[0], 10, 64)
117  	if err != nil {
118  		return nil, err
119  	}
120  	line.RxPackets, err = strconv.ParseUint(fields[1], 10, 64)
121  	if err != nil {
122  		return nil, err
123  	}
124  	line.RxErrors, err = strconv.ParseUint(fields[2], 10, 64)
125  	if err != nil {
126  		return nil, err
127  	}
128  	line.RxDropped, err = strconv.ParseUint(fields[3], 10, 64)
129  	if err != nil {
130  		return nil, err
131  	}
132  	line.RxFIFO, err = strconv.ParseUint(fields[4], 10, 64)
133  	if err != nil {
134  		return nil, err
135  	}
136  	line.RxFrame, err = strconv.ParseUint(fields[5], 10, 64)
137  	if err != nil {
138  		return nil, err
139  	}
140  	line.RxCompressed, err = strconv.ParseUint(fields[6], 10, 64)
141  	if err != nil {
142  		return nil, err
143  	}
144  	line.RxMulticast, err = strconv.ParseUint(fields[7], 10, 64)
145  	if err != nil {
146  		return nil, err
147  	}
148  
149  	// TX
150  	line.TxBytes, err = strconv.ParseUint(fields[8], 10, 64)
151  	if err != nil {
152  		return nil, err
153  	}
154  	line.TxPackets, err = strconv.ParseUint(fields[9], 10, 64)
155  	if err != nil {
156  		return nil, err
157  	}
158  	line.TxErrors, err = strconv.ParseUint(fields[10], 10, 64)
159  	if err != nil {
160  		return nil, err
161  	}
162  	line.TxDropped, err = strconv.ParseUint(fields[11], 10, 64)
163  	if err != nil {
164  		return nil, err
165  	}
166  	line.TxFIFO, err = strconv.ParseUint(fields[12], 10, 64)
167  	if err != nil {
168  		return nil, err
169  	}
170  	line.TxCollisions, err = strconv.ParseUint(fields[13], 10, 64)
171  	if err != nil {
172  		return nil, err
173  	}
174  	line.TxCarrier, err = strconv.ParseUint(fields[14], 10, 64)
175  	if err != nil {
176  		return nil, err
177  	}
178  	line.TxCompressed, err = strconv.ParseUint(fields[15], 10, 64)
179  	if err != nil {
180  		return nil, err
181  	}
182  
183  	return line, nil
184  }
185  
186  // Total aggregates the values across interfaces and returns a new NetDevLine.
187  // The Name field will be a sorted comma separated list of interface names.
188  func (nd NetDev) Total() NetDevLine {
189  	total := NetDevLine{}
190  
191  	names := make([]string, 0, len(nd))
192  	for _, ifc := range nd {
193  		names = append(names, ifc.Name)
194  		total.RxBytes += ifc.RxBytes
195  		total.RxPackets += ifc.RxPackets
196  		total.RxPackets += ifc.RxPackets
197  		total.RxErrors += ifc.RxErrors
198  		total.RxDropped += ifc.RxDropped
199  		total.RxFIFO += ifc.RxFIFO
200  		total.RxFrame += ifc.RxFrame
201  		total.RxCompressed += ifc.RxCompressed
202  		total.RxMulticast += ifc.RxMulticast
203  		total.TxBytes += ifc.TxBytes
204  		total.TxPackets += ifc.TxPackets
205  		total.TxErrors += ifc.TxErrors
206  		total.TxDropped += ifc.TxDropped
207  		total.TxFIFO += ifc.TxFIFO
208  		total.TxCollisions += ifc.TxCollisions
209  		total.TxCarrier += ifc.TxCarrier
210  		total.TxCompressed += ifc.TxCompressed
211  	}
212  	sort.Strings(names)
213  	total.Name = strings.Join(names, ", ")
214  
215  	return total
216  }