VictoriaMetrics/vendor/github.com/prometheus/procfs/proc_status.go

222 lines
5.5 KiB
Go
Raw Normal View History

// 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"
2023-07-07 09:04:32 +02:00
"sort"
"strconv"
"strings"
"github.com/prometheus/procfs/internal/util"
)
// ProcStatus provides status information about the process,
2023-10-02 21:49:16 +02:00
// read from /proc/[pid]/status.
type ProcStatus struct {
// The process ID.
PID int
// The process name.
Name string
// Thread group ID.
TGID int
2023-10-02 21:49:16 +02:00
// List of Pid namespace.
NSpids []uint64
// Peak virtual memory size.
2022-08-02 08:19:38 +02:00
VmPeak uint64 // nolint:revive
// Virtual memory size.
2022-08-02 08:19:38 +02:00
VmSize uint64 // nolint:revive
// Locked memory size.
2022-08-02 08:19:38 +02:00
VmLck uint64 // nolint:revive
// Pinned memory size.
2022-08-02 08:19:38 +02:00
VmPin uint64 // nolint:revive
// Peak resident set size.
2022-08-02 08:19:38 +02:00
VmHWM uint64 // nolint:revive
// Resident set size (sum of RssAnnon RssFile and RssShmem).
2022-08-02 08:19:38 +02:00
VmRSS uint64 // nolint:revive
// Size of resident anonymous memory.
2022-08-02 08:19:38 +02:00
RssAnon uint64 // nolint:revive
// Size of resident file mappings.
2022-08-02 08:19:38 +02:00
RssFile uint64 // nolint:revive
// Size of resident shared memory.
2022-08-02 08:19:38 +02:00
RssShmem uint64 // nolint:revive
// Size of data segments.
2022-08-02 08:19:38 +02:00
VmData uint64 // nolint:revive
// Size of stack segments.
2022-08-02 08:19:38 +02:00
VmStk uint64 // nolint:revive
// Size of text segments.
2022-08-02 08:19:38 +02:00
VmExe uint64 // nolint:revive
// Shared library code size.
2022-08-02 08:19:38 +02:00
VmLib uint64 // nolint:revive
// Page table entries size.
2022-08-02 08:19:38 +02:00
VmPTE uint64 // nolint:revive
// Size of second-level page tables.
2022-08-02 08:19:38 +02:00
VmPMD uint64 // nolint:revive
// Swapped-out virtual memory size by anonymous private.
2022-08-02 08:19:38 +02:00
VmSwap uint64 // nolint:revive
// Size of hugetlb memory portions
HugetlbPages uint64
// Number of voluntary context switches.
VoluntaryCtxtSwitches uint64
// Number of involuntary context switches.
NonVoluntaryCtxtSwitches uint64
// UIDs of the process (Real, effective, saved set, and filesystem UIDs)
UIDs [4]string
// GIDs of the process (Real, effective, saved set, and filesystem GIDs)
GIDs [4]string
2023-07-07 09:04:32 +02:00
// CpusAllowedList: List of cpu cores processes are allowed to run on.
CpusAllowedList []uint64
}
// NewStatus returns the current status information of the process.
func (p Proc) NewStatus() (ProcStatus, error) {
data, err := util.ReadFileNoStat(p.path("status"))
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
2022-12-29 00:00:02 +01:00
k := strings.TrimSpace(kv[0])
v := strings.TrimSpace(kv[1])
// removes "kB"
2022-12-29 00:00:02 +01:00
v = strings.TrimSuffix(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 "Tgid":
s.TGID = int(vUint)
case "Name":
s.Name = vString
case "Uid":
copy(s.UIDs[:], strings.Split(vString, "\t"))
case "Gid":
copy(s.GIDs[:], strings.Split(vString, "\t"))
2023-10-02 21:49:16 +02:00
case "NSpid":
s.NSpids = calcNSPidsList(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
2023-07-07 09:04:32 +02:00
case "Cpus_allowed_list":
s.CpusAllowedList = calcCpusAllowedList(vString)
}
2023-07-07 09:04:32 +02:00
}
// TotalCtxtSwitches returns the total context switch.
func (s ProcStatus) TotalCtxtSwitches() uint64 {
return s.VoluntaryCtxtSwitches + s.NonVoluntaryCtxtSwitches
}
2023-07-07 09:04:32 +02:00
func calcCpusAllowedList(cpuString string) []uint64 {
s := strings.Split(cpuString, ",")
var g []uint64
for _, cpu := range s {
// parse cpu ranges, example: 1-3=[1,2,3]
if l := strings.Split(strings.TrimSpace(cpu), "-"); len(l) > 1 {
startCPU, _ := strconv.ParseUint(l[0], 10, 64)
endCPU, _ := strconv.ParseUint(l[1], 10, 64)
for i := startCPU; i <= endCPU; i++ {
g = append(g, i)
}
} else if len(l) == 1 {
cpu, _ := strconv.ParseUint(l[0], 10, 64)
g = append(g, cpu)
}
}
sort.Slice(g, func(i, j int) bool { return g[i] < g[j] })
return g
}
2023-10-02 21:49:16 +02:00
func calcNSPidsList(nspidsString string) []uint64 {
s := strings.Split(nspidsString, " ")
var nspids []uint64
for _, nspid := range s {
nspid, _ := strconv.ParseUint(nspid, 10, 64)
if nspid == 0 {
continue
}
nspids = append(nspids, nspid)
}
return nspids
}