| // Copyright 2018 The Prometheus Authors |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package procfs |
| |
| import ( |
| "bytes" |
| "io/ioutil" |
| "os" |
| "strconv" |
| "strings" |
| ) |
| |
| // ProcStat provides status information about the process, |
| // read from /proc/[pid]/stat. |
| type ProcStatus struct { |
| // The process ID. |
| PID int |
| // The process name. |
| Name string |
| |
| // Peak virtual memory size. |
| VmPeak uint64 |
| // Virtual memory size. |
| VmSize uint64 |
| // Locked memory size. |
| VmLck uint64 |
| // Pinned memory size. |
| VmPin uint64 |
| // Peak resident set size. |
| VmHWM uint64 |
| // Resident set size (sum of RssAnnon RssFile and RssShmem). |
| VmRSS uint64 |
| // Size of resident anonymous memory. |
| RssAnon uint64 |
| // Size of resident file mappings. |
| RssFile uint64 |
| // Size of resident shared memory. |
| RssShmem uint64 |
| // Size of data segments. |
| VmData uint64 |
| // Size of stack segments. |
| VmStk uint64 |
| // Size of text segments. |
| VmExe uint64 |
| // Shared library code size. |
| VmLib uint64 |
| // Page table entries size. |
| VmPTE uint64 |
| // Size of second-level page tables. |
| VmPMD uint64 |
| // Swapped-out virtual memory size by anonymous private. |
| VmSwap uint64 |
| // Size of hugetlb memory portions |
| HugetlbPages uint64 |
| |
| // Number of voluntary context switches. |
| VoluntaryCtxtSwitches uint64 |
| // Number of involuntary context switches. |
| NonVoluntaryCtxtSwitches uint64 |
| } |
| |
| // NewStatus returns the current status information of the process. |
| func (p Proc) NewStatus() (ProcStatus, error) { |
| f, err := os.Open(p.path("status")) |
| if err != nil { |
| return ProcStatus{}, err |
| } |
| defer f.Close() |
| |
| data, err := ioutil.ReadAll(f) |
| if err != nil { |
| return ProcStatus{}, err |
| } |
| |
| s := ProcStatus{PID: p.PID} |
| |
| lines := strings.Split(string(data), "\n") |
| for _, line := range lines { |
| if !bytes.Contains([]byte(line), []byte(":")) { |
| continue |
| } |
| |
| kv := strings.SplitN(line, ":", 2) |
| |
| // removes spaces |
| k := string(strings.TrimSpace(kv[0])) |
| v := string(strings.TrimSpace(kv[1])) |
| // removes "kB" |
| v = string(bytes.Trim([]byte(v), " kB")) |
| |
| // value to int when possible |
| // we can skip error check here, 'cause vKBytes is not used when value is a string |
| vKBytes, _ := strconv.ParseUint(v, 10, 64) |
| // convert kB to B |
| vBytes := vKBytes * 1024 |
| |
| s.fillStatus(k, v, vKBytes, vBytes) |
| } |
| |
| return s, nil |
| } |
| |
| func (s *ProcStatus) fillStatus(k string, vString string, vUint uint64, vUintBytes uint64) { |
| switch k { |
| case "Name": |
| s.Name = vString |
| case "VmPeak": |
| s.VmPeak = vUintBytes |
| case "VmSize": |
| s.VmSize = vUintBytes |
| case "VmLck": |
| s.VmLck = vUintBytes |
| case "VmPin": |
| s.VmPin = vUintBytes |
| case "VmHWM": |
| s.VmHWM = vUintBytes |
| case "VmRSS": |
| s.VmRSS = vUintBytes |
| case "RssAnon": |
| s.RssAnon = vUintBytes |
| case "RssFile": |
| s.RssFile = vUintBytes |
| case "RssShmem": |
| s.RssShmem = vUintBytes |
| case "VmData": |
| s.VmData = vUintBytes |
| case "VmStk": |
| s.VmStk = vUintBytes |
| case "VmExe": |
| s.VmExe = vUintBytes |
| case "VmLib": |
| s.VmLib = vUintBytes |
| case "VmPTE": |
| s.VmPTE = vUintBytes |
| case "VmPMD": |
| s.VmPMD = vUintBytes |
| case "VmSwap": |
| s.VmSwap = vUintBytes |
| case "HugetlbPages": |
| s.HugetlbPages = vUintBytes |
| case "voluntary_ctxt_switches": |
| s.VoluntaryCtxtSwitches = vUint |
| case "nonvoluntary_ctxt_switches": |
| s.NonVoluntaryCtxtSwitches = vUint |
| } |
| } |
| |
| // TotalCtxtSwitches returns the total context switch. |
| func (s ProcStatus) TotalCtxtSwitches() uint64 { |
| return s.VoluntaryCtxtSwitches + s.NonVoluntaryCtxtSwitches |
| } |