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.
 
 

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