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.
 
 

197 regels
6.2 KiB

  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. //go:build !windows
  14. // +build !windows
  15. package procfs
  16. import (
  17. "bytes"
  18. "fmt"
  19. "os"
  20. "regexp"
  21. "strings"
  22. "github.com/prometheus/procfs/internal/util"
  23. )
  24. // Zoneinfo holds info parsed from /proc/zoneinfo.
  25. type Zoneinfo struct {
  26. Node string
  27. Zone string
  28. NrFreePages *int64
  29. Min *int64
  30. Low *int64
  31. High *int64
  32. Scanned *int64
  33. Spanned *int64
  34. Present *int64
  35. Managed *int64
  36. NrActiveAnon *int64
  37. NrInactiveAnon *int64
  38. NrIsolatedAnon *int64
  39. NrAnonPages *int64
  40. NrAnonTransparentHugepages *int64
  41. NrActiveFile *int64
  42. NrInactiveFile *int64
  43. NrIsolatedFile *int64
  44. NrFilePages *int64
  45. NrSlabReclaimable *int64
  46. NrSlabUnreclaimable *int64
  47. NrMlockStack *int64
  48. NrKernelStack *int64
  49. NrMapped *int64
  50. NrDirty *int64
  51. NrWriteback *int64
  52. NrUnevictable *int64
  53. NrShmem *int64
  54. NrDirtied *int64
  55. NrWritten *int64
  56. NumaHit *int64
  57. NumaMiss *int64
  58. NumaForeign *int64
  59. NumaInterleave *int64
  60. NumaLocal *int64
  61. NumaOther *int64
  62. Protection []*int64
  63. }
  64. var nodeZoneRE = regexp.MustCompile(`(\d+), zone\s+(\w+)`)
  65. // Zoneinfo parses an zoneinfo-file (/proc/zoneinfo) and returns a slice of
  66. // structs containing the relevant info. More information available here:
  67. // https://www.kernel.org/doc/Documentation/sysctl/vm.txt
  68. func (fs FS) Zoneinfo() ([]Zoneinfo, error) {
  69. data, err := os.ReadFile(fs.proc.Path("zoneinfo"))
  70. if err != nil {
  71. return nil, fmt.Errorf("error reading zoneinfo %q: %w", fs.proc.Path("zoneinfo"), err)
  72. }
  73. zoneinfo, err := parseZoneinfo(data)
  74. if err != nil {
  75. return nil, fmt.Errorf("error parsing zoneinfo %q: %w", fs.proc.Path("zoneinfo"), err)
  76. }
  77. return zoneinfo, nil
  78. }
  79. func parseZoneinfo(zoneinfoData []byte) ([]Zoneinfo, error) {
  80. zoneinfo := []Zoneinfo{}
  81. zoneinfoBlocks := bytes.Split(zoneinfoData, []byte("\nNode"))
  82. for _, block := range zoneinfoBlocks {
  83. var zoneinfoElement Zoneinfo
  84. lines := strings.Split(string(block), "\n")
  85. for _, line := range lines {
  86. if nodeZone := nodeZoneRE.FindStringSubmatch(line); nodeZone != nil {
  87. zoneinfoElement.Node = nodeZone[1]
  88. zoneinfoElement.Zone = nodeZone[2]
  89. continue
  90. }
  91. if strings.HasPrefix(strings.TrimSpace(line), "per-node stats") {
  92. continue
  93. }
  94. parts := strings.Fields(strings.TrimSpace(line))
  95. if len(parts) < 2 {
  96. continue
  97. }
  98. vp := util.NewValueParser(parts[1])
  99. switch parts[0] {
  100. case "nr_free_pages":
  101. zoneinfoElement.NrFreePages = vp.PInt64()
  102. case "min":
  103. zoneinfoElement.Min = vp.PInt64()
  104. case "low":
  105. zoneinfoElement.Low = vp.PInt64()
  106. case "high":
  107. zoneinfoElement.High = vp.PInt64()
  108. case "scanned":
  109. zoneinfoElement.Scanned = vp.PInt64()
  110. case "spanned":
  111. zoneinfoElement.Spanned = vp.PInt64()
  112. case "present":
  113. zoneinfoElement.Present = vp.PInt64()
  114. case "managed":
  115. zoneinfoElement.Managed = vp.PInt64()
  116. case "nr_active_anon":
  117. zoneinfoElement.NrActiveAnon = vp.PInt64()
  118. case "nr_inactive_anon":
  119. zoneinfoElement.NrInactiveAnon = vp.PInt64()
  120. case "nr_isolated_anon":
  121. zoneinfoElement.NrIsolatedAnon = vp.PInt64()
  122. case "nr_anon_pages":
  123. zoneinfoElement.NrAnonPages = vp.PInt64()
  124. case "nr_anon_transparent_hugepages":
  125. zoneinfoElement.NrAnonTransparentHugepages = vp.PInt64()
  126. case "nr_active_file":
  127. zoneinfoElement.NrActiveFile = vp.PInt64()
  128. case "nr_inactive_file":
  129. zoneinfoElement.NrInactiveFile = vp.PInt64()
  130. case "nr_isolated_file":
  131. zoneinfoElement.NrIsolatedFile = vp.PInt64()
  132. case "nr_file_pages":
  133. zoneinfoElement.NrFilePages = vp.PInt64()
  134. case "nr_slab_reclaimable":
  135. zoneinfoElement.NrSlabReclaimable = vp.PInt64()
  136. case "nr_slab_unreclaimable":
  137. zoneinfoElement.NrSlabUnreclaimable = vp.PInt64()
  138. case "nr_mlock_stack":
  139. zoneinfoElement.NrMlockStack = vp.PInt64()
  140. case "nr_kernel_stack":
  141. zoneinfoElement.NrKernelStack = vp.PInt64()
  142. case "nr_mapped":
  143. zoneinfoElement.NrMapped = vp.PInt64()
  144. case "nr_dirty":
  145. zoneinfoElement.NrDirty = vp.PInt64()
  146. case "nr_writeback":
  147. zoneinfoElement.NrWriteback = vp.PInt64()
  148. case "nr_unevictable":
  149. zoneinfoElement.NrUnevictable = vp.PInt64()
  150. case "nr_shmem":
  151. zoneinfoElement.NrShmem = vp.PInt64()
  152. case "nr_dirtied":
  153. zoneinfoElement.NrDirtied = vp.PInt64()
  154. case "nr_written":
  155. zoneinfoElement.NrWritten = vp.PInt64()
  156. case "numa_hit":
  157. zoneinfoElement.NumaHit = vp.PInt64()
  158. case "numa_miss":
  159. zoneinfoElement.NumaMiss = vp.PInt64()
  160. case "numa_foreign":
  161. zoneinfoElement.NumaForeign = vp.PInt64()
  162. case "numa_interleave":
  163. zoneinfoElement.NumaInterleave = vp.PInt64()
  164. case "numa_local":
  165. zoneinfoElement.NumaLocal = vp.PInt64()
  166. case "numa_other":
  167. zoneinfoElement.NumaOther = vp.PInt64()
  168. case "protection:":
  169. protectionParts := strings.Split(line, ":")
  170. protectionValues := strings.Replace(protectionParts[1], "(", "", 1)
  171. protectionValues = strings.Replace(protectionValues, ")", "", 1)
  172. protectionValues = strings.TrimSpace(protectionValues)
  173. protectionStringMap := strings.Split(protectionValues, ", ")
  174. val, err := util.ParsePInt64s(protectionStringMap)
  175. if err == nil {
  176. zoneinfoElement.Protection = val
  177. }
  178. }
  179. }
  180. zoneinfo = append(zoneinfo, zoneinfoElement)
  181. }
  182. return zoneinfo, nil
  183. }