You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

216 lines
6.6 KiB

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