proc_status.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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. "bytes"
  16. "sort"
  17. "strconv"
  18. "strings"
  19. "github.com/prometheus/procfs/internal/util"
  20. )
  21. // ProcStatus provides status information about the process,
  22. // read from /proc/[pid]/stat.
  23. type ProcStatus struct {
  24. // The process ID.
  25. PID int
  26. // The process name.
  27. Name string
  28. // Thread group ID.
  29. TGID int
  30. // Peak virtual memory size.
  31. VmPeak uint64 // nolint:revive
  32. // Virtual memory size.
  33. VmSize uint64 // nolint:revive
  34. // Locked memory size.
  35. VmLck uint64 // nolint:revive
  36. // Pinned memory size.
  37. VmPin uint64 // nolint:revive
  38. // Peak resident set size.
  39. VmHWM uint64 // nolint:revive
  40. // Resident set size (sum of RssAnnon RssFile and RssShmem).
  41. VmRSS uint64 // nolint:revive
  42. // Size of resident anonymous memory.
  43. RssAnon uint64 // nolint:revive
  44. // Size of resident file mappings.
  45. RssFile uint64 // nolint:revive
  46. // Size of resident shared memory.
  47. RssShmem uint64 // nolint:revive
  48. // Size of data segments.
  49. VmData uint64 // nolint:revive
  50. // Size of stack segments.
  51. VmStk uint64 // nolint:revive
  52. // Size of text segments.
  53. VmExe uint64 // nolint:revive
  54. // Shared library code size.
  55. VmLib uint64 // nolint:revive
  56. // Page table entries size.
  57. VmPTE uint64 // nolint:revive
  58. // Size of second-level page tables.
  59. VmPMD uint64 // nolint:revive
  60. // Swapped-out virtual memory size by anonymous private.
  61. VmSwap uint64 // nolint:revive
  62. // Size of hugetlb memory portions
  63. HugetlbPages uint64
  64. // Number of voluntary context switches.
  65. VoluntaryCtxtSwitches uint64
  66. // Number of involuntary context switches.
  67. NonVoluntaryCtxtSwitches uint64
  68. // UIDs of the process (Real, effective, saved set, and filesystem UIDs)
  69. UIDs [4]string
  70. // GIDs of the process (Real, effective, saved set, and filesystem GIDs)
  71. GIDs [4]string
  72. // CpusAllowedList: List of cpu cores processes are allowed to run on.
  73. CpusAllowedList []uint64
  74. }
  75. // NewStatus returns the current status information of the process.
  76. func (p Proc) NewStatus() (ProcStatus, error) {
  77. data, err := util.ReadFileNoStat(p.path("status"))
  78. if err != nil {
  79. return ProcStatus{}, err
  80. }
  81. s := ProcStatus{PID: p.PID}
  82. lines := strings.Split(string(data), "\n")
  83. for _, line := range lines {
  84. if !bytes.Contains([]byte(line), []byte(":")) {
  85. continue
  86. }
  87. kv := strings.SplitN(line, ":", 2)
  88. // removes spaces
  89. k := strings.TrimSpace(kv[0])
  90. v := strings.TrimSpace(kv[1])
  91. // removes "kB"
  92. v = strings.TrimSuffix(v, " kB")
  93. // value to int when possible
  94. // we can skip error check here, 'cause vKBytes is not used when value is a string
  95. vKBytes, _ := strconv.ParseUint(v, 10, 64)
  96. // convert kB to B
  97. vBytes := vKBytes * 1024
  98. s.fillStatus(k, v, vKBytes, vBytes)
  99. }
  100. return s, nil
  101. }
  102. func (s *ProcStatus) fillStatus(k string, vString string, vUint uint64, vUintBytes uint64) {
  103. switch k {
  104. case "Tgid":
  105. s.TGID = int(vUint)
  106. case "Name":
  107. s.Name = vString
  108. case "Uid":
  109. copy(s.UIDs[:], strings.Split(vString, "\t"))
  110. case "Gid":
  111. copy(s.GIDs[:], strings.Split(vString, "\t"))
  112. case "VmPeak":
  113. s.VmPeak = vUintBytes
  114. case "VmSize":
  115. s.VmSize = vUintBytes
  116. case "VmLck":
  117. s.VmLck = vUintBytes
  118. case "VmPin":
  119. s.VmPin = vUintBytes
  120. case "VmHWM":
  121. s.VmHWM = vUintBytes
  122. case "VmRSS":
  123. s.VmRSS = vUintBytes
  124. case "RssAnon":
  125. s.RssAnon = vUintBytes
  126. case "RssFile":
  127. s.RssFile = vUintBytes
  128. case "RssShmem":
  129. s.RssShmem = vUintBytes
  130. case "VmData":
  131. s.VmData = vUintBytes
  132. case "VmStk":
  133. s.VmStk = vUintBytes
  134. case "VmExe":
  135. s.VmExe = vUintBytes
  136. case "VmLib":
  137. s.VmLib = vUintBytes
  138. case "VmPTE":
  139. s.VmPTE = vUintBytes
  140. case "VmPMD":
  141. s.VmPMD = vUintBytes
  142. case "VmSwap":
  143. s.VmSwap = vUintBytes
  144. case "HugetlbPages":
  145. s.HugetlbPages = vUintBytes
  146. case "voluntary_ctxt_switches":
  147. s.VoluntaryCtxtSwitches = vUint
  148. case "nonvoluntary_ctxt_switches":
  149. s.NonVoluntaryCtxtSwitches = vUint
  150. case "Cpus_allowed_list":
  151. s.CpusAllowedList = calcCpusAllowedList(vString)
  152. }
  153. }
  154. // TotalCtxtSwitches returns the total context switch.
  155. func (s ProcStatus) TotalCtxtSwitches() uint64 {
  156. return s.VoluntaryCtxtSwitches + s.NonVoluntaryCtxtSwitches
  157. }
  158. func calcCpusAllowedList(cpuString string) []uint64 {
  159. s := strings.Split(cpuString, ",")
  160. var g []uint64
  161. for _, cpu := range s {
  162. // parse cpu ranges, example: 1-3=[1,2,3]
  163. if l := strings.Split(strings.TrimSpace(cpu), "-"); len(l) > 1 {
  164. startCPU, _ := strconv.ParseUint(l[0], 10, 64)
  165. endCPU, _ := strconv.ParseUint(l[1], 10, 64)
  166. for i := startCPU; i <= endCPU; i++ {
  167. g = append(g, i)
  168. }
  169. } else if len(l) == 1 {
  170. cpu, _ := strconv.ParseUint(l[0], 10, 64)
  171. g = append(g, cpu)
  172. }
  173. }
  174. sort.Slice(g, func(i, j int) bool { return g[i] < g[j] })
  175. return g
  176. }