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