本站源代码
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.

92 lines
2.8KB

  1. // Copyright 2019 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. "fmt"
  16. "io/ioutil"
  17. "strconv"
  18. "strings"
  19. )
  20. // For the proc file format details,
  21. // see https://elixir.bootlin.com/linux/v4.17/source/net/core/net-procfs.c#L162
  22. // and https://elixir.bootlin.com/linux/v4.17/source/include/linux/netdevice.h#L2810.
  23. // SoftnetEntry contains a single row of data from /proc/net/softnet_stat
  24. type SoftnetEntry struct {
  25. // Number of processed packets
  26. Processed uint
  27. // Number of dropped packets
  28. Dropped uint
  29. // Number of times processing packets ran out of quota
  30. TimeSqueezed uint
  31. }
  32. // GatherSoftnetStats reads /proc/net/softnet_stat, parse the relevant columns,
  33. // and then return a slice of SoftnetEntry's.
  34. func (fs FS) GatherSoftnetStats() ([]SoftnetEntry, error) {
  35. data, err := ioutil.ReadFile(fs.proc.Path("net/softnet_stat"))
  36. if err != nil {
  37. return nil, fmt.Errorf("error reading softnet %s: %s", fs.proc.Path("net/softnet_stat"), err)
  38. }
  39. return parseSoftnetEntries(data)
  40. }
  41. func parseSoftnetEntries(data []byte) ([]SoftnetEntry, error) {
  42. lines := strings.Split(string(data), "\n")
  43. entries := make([]SoftnetEntry, 0)
  44. var err error
  45. const (
  46. expectedColumns = 11
  47. )
  48. for _, line := range lines {
  49. columns := strings.Fields(line)
  50. width := len(columns)
  51. if width == 0 {
  52. continue
  53. }
  54. if width != expectedColumns {
  55. return []SoftnetEntry{}, fmt.Errorf("%d columns were detected, but %d were expected", width, expectedColumns)
  56. }
  57. var entry SoftnetEntry
  58. if entry, err = parseSoftnetEntry(columns); err != nil {
  59. return []SoftnetEntry{}, err
  60. }
  61. entries = append(entries, entry)
  62. }
  63. return entries, nil
  64. }
  65. func parseSoftnetEntry(columns []string) (SoftnetEntry, error) {
  66. var err error
  67. var processed, dropped, timeSqueezed uint64
  68. if processed, err = strconv.ParseUint(columns[0], 16, 32); err != nil {
  69. return SoftnetEntry{}, fmt.Errorf("Unable to parse column 0: %s", err)
  70. }
  71. if dropped, err = strconv.ParseUint(columns[1], 16, 32); err != nil {
  72. return SoftnetEntry{}, fmt.Errorf("Unable to parse column 1: %s", err)
  73. }
  74. if timeSqueezed, err = strconv.ParseUint(columns[2], 16, 32); err != nil {
  75. return SoftnetEntry{}, fmt.Errorf("Unable to parse column 2: %s", err)
  76. }
  77. return SoftnetEntry{
  78. Processed: uint(processed),
  79. Dropped: uint(dropped),
  80. TimeSqueezed: uint(timeSqueezed),
  81. }, nil
  82. }
上海开阖软件有限公司 沪ICP备12045867号-1