net_dev.go 6.4 KB

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