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