allow to pass context values to override environment variables

pull/1439/head
Antoine Toulme 2 years ago
parent 32e8a92ad6
commit 38b94668ea

@ -96,7 +96,7 @@ func Times(percpu bool) ([]TimesStat, error) {
}
func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
filename := common.HostProc("stat")
filename := common.HostProcWithContext(ctx, "stat")
lines := []string{}
if percpu {
statlines, err := common.ReadLines(filename)
@ -126,17 +126,17 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
return ret, nil
}
func sysCPUPath(cpu int32, relPath string) string {
return common.HostSys(fmt.Sprintf("devices/system/cpu/cpu%d", cpu), relPath)
func sysCPUPath(ctx context.Context, cpu int32, relPath string) string {
return common.HostSysWithContext(ctx, fmt.Sprintf("devices/system/cpu/cpu%d", cpu), relPath)
}
func finishCPUInfo(c *InfoStat) {
func finishCPUInfo(ctx context.Context, c *InfoStat) {
var lines []string
var err error
var value float64
if len(c.CoreID) == 0 {
lines, err = common.ReadLines(sysCPUPath(c.CPU, "topology/core_id"))
lines, err = common.ReadLines(sysCPUPath(ctx, c.CPU, "topology/core_id"))
if err == nil {
c.CoreID = lines[0]
}
@ -145,7 +145,7 @@ func finishCPUInfo(c *InfoStat) {
// override the value of c.Mhz with cpufreq/cpuinfo_max_freq regardless
// of the value from /proc/cpuinfo because we want to report the maximum
// clock-speed of the CPU for c.Mhz, matching the behaviour of Windows
lines, err = common.ReadLines(sysCPUPath(c.CPU, "cpufreq/cpuinfo_max_freq"))
lines, err = common.ReadLines(sysCPUPath(ctx, c.CPU, "cpufreq/cpuinfo_max_freq"))
// if we encounter errors below such as there are no cpuinfo_max_freq file,
// we just ignore. so let Mhz is 0.
if err != nil || len(lines) == 0 {
@ -173,7 +173,7 @@ func Info() ([]InfoStat, error) {
}
func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
filename := common.HostProc("cpuinfo")
filename := common.HostProcWithContext(ctx, "cpuinfo")
lines, _ := common.ReadLines(filename)
var ret []InfoStat
@ -193,7 +193,7 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
processorName = value
case "processor", "cpu number":
if c.CPU >= 0 {
finishCPUInfo(&c)
finishCPUInfo(ctx, &c)
ret = append(ret, c)
}
c = InfoStat{Cores: 1, ModelName: processorName}
@ -301,7 +301,7 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
}
}
if c.CPU >= 0 {
finishCPUInfo(&c)
finishCPUInfo(ctx, &c)
ret = append(ret, c)
}
return ret, nil
@ -390,7 +390,7 @@ func CountsWithContext(ctx context.Context, logical bool) (int, error) {
if logical {
ret := 0
// https://github.com/giampaolo/psutil/blob/d01a9eaa35a8aadf6c519839e987a49d8be2d891/psutil/_pslinux.py#L599
procCpuinfo := common.HostProc("cpuinfo")
procCpuinfo := common.HostProcWithContext(ctx, "cpuinfo")
lines, err := common.ReadLines(procCpuinfo)
if err == nil {
for _, line := range lines {
@ -404,7 +404,7 @@ func CountsWithContext(ctx context.Context, logical bool) (int, error) {
}
}
if ret == 0 {
procStat := common.HostProc("stat")
procStat := common.HostProcWithContext(ctx, "stat")
lines, err = common.ReadLines(procStat)
if err != nil {
return 0, err
@ -425,7 +425,7 @@ func CountsWithContext(ctx context.Context, logical bool) (int, error) {
// https://github.com/giampaolo/psutil/pull/1727#issuecomment-707624964
// https://lkml.org/lkml/2019/2/26/41
for _, glob := range []string{"devices/system/cpu/cpu[0-9]*/topology/core_cpus_list", "devices/system/cpu/cpu[0-9]*/topology/thread_siblings_list"} {
if files, err := filepath.Glob(common.HostSys(glob)); err == nil {
if files, err := filepath.Glob(common.HostSysWithContext(ctx, glob)); err == nil {
for _, file := range files {
lines, err := common.ReadLines(file)
if err != nil || len(lines) != 1 {
@ -440,7 +440,7 @@ func CountsWithContext(ctx context.Context, logical bool) (int, error) {
}
}
// https://github.com/giampaolo/psutil/blob/122174a10b75c9beebe15f6c07dcf3afbe3b120d/psutil/_pslinux.py#L631-L652
filename := common.HostProc("cpuinfo")
filename := common.HostProcWithContext(ctx, "cpuinfo")
lines, err := common.ReadLines(filename)
if err != nil {
return 0, err

@ -260,10 +260,10 @@ func readMountFile(root string) (lines []string, useMounts bool, filename string
func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) {
// by default, try "/proc/1/..." first
root := common.HostProc(path.Join("1"))
root := common.HostProcWithContext(ctx, path.Join("1"))
// force preference for dirname of HOST_PROC_MOUNTINFO, if set #1271
hpmPath := os.Getenv("HOST_PROC_MOUNTINFO")
hpmPath := common.HostProcMountInfoWithContext(ctx)
if hpmPath != "" {
root = filepath.Dir(hpmPath)
}
@ -274,13 +274,13 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
return nil, err
}
// fallback to "/proc/self/..." #1159
lines, useMounts, filename, err = readMountFile(common.HostProc(path.Join("self")))
lines, useMounts, filename, err = readMountFile(common.HostProcWithContext(ctx, path.Join("self")))
if err != nil {
return nil, err
}
}
fs, err := getFileSystems()
fs, err := getFileSystems(ctx)
if err != nil && !all {
return nil, err
}
@ -342,7 +342,7 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
}
if strings.HasPrefix(d.Device, "/dev/mapper/") {
devpath, err := filepath.EvalSymlinks(common.HostDev(strings.Replace(d.Device, "/dev", "", 1)))
devpath, err := filepath.EvalSymlinks(common.HostDevWithContext(ctx, strings.Replace(d.Device, "/dev", "", 1)))
if err == nil {
d.Device = devpath
}
@ -351,7 +351,7 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
// /dev/root is not the real device name
// so we get the real device name from its major/minor number
if d.Device == "/dev/root" {
devpath, err := os.Readlink(common.HostSys("/dev/block/" + blockDeviceID))
devpath, err := os.Readlink(common.HostSysWithContext(ctx, "/dev/block/"+blockDeviceID))
if err == nil {
d.Device = strings.Replace(d.Device, "root", filepath.Base(devpath), 1)
}
@ -364,8 +364,8 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
}
// getFileSystems returns supported filesystems from /proc/filesystems
func getFileSystems() ([]string, error) {
filename := common.HostProc("filesystems")
func getFileSystems(ctx context.Context) ([]string, error) {
filename := common.HostProcWithContext(ctx, "filesystems")
lines, err := common.ReadLines(filename)
if err != nil {
return nil, err
@ -387,7 +387,7 @@ func getFileSystems() ([]string, error) {
}
func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) {
filename := common.HostProc("diskstats")
filename := common.HostProcWithContext(ctx, "diskstats")
lines, err := common.ReadLines(filename)
if err != nil {
return nil, err
@ -492,7 +492,7 @@ func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
minor := unix.Minor(uint64(stat.Rdev))
// Try to get the serial from udev data
udevDataPath := common.HostRun(fmt.Sprintf("udev/data/b%d:%d", major, minor))
udevDataPath := common.HostRunWithContext(ctx, fmt.Sprintf("udev/data/b%d:%d", major, minor))
if udevdata, err := ioutil.ReadFile(udevDataPath); err == nil {
scanner := bufio.NewScanner(bytes.NewReader(udevdata))
for scanner.Scan() {
@ -505,7 +505,7 @@ func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
// Try to get the serial from sysfs, look at the disk device (minor 0) directly
// because if it is a partition it is not going to contain any device information
devicePath := common.HostSys(fmt.Sprintf("dev/block/%d:0/device", major))
devicePath := common.HostSysWithContext(ctx, fmt.Sprintf("dev/block/%d:0/device", major))
model, _ := ioutil.ReadFile(filepath.Join(devicePath, "model"))
serial, _ := ioutil.ReadFile(filepath.Join(devicePath, "serial"))
if len(model) > 0 && len(serial) > 0 {
@ -516,7 +516,7 @@ func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
func LabelWithContext(ctx context.Context, name string) (string, error) {
// Try label based on devicemapper name
dmname_filename := common.HostSys(fmt.Sprintf("block/%s/dm/name", name))
dmname_filename := common.HostSysWithContext(ctx, fmt.Sprintf("block/%s/dm/name", name))
if !common.PathExists(dmname_filename) {
return "", nil

@ -100,7 +100,7 @@ func CgroupCPUUsage(containerID string, base string) (float64, error) {
}
func CgroupCPUWithContext(ctx context.Context, containerID string, base string) (*CgroupCPUStat, error) {
statfile := getCgroupFilePath(containerID, base, "cpuacct", "cpuacct.stat")
statfile := getCgroupFilePath(ctx, containerID, base, "cpuacct", "cpuacct.stat")
lines, err := common.ReadLines(statfile)
if err != nil {
return nil, err
@ -136,7 +136,7 @@ func CgroupCPUWithContext(ctx context.Context, containerID string, base string)
}
func CgroupCPUUsageWithContext(ctx context.Context, containerID, base string) (float64, error) {
usagefile := getCgroupFilePath(containerID, base, "cpuacct", "cpuacct.usage")
usagefile := getCgroupFilePath(ctx, containerID, base, "cpuacct", "cpuacct.usage")
lines, err := common.ReadLinesOffsetN(usagefile, 0, 1)
if err != nil {
return 0.0, err
@ -159,11 +159,11 @@ func CgroupCPUUsageDocker(containerid string) (float64, error) {
}
func CgroupCPUDockerWithContext(ctx context.Context, containerid string) (*CgroupCPUStat, error) {
return CgroupCPUWithContext(ctx, containerid, common.HostSys("fs/cgroup/cpuacct/docker"))
return CgroupCPUWithContext(ctx, containerid, common.HostSysWithContext(ctx, "fs/cgroup/cpuacct/docker"))
}
func CgroupCPUDockerUsageWithContext(ctx context.Context, containerid string) (float64, error) {
return CgroupCPUUsageWithContext(ctx, containerid, common.HostSys("fs/cgroup/cpuacct/docker"))
return CgroupCPUUsageWithContext(ctx, containerid, common.HostSysWithContext(ctx, "fs/cgroup/cpuacct/docker"))
}
func CgroupMem(containerID string, base string) (*CgroupMemStat, error) {
@ -171,7 +171,7 @@ func CgroupMem(containerID string, base string) (*CgroupMemStat, error) {
}
func CgroupMemWithContext(ctx context.Context, containerID string, base string) (*CgroupMemStat, error) {
statfile := getCgroupFilePath(containerID, base, "memory", "memory.stat")
statfile := getCgroupFilePath(ctx, containerID, base, "memory", "memory.stat")
// empty containerID means all cgroup
if len(containerID) == 0 {
@ -246,19 +246,19 @@ func CgroupMemWithContext(ctx context.Context, containerID string, base string)
}
}
r, err := getCgroupMemFile(containerID, base, "memory.usage_in_bytes")
r, err := getCgroupMemFile(ctx, containerID, base, "memory.usage_in_bytes")
if err == nil {
ret.MemUsageInBytes = r
}
r, err = getCgroupMemFile(containerID, base, "memory.max_usage_in_bytes")
r, err = getCgroupMemFile(ctx, containerID, base, "memory.max_usage_in_bytes")
if err == nil {
ret.MemMaxUsageInBytes = r
}
r, err = getCgroupMemFile(containerID, base, "memory.limit_in_bytes")
r, err = getCgroupMemFile(ctx, containerID, base, "memory.limit_in_bytes")
if err == nil {
ret.MemLimitInBytes = r
}
r, err = getCgroupMemFile(containerID, base, "memory.failcnt")
r, err = getCgroupMemFile(ctx, containerID, base, "memory.failcnt")
if err == nil {
ret.MemFailCnt = r
}
@ -271,27 +271,27 @@ func CgroupMemDocker(containerID string) (*CgroupMemStat, error) {
}
func CgroupMemDockerWithContext(ctx context.Context, containerID string) (*CgroupMemStat, error) {
return CgroupMemWithContext(ctx, containerID, common.HostSys("fs/cgroup/memory/docker"))
return CgroupMemWithContext(ctx, containerID, common.HostSysWithContext(ctx, "fs/cgroup/memory/docker"))
}
// getCgroupFilePath constructs file path to get targeted stats file.
func getCgroupFilePath(containerID, base, target, file string) string {
func getCgroupFilePath(ctx context.Context, containerID, base, target, file string) string {
if len(base) == 0 {
base = common.HostSys(fmt.Sprintf("fs/cgroup/%s/docker", target))
base = common.HostSysWithContext(ctx, fmt.Sprintf("fs/cgroup/%s/docker", target))
}
statfile := path.Join(base, containerID, file)
if _, err := os.Stat(statfile); os.IsNotExist(err) {
statfile = path.Join(
common.HostSys(fmt.Sprintf("fs/cgroup/%s/system.slice", target)), "docker-"+containerID+".scope", file)
common.HostSysWithContext(ctx, fmt.Sprintf("fs/cgroup/%s/system.slice", target)), "docker-"+containerID+".scope", file)
}
return statfile
}
// getCgroupMemFile reads a cgroup file and return the contents as uint64.
func getCgroupMemFile(containerID, base, file string) (uint64, error) {
statfile := getCgroupFilePath(containerID, base, "memory", file)
func getCgroupMemFile(ctx context.Context, containerID, base, file string) (uint64, error) {
statfile := getCgroupFilePath(ctx, containerID, base, "memory", file)
lines, err := common.ReadLines(statfile)
if err != nil {
return 0, err

@ -46,7 +46,7 @@ func CgroupCPUDocker(containerid string) (*CgroupCPUStat, error) {
}
func CgroupCPUDockerWithContext(ctx context.Context, containerid string) (*CgroupCPUStat, error) {
return CgroupCPU(containerid, common.HostSys("fs/cgroup/cpuacct/docker"))
return CgroupCPU(containerid, common.HostSysWithContext(ctx, "fs/cgroup/cpuacct/docker"))
}
func CgroupMem(containerid string, base string) (*CgroupMemStat, error) {
@ -62,5 +62,5 @@ func CgroupMemDocker(containerid string) (*CgroupMemStat, error) {
}
func CgroupMemDockerWithContext(ctx context.Context, containerid string) (*CgroupMemStat, error) {
return CgroupMem(containerid, common.HostSys("fs/cgroup/memory/docker"))
return CgroupMem(containerid, common.HostSysWithContext(ctx, "fs/cgroup/memory/docker"))
}

@ -35,9 +35,9 @@ const (
)
func HostIDWithContext(ctx context.Context) (string, error) {
sysProductUUID := common.HostSys("class/dmi/id/product_uuid")
machineID := common.HostEtc("machine-id")
procSysKernelRandomBootID := common.HostProc("sys/kernel/random/boot_id")
sysProductUUID := common.HostSysWithContext(ctx, "class/dmi/id/product_uuid")
machineID := common.HostEtcWithContext(ctx, "machine-id")
procSysKernelRandomBootID := common.HostProcWithContext(ctx, "sys/kernel/random/boot_id")
switch {
// In order to read this file, needs to be supported by kernel/arch and run as root
// so having fallback is important
@ -67,7 +67,7 @@ func HostIDWithContext(ctx context.Context) (string, error) {
}
func numProcs(ctx context.Context) (uint64, error) {
return common.NumProcs()
return common.NumProcsWithContext(ctx)
}
func BootTimeWithContext(ctx context.Context) (uint64, error) {
@ -83,7 +83,7 @@ func UptimeWithContext(ctx context.Context) (uint64, error) {
}
func UsersWithContext(ctx context.Context) ([]UserStat, error) {
utmpfile := common.HostVar("run/utmp")
utmpfile := common.HostVarWithContext(ctx, "run/utmp")
file, err := os.Open(utmpfile)
if err != nil {
@ -124,10 +124,10 @@ func UsersWithContext(ctx context.Context) ([]UserStat, error) {
return ret, nil
}
func getlsbStruct() (*lsbStruct, error) {
func getlsbStruct(ctx context.Context) (*lsbStruct, error) {
ret := &lsbStruct{}
if common.PathExists(common.HostEtc("lsb-release")) {
contents, err := common.ReadLines(common.HostEtc("lsb-release"))
if common.PathExists(common.HostEtcWithContext(ctx, "lsb-release")) {
contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "lsb-release"))
if err != nil {
return ret, err // return empty
}
@ -175,31 +175,31 @@ func getlsbStruct() (*lsbStruct, error) {
}
func PlatformInformationWithContext(ctx context.Context) (platform string, family string, version string, err error) {
lsb, err := getlsbStruct()
lsb, err := getlsbStruct(ctx)
if err != nil {
lsb = &lsbStruct{}
}
if common.PathExistsWithContents(common.HostEtc("oracle-release")) {
if common.PathExistsWithContents(common.HostEtcWithContext(ctx, "oracle-release")) {
platform = "oracle"
contents, err := common.ReadLines(common.HostEtc("oracle-release"))
contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "oracle-release"))
if err == nil {
version = getRedhatishVersion(contents)
}
} else if common.PathExistsWithContents(common.HostEtc("enterprise-release")) {
} else if common.PathExistsWithContents(common.HostEtcWithContext(ctx, "enterprise-release")) {
platform = "oracle"
contents, err := common.ReadLines(common.HostEtc("enterprise-release"))
contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "enterprise-release"))
if err == nil {
version = getRedhatishVersion(contents)
}
} else if common.PathExistsWithContents(common.HostEtc("slackware-version")) {
} else if common.PathExistsWithContents(common.HostEtcWithContext(ctx, "slackware-version")) {
platform = "slackware"
contents, err := common.ReadLines(common.HostEtc("slackware-version"))
contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "slackware-version"))
if err == nil {
version = getSlackwareVersion(contents)
}
} else if common.PathExistsWithContents(common.HostEtc("debian_version")) {
} else if common.PathExistsWithContents(common.HostEtcWithContext(ctx, "debian_version")) {
if lsb.ID == "Ubuntu" {
platform = "ubuntu"
version = lsb.Release
@ -218,53 +218,53 @@ func PlatformInformationWithContext(ctx context.Context) (platform string, famil
} else {
platform = "debian"
}
contents, err := common.ReadLines(common.HostEtc("debian_version"))
contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "debian_version"))
if err == nil && len(contents) > 0 && contents[0] != "" {
version = contents[0]
}
}
} else if common.PathExists(common.HostEtc("neokylin-release")) {
contents, err := common.ReadLines(common.HostEtc("neokylin-release"))
} else if common.PathExists(common.HostEtcWithContext(ctx, "neokylin-release")) {
contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "neokylin-release"))
if err == nil {
version = getRedhatishVersion(contents)
platform = getRedhatishPlatform(contents)
}
} else if common.PathExists(common.HostEtc("redhat-release")) {
contents, err := common.ReadLines(common.HostEtc("redhat-release"))
} else if common.PathExists(common.HostEtcWithContext(ctx, "redhat-release")) {
contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "redhat-release"))
if err == nil {
version = getRedhatishVersion(contents)
platform = getRedhatishPlatform(contents)
}
} else if common.PathExists(common.HostEtc("system-release")) {
contents, err := common.ReadLines(common.HostEtc("system-release"))
} else if common.PathExists(common.HostEtcWithContext(ctx, "system-release")) {
contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "system-release"))
if err == nil {
version = getRedhatishVersion(contents)
platform = getRedhatishPlatform(contents)
}
} else if common.PathExists(common.HostEtc("gentoo-release")) {
} else if common.PathExists(common.HostEtcWithContext(ctx, "gentoo-release")) {
platform = "gentoo"
contents, err := common.ReadLines(common.HostEtc("gentoo-release"))
contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "gentoo-release"))
if err == nil {
version = getRedhatishVersion(contents)
}
} else if common.PathExists(common.HostEtc("SuSE-release")) {
contents, err := common.ReadLines(common.HostEtc("SuSE-release"))
} else if common.PathExists(common.HostEtcWithContext(ctx, "SuSE-release")) {
contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "SuSE-release"))
if err == nil {
version = getSuseVersion(contents)
platform = getSusePlatform(contents)
}
// TODO: slackware detecion
} else if common.PathExists(common.HostEtc("arch-release")) {
} else if common.PathExists(common.HostEtcWithContext(ctx, "arch-release")) {
platform = "arch"
version = lsb.Release
} else if common.PathExists(common.HostEtc("alpine-release")) {
} else if common.PathExists(common.HostEtcWithContext(ctx, "alpine-release")) {
platform = "alpine"
contents, err := common.ReadLines(common.HostEtc("alpine-release"))
contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "alpine-release"))
if err == nil && len(contents) > 0 && contents[0] != "" {
version = contents[0]
}
} else if common.PathExists(common.HostEtc("os-release")) {
p, v, err := common.GetOSRelease()
} else if common.PathExists(common.HostEtcWithContext(ctx, "os-release")) {
p, v, err := common.GetOSReleaseWithContext(ctx)
if err == nil {
platform = p
version = v
@ -390,14 +390,14 @@ func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, err
// Only the temp*_input file provides current temperature
// value in millidegree Celsius as reported by the temperature to the device:
// https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface
if files, err = filepath.Glob(common.HostSys("/class/hwmon/hwmon*/temp*_input")); err != nil {
if files, err = filepath.Glob(common.HostSysWithContext(ctx, "/class/hwmon/hwmon*/temp*_input")); err != nil {
return temperatures, err
}
if len(files) == 0 {
// CentOS has an intermediate /device directory:
// https://github.com/giampaolo/psutil/issues/971
if files, err = filepath.Glob(common.HostSys("/class/hwmon/hwmon*/device/temp*_input")); err != nil {
if files, err = filepath.Glob(common.HostSysWithContext(ctx, "/class/hwmon/hwmon*/device/temp*_input")); err != nil {
return temperatures, err
}
}
@ -405,7 +405,7 @@ func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, err
var warns Warnings
if len(files) == 0 { // handle distributions without hwmon, like raspbian #391, parse legacy thermal_zone files
files, err = filepath.Glob(common.HostSys("/class/thermal/thermal_zone*/"))
files, err = filepath.Glob(common.HostSysWithContext(ctx, "/class/thermal/thermal_zone*/"))
if err != nil {
return temperatures, err
}

@ -32,6 +32,10 @@ var (
ErrTimeout = errors.New("command timed out")
)
type envKey string
var Env = envKey("string")
type Invoker interface {
Command(string, ...string) ([]byte, error)
CommandWithContext(context.Context, string, ...string) ([]byte, error)
@ -321,6 +325,23 @@ func PathExistsWithContents(filename string) bool {
return info.Size() > 4 // at least 4 bytes
}
// GetEnvWithContext retrieves the environment variable key. If it does not exist it returns the default.
// The context may optionally contain a map superseding os.Env.
func GetEnvWithContext(ctx context.Context, key string, dfault string, combineWith ...string) string {
var value string
if env, ok := ctx.Value(Env).(map[string]string); ok {
value = env[key]
}
if value == "" {
value = os.Getenv(key)
}
if value == "" {
value = dfault
}
return combine(value, combineWith)
}
// GetEnv retrieves the environment variable key. If it does not exist it returns the default.
func GetEnv(key string, dfault string, combineWith ...string) string {
value := os.Getenv(key)
@ -328,6 +349,10 @@ func GetEnv(key string, dfault string, combineWith ...string) string {
value = dfault
}
return combine(value, combineWith)
}
func combine(value string, combineWith []string) string {
switch len(combineWith) {
case 0:
return value
@ -341,34 +366,73 @@ func GetEnv(key string, dfault string, combineWith ...string) string {
}
}
// Deprecated: use HostProcWithContext instead
func HostProc(combineWith ...string) string {
return GetEnv("HOST_PROC", "/proc", combineWith...)
}
// Deprecated: use HostSysWithContext instead
func HostSys(combineWith ...string) string {
return GetEnv("HOST_SYS", "/sys", combineWith...)
}
// Deprecated: use HostEtcWithContext instead
func HostEtc(combineWith ...string) string {
return GetEnv("HOST_ETC", "/etc", combineWith...)
}
// Deprecated: use HostVarWithContext instead
func HostVar(combineWith ...string) string {
return GetEnv("HOST_VAR", "/var", combineWith...)
}
// Deprecated: use HostRunWithContext instead
func HostRun(combineWith ...string) string {
return GetEnv("HOST_RUN", "/run", combineWith...)
}
// Deprecated: use HostDevWithContext instead
func HostDev(combineWith ...string) string {
return GetEnv("HOST_DEV", "/dev", combineWith...)
}
// Deprecated: use HostRootWithContext instead
func HostRoot(combineWith ...string) string {
return GetEnv("HOST_ROOT", "/", combineWith...)
}
func HostProcWithContext(ctx context.Context, combineWith ...string) string {
return GetEnvWithContext(ctx, "HOST_PROC", "/proc", combineWith...)
}
func HostProcMountInfoWithContext(ctx context.Context, combineWith ...string) string {
return GetEnvWithContext(ctx, "HOST_PROC_MOUNTINFO", "", combineWith...)
}
func HostSysWithContext(ctx context.Context, combineWith ...string) string {
return GetEnvWithContext(ctx, "HOST_SYS", "/sys", combineWith...)
}
func HostEtcWithContext(ctx context.Context, combineWith ...string) string {
return GetEnvWithContext(ctx, "HOST_ETC", "/etc", combineWith...)
}
func HostVarWithContext(ctx context.Context, combineWith ...string) string {
return GetEnvWithContext(ctx, "HOST_VAR", "/var", combineWith...)
}
func HostRunWithContext(ctx context.Context, combineWith ...string) string {
return GetEnvWithContext(ctx, "HOST_RUN", "/run", combineWith...)
}
func HostDevWithContext(ctx context.Context, combineWith ...string) string {
return GetEnvWithContext(ctx, "HOST_DEV", "/dev", combineWith...)
}
func HostRootWithContext(ctx context.Context, combineWith ...string) string {
return GetEnvWithContext(ctx, "HOST_ROOT", "/", combineWith...)
}
// getSysctrlEnv sets LC_ALL=C in a list of env vars for use when running
// sysctl commands (see DoSysctrl).
func getSysctrlEnv(env []string) []string {

@ -30,8 +30,13 @@ func DoSysctrl(mib string) ([]string, error) {
return values, nil
}
// Deprecated: use NumProcsWithContext instead
func NumProcs() (uint64, error) {
f, err := os.Open(HostProc())
return NumProcsWithContext(context.Background())
}
func NumProcsWithContext(ctx context.Context) (uint64, error) {
f, err := os.Open(HostProcWithContext(ctx))
if err != nil {
return 0, err
}
@ -67,7 +72,7 @@ func BootTimeWithContext(ctx context.Context) (uint64, error) {
statFile = "uptime"
}
filename := HostProc(statFile)
filename := HostProcWithContext(ctx, statFile)
lines, err := ReadLines(filename)
if os.IsPermission(err) {
var info syscall.Sysinfo_t
@ -139,7 +144,7 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
}
cachedVirtMutex.RUnlock()
filename := HostProc("xen")
filename := HostProcWithContext(ctx, "xen")
if PathExists(filename) {
system = "xen"
role = "guest" // assume guest
@ -154,7 +159,7 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
}
}
filename = HostProc("modules")
filename = HostProcWithContext(ctx, "modules")
if PathExists(filename) {
contents, err := ReadLines(filename)
if err == nil {
@ -177,7 +182,7 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
}
}
filename = HostProc("cpuinfo")
filename = HostProcWithContext(ctx, "cpuinfo")
if PathExists(filename) {
contents, err := ReadLines(filename)
if err == nil {
@ -190,7 +195,7 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
}
}
filename = HostProc("bus/pci/devices")
filename = HostProcWithContext(ctx, "bus/pci/devices")
if PathExists(filename) {
contents, err := ReadLines(filename)
if err == nil {
@ -200,7 +205,7 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
}
}
filename = HostProc()
filename = HostProcWithContext(ctx)
if PathExists(filepath.Join(filename, "bc", "0")) {
system = "openvz"
role = "host"
@ -251,15 +256,15 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
}
}
if PathExists(HostEtc("os-release")) {
p, _, err := GetOSRelease()
if PathExists(HostEtcWithContext(ctx, "os-release")) {
p, _, err := GetOSReleaseWithContext(ctx)
if err == nil && p == "coreos" {
system = "rkt" // Is it true?
role = "host"
}
}
if PathExists(HostRoot(".dockerenv")) {
if PathExists(HostRootWithContext(ctx, ".dockerenv")) {
system = "docker"
role = "guest"
}
@ -278,7 +283,11 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
}
func GetOSRelease() (platform string, version string, err error) {
contents, err := ReadLines(HostEtc("os-release"))
return GetOSReleaseWithContext(context.Background())
}
func GetOSReleaseWithContext(ctx context.Context) (platform string, version string, err error) {
contents, err := ReadLines(HostEtcWithContext(ctx, "os-release"))
if err != nil {
return "", "", nil // return empty
}

@ -1,6 +1,7 @@
package common
import (
"context"
"fmt"
"os"
"reflect"
@ -125,7 +126,7 @@ func TestHostEtc(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("windows doesn't have etc")
}
p := HostEtc("mtab")
p := HostEtcWithContext(context.Background(), "mtab")
if p != "/etc/mtab" {
t.Errorf("invalid HostEtc, %s", p)
}
@ -160,3 +161,44 @@ func TestGetSysctrlEnv(t *testing.T) {
t.Errorf("unexpected real result from getSysctrlEnv: %q", env)
}
}
func TestGetEnvDefault(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("windows doesn't have etc")
}
p := HostEtcWithContext(context.Background(), "mtab")
if p != "/etc/mtab" {
t.Errorf("invalid HostEtc, %s", p)
}
}
func TestGetEnvWithNoContext(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("windows doesn't have etc")
}
old := os.Getenv("HOST_ETC")
os.Setenv("HOST_ETC", "/bar")
defer func() {
os.Setenv("HOST_ETC", old)
}()
p := HostEtcWithContext(context.Background(), "mtab")
if p != "/bar/mtab" {
t.Errorf("invalid HostEtc, %s", p)
}
}
func TestGetEnvWithContextOverride(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("windows doesn't have etc")
}
old := os.Getenv("HOST_ETC")
os.Setenv("HOST_ETC", "/bar")
defer func() {
os.Setenv("HOST_ETC", old)
}()
ctx := context.WithValue(context.Background(), Env, map[string]string{"HOST_ETC": "/foo"})
p := HostEtcWithContext(ctx, "mtab")
if p != "/foo/mtab" {
t.Errorf("invalid HostEtc, %s", p)
}
}

@ -18,7 +18,7 @@ func Avg() (*AvgStat, error) {
}
func AvgWithContext(ctx context.Context) (*AvgStat, error) {
stat, err := fileAvgWithContext()
stat, err := fileAvgWithContext(ctx)
if err != nil {
stat, err = sysinfoAvgWithContext()
}
@ -40,8 +40,8 @@ func sysinfoAvgWithContext() (*AvgStat, error) {
}, nil
}
func fileAvgWithContext() (*AvgStat, error) {
values, err := readLoadAvgFromFile()
func fileAvgWithContext(ctx context.Context) (*AvgStat, error) {
values, err := readLoadAvgFromFile(ctx)
if err != nil {
return nil, err
}
@ -75,7 +75,7 @@ func Misc() (*MiscStat, error) {
}
func MiscWithContext(ctx context.Context) (*MiscStat, error) {
filename := common.HostProc("stat")
filename := common.HostProcWithContext(ctx, "stat")
out, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
@ -107,7 +107,7 @@ func MiscWithContext(ctx context.Context) (*MiscStat, error) {
}
procsTotal, err := getProcsTotal()
procsTotal, err := getProcsTotal(ctx)
if err != nil {
return ret, err
}
@ -116,16 +116,16 @@ func MiscWithContext(ctx context.Context) (*MiscStat, error) {
return ret, nil
}
func getProcsTotal() (int64, error) {
values, err := readLoadAvgFromFile()
func getProcsTotal(ctx context.Context) (int64, error) {
values, err := readLoadAvgFromFile(ctx)
if err != nil {
return 0, err
}
return strconv.ParseInt(strings.Split(values[3], "/")[1], 10, 64)
}
func readLoadAvgFromFile() ([]string, error) {
loadavgFilename := common.HostProc("loadavg")
func readLoadAvgFromFile(ctx context.Context) ([]string, error) {
loadavgFilename := common.HostProcWithContext(ctx, "loadavg")
line, err := ioutil.ReadFile(loadavgFilename)
if err != nil {
return nil, err

@ -37,7 +37,7 @@ func VirtualMemory() (*VirtualMemoryStat, error) {
}
func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
vm, _, err := fillFromMeminfoWithContext()
vm, _, err := fillFromMeminfoWithContext(ctx)
if err != nil {
return nil, err
}
@ -49,15 +49,15 @@ func VirtualMemoryEx() (*VirtualMemoryExStat, error) {
}
func VirtualMemoryExWithContext(ctx context.Context) (*VirtualMemoryExStat, error) {
_, vmEx, err := fillFromMeminfoWithContext()
_, vmEx, err := fillFromMeminfoWithContext(ctx)
if err != nil {
return nil, err
}
return vmEx, nil
}
func fillFromMeminfoWithContext() (*VirtualMemoryStat, *VirtualMemoryExStat, error) {
filename := common.HostProc("meminfo")
func fillFromMeminfoWithContext(ctx context.Context) (*VirtualMemoryStat, *VirtualMemoryExStat, error) {
filename := common.HostProcWithContext(ctx, "meminfo")
lines, _ := common.ReadLines(filename)
// flag if MemAvailable is in /proc/meminfo (kernel 3.14+)
@ -318,7 +318,7 @@ func fillFromMeminfoWithContext() (*VirtualMemoryStat, *VirtualMemoryExStat, err
if !memavail {
if activeFile && inactiveFile && sReclaimable {
ret.Available = calculateAvailVmem(ret, retEx)
ret.Available = calculateAvailVmem(ctx, ret, retEx)
} else {
ret.Available = ret.Cached + ret.Free
}
@ -351,7 +351,7 @@ func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
} else {
ret.UsedPercent = 0
}
filename := common.HostProc("vmstat")
filename := common.HostProcWithContext(ctx, "vmstat")
lines, _ := common.ReadLines(filename)
for _, l := range lines {
fields := strings.Fields(l)
@ -403,10 +403,10 @@ func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
// calculateAvailVmem is a fallback under kernel 3.14 where /proc/meminfo does not provide
// "MemAvailable:" column. It reimplements an algorithm from the link below
// https://github.com/giampaolo/psutil/pull/890
func calculateAvailVmem(ret *VirtualMemoryStat, retEx *VirtualMemoryExStat) uint64 {
func calculateAvailVmem(ctx context.Context, ret *VirtualMemoryStat, retEx *VirtualMemoryExStat) uint64 {
var watermarkLow uint64
fn := common.HostProc("zoneinfo")
fn := common.HostProcWithContext(ctx, "zoneinfo")
lines, err := common.ReadLines(fn)
if err != nil {
return ret.Free + ret.Cached // fallback under kernel 2.6.13
@ -458,18 +458,18 @@ func SwapDevices() ([]*SwapDevice, error) {
}
func SwapDevicesWithContext(ctx context.Context) ([]*SwapDevice, error) {
swapsFilePath := common.HostProc(swapsFilename)
swapsFilePath := common.HostProcWithContext(ctx, swapsFilename)
f, err := os.Open(swapsFilePath)
if err != nil {
return nil, err
}
defer f.Close()
return parseSwapsFile(f)
return parseSwapsFile(ctx, f)
}
func parseSwapsFile(r io.Reader) ([]*SwapDevice, error) {
swapsFilePath := common.HostProc(swapsFilename)
func parseSwapsFile(ctx context.Context, r io.Reader) ([]*SwapDevice, error) {
swapsFilePath := common.HostProcWithContext(ctx, swapsFilename)
scanner := bufio.NewScanner(r)
if !scanner.Scan() {
if err := scanner.Err(); err != nil {

@ -4,6 +4,7 @@
package mem
import (
"context"
"path/filepath"
"reflect"
"strings"
@ -138,7 +139,7 @@ const invalidFile = `INVALID Type Size Used Priority
func TestParseSwapsFile_ValidFile(t *testing.T) {
assert := assert.New(t)
stats, err := parseSwapsFile(strings.NewReader(validFile))
stats, err := parseSwapsFile(context.Background(), strings.NewReader(validFile))
assert.NoError(err)
assert.Equal(*stats[0], SwapDevice{
@ -155,11 +156,11 @@ func TestParseSwapsFile_ValidFile(t *testing.T) {
}
func TestParseSwapsFile_InvalidFile(t *testing.T) {
_, err := parseSwapsFile(strings.NewReader(invalidFile))
_, err := parseSwapsFile(context.Background(), strings.NewReader(invalidFile))
assert.Error(t, err)
}
func TestParseSwapsFile_EmptyFile(t *testing.T) {
_, err := parseSwapsFile(strings.NewReader(""))
_, err := parseSwapsFile(context.Background(), strings.NewReader(""))
assert.Error(t, err)
}

@ -50,7 +50,7 @@ func IOCounters(pernic bool) ([]IOCountersStat, error) {
}
func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat, error) {
filename := common.HostProc("net/dev")
filename := common.HostProcWithContext(ctx, "net/dev")
return IOCountersByFileWithContext(ctx, pernic, filename)
}
@ -177,7 +177,7 @@ func ProtoCountersWithContext(ctx context.Context, protocols []string) ([]ProtoC
protos[p] = true
}
filename := common.HostProc("net/snmp")
filename := common.HostProcWithContext(ctx, "net/snmp")
lines, err := common.ReadLines(filename)
if err != nil {
return nil, err
@ -230,8 +230,8 @@ func FilterCounters() ([]FilterStat, error) {
}
func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
countfile := common.HostProc("sys/net/netfilter/nf_conntrack_count")
maxfile := common.HostProc("sys/net/netfilter/nf_conntrack_max")
countfile := common.HostProcWithContext(ctx, "sys/net/netfilter/nf_conntrack_count")
maxfile := common.HostProcWithContext(ctx, "sys/net/netfilter/nf_conntrack_max")
count, err := common.ReadInts(countfile)
if err != nil {
@ -260,7 +260,7 @@ func ConntrackStats(percpu bool) ([]ConntrackStat, error) {
// ConntrackStatsWithContext returns more detailed info about the conntrack table
func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackStat, error) {
return conntrackStatsFromFile(common.HostProc("net/stat/nf_conntrack"), percpu)
return conntrackStatsFromFile(common.HostProcWithContext(ctx, "net/stat/nf_conntrack"), percpu)
}
// conntrackStatsFromFile returns more detailed info about the conntrack table
@ -459,7 +459,7 @@ func connectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, p
if !ok {
return nil, fmt.Errorf("invalid kind, %s", kind)
}
root := common.HostProc()
root := common.HostProcWithContext(ctx)
var err error
var inodes map[string][]inodeMap
if pid == 0 {
@ -531,7 +531,7 @@ func statsFromInodesWithContext(ctx context.Context, root string, pid int32, tma
if !skipUids {
// fetch process owner Real, effective, saved set, and filesystem UIDs
proc := process{Pid: conn.Pid}
conn.Uids, _ = proc.getUids()
conn.Uids, _ = proc.getUids(ctx)
}
ret = append(ret, conn)
@ -599,7 +599,7 @@ func Pids() ([]int32, error) {
func PidsWithContext(ctx context.Context) ([]int32, error) {
var ret []int32
d, err := os.Open(common.HostProc())
d, err := os.Open(common.HostProcWithContext(ctx))
if err != nil {
return nil, err
}
@ -631,8 +631,8 @@ type process struct {
}
// Uids returns user ids of the process as a slice of the int
func (p *process) getUids() ([]int32, error) {
err := p.fillFromStatus()
func (p *process) getUids(ctx context.Context) ([]int32, error) {
err := p.fillFromStatus(ctx)
if err != nil {
return []int32{}, err
}
@ -640,9 +640,9 @@ func (p *process) getUids() ([]int32, error) {
}
// Get status from /proc/(pid)/status
func (p *process) fillFromStatus() error {
func (p *process) fillFromStatus(ctx context.Context) error {
pid := p.Pid
statPath := common.HostProc(strconv.Itoa(int(pid)), "status")
statPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "status")
contents, err := ioutil.ReadFile(statPath)
if err != nil {
return err

@ -1,6 +1,7 @@
package net
import (
"context"
"fmt"
"io/ioutil"
"net"
@ -101,7 +102,7 @@ func TestGetProcInodesAll(t *testing.T) {
}()
<-waitForServer
root := common.HostProc("")
root := common.HostProcWithContext(context.Background(), "")
v, err := getProcInodesAll(root, 0)
assert.Nil(t, err)
assert.NotEmpty(t, v)

@ -101,7 +101,7 @@ func (p *Process) TgidWithContext(ctx context.Context) (int32, error) {
}
func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
return p.fillFromExeWithContext()
return p.fillFromExeWithContext(ctx)
}
func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
@ -121,7 +121,7 @@ func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
}
func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
return p.fillFromCwdWithContext()
return p.fillFromCwdWithContext(ctx)
}
func (p *Process) StatusWithContext(ctx context.Context) ([]string, error) {
@ -135,7 +135,7 @@ func (p *Process) StatusWithContext(ctx context.Context) ([]string, error) {
func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
// see https://github.com/shirou/gopsutil/issues/596#issuecomment-432707831 for implementation details
pid := p.Pid
statPath := common.HostProc(strconv.Itoa(int(pid)), "stat")
statPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "stat")
contents, err := ioutil.ReadFile(statPath)
if err != nil {
return false, err
@ -203,7 +203,7 @@ func (p *Process) RlimitWithContext(ctx context.Context) ([]RlimitStat, error) {
}
func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) ([]RlimitStat, error) {
rlimits, err := p.fillFromLimitsWithContext()
rlimits, err := p.fillFromLimitsWithContext(ctx)
if !gatherUsed || err != nil {
return rlimits, err
}
@ -258,7 +258,7 @@ func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) (
}
func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error) {
return p.fillFromIOWithContext()
return p.fillFromIOWithContext(ctx)
}
func (p *Process) NumCtxSwitchesWithContext(ctx context.Context) (*NumCtxSwitchesStat, error) {
@ -284,7 +284,7 @@ func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesStat, error) {
ret := make(map[int32]*cpu.TimesStat)
taskPath := common.HostProc(strconv.Itoa(int(p.Pid)), "task")
taskPath := common.HostProcWithContext(ctx, strconv.Itoa(int(p.Pid)), "task")
tids, err := readPidsFromDir(taskPath)
if err != nil {
@ -315,7 +315,7 @@ func (p *Process) CPUAffinityWithContext(ctx context.Context) ([]int32, error) {
}
func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) {
meminfo, _, err := p.fillFromStatmWithContext()
meminfo, _, err := p.fillFromStatmWithContext(ctx)
if err != nil {
return nil, err
}
@ -323,7 +323,7 @@ func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, e
}
func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) {
_, memInfoEx, err := p.fillFromStatmWithContext()
_, memInfoEx, err := p.fillFromStatmWithContext(ctx)
if err != nil {
return nil, err
}
@ -381,12 +381,12 @@ func (p *Process) ConnectionsMaxWithContext(ctx context.Context, max int) ([]net
func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]MemoryMapsStat, error) {
pid := p.Pid
var ret []MemoryMapsStat
smapsPath := common.HostProc(strconv.Itoa(int(pid)), "smaps")
smapsPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "smaps")
if grouped {
ret = make([]MemoryMapsStat, 1)
// If smaps_rollup exists (require kernel >= 4.15), then we will use it
// for pre-summed memory information for a process.
smapsRollupPath := common.HostProc(strconv.Itoa(int(pid)), "smaps_rollup")
smapsRollupPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "smaps_rollup")
if _, err := os.Stat(smapsRollupPath); !os.IsNotExist(err) {
smapsPath = smapsRollupPath
}
@ -482,7 +482,7 @@ func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]M
}
func (p *Process) EnvironWithContext(ctx context.Context) ([]string, error) {
environPath := common.HostProc(strconv.Itoa(int(p.Pid)), "environ")
environPath := common.HostProcWithContext(ctx, strconv.Itoa(int(p.Pid)), "environ")
environContent, err := ioutil.ReadFile(environPath)
if err != nil {
@ -508,9 +508,9 @@ func limitToUint(val string) (uint64, error) {
}
// Get num_fds from /proc/(pid)/limits
func (p *Process) fillFromLimitsWithContext() ([]RlimitStat, error) {
func (p *Process) fillFromLimitsWithContext(ctx context.Context) ([]RlimitStat, error) {
pid := p.Pid
limitsFile := common.HostProc(strconv.Itoa(int(pid)), "limits")
limitsFile := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "limits")
d, err := os.Open(limitsFile)
if err != nil {
return nil, err
@ -603,7 +603,7 @@ func (p *Process) fillFromLimitsWithContext() ([]RlimitStat, error) {
// Get list of /proc/(pid)/fd files
func (p *Process) fillFromfdListWithContext(ctx context.Context) (string, []string, error) {
pid := p.Pid
statPath := common.HostProc(strconv.Itoa(int(pid)), "fd")
statPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "fd")
d, err := os.Open(statPath)
if err != nil {
return statPath, []string{}, err
@ -643,9 +643,9 @@ func (p *Process) fillFromfdWithContext(ctx context.Context) (int32, []*OpenFile
}
// Get cwd from /proc/(pid)/cwd
func (p *Process) fillFromCwdWithContext() (string, error) {
func (p *Process) fillFromCwdWithContext(ctx context.Context) (string, error) {
pid := p.Pid
cwdPath := common.HostProc(strconv.Itoa(int(pid)), "cwd")
cwdPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "cwd")
cwd, err := os.Readlink(cwdPath)
if err != nil {
return "", err
@ -654,9 +654,9 @@ func (p *Process) fillFromCwdWithContext() (string, error) {
}
// Get exe from /proc/(pid)/exe
func (p *Process) fillFromExeWithContext() (string, error) {
func (p *Process) fillFromExeWithContext(ctx context.Context) (string, error) {
pid := p.Pid
exePath := common.HostProc(strconv.Itoa(int(pid)), "exe")
exePath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "exe")
exe, err := os.Readlink(exePath)
if err != nil {
return "", err
@ -667,7 +667,7 @@ func (p *Process) fillFromExeWithContext() (string, error) {
// Get cmdline from /proc/(pid)/cmdline
func (p *Process) fillFromCmdlineWithContext(ctx context.Context) (string, error) {
pid := p.Pid
cmdPath := common.HostProc(strconv.Itoa(int(pid)), "cmdline")
cmdPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "cmdline")
cmdline, err := ioutil.ReadFile(cmdPath)
if err != nil {
return "", err
@ -681,7 +681,7 @@ func (p *Process) fillFromCmdlineWithContext(ctx context.Context) (string, error
func (p *Process) fillSliceFromCmdlineWithContext(ctx context.Context) ([]string, error) {
pid := p.Pid
cmdPath := common.HostProc(strconv.Itoa(int(pid)), "cmdline")
cmdPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "cmdline")
cmdline, err := ioutil.ReadFile(cmdPath)
if err != nil {
return nil, err
@ -702,9 +702,9 @@ func (p *Process) fillSliceFromCmdlineWithContext(ctx context.Context) ([]string
}
// Get IO status from /proc/(pid)/io
func (p *Process) fillFromIOWithContext() (*IOCountersStat, error) {
func (p *Process) fillFromIOWithContext(ctx context.Context) (*IOCountersStat, error) {
pid := p.Pid
ioPath := common.HostProc(strconv.Itoa(int(pid)), "io")
ioPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "io")
ioline, err := ioutil.ReadFile(ioPath)
if err != nil {
return nil, err
@ -738,9 +738,9 @@ func (p *Process) fillFromIOWithContext() (*IOCountersStat, error) {
}
// Get memory info from /proc/(pid)/statm
func (p *Process) fillFromStatmWithContext() (*MemoryInfoStat, *MemoryInfoExStat, error) {
func (p *Process) fillFromStatmWithContext(ctx context.Context) (*MemoryInfoStat, *MemoryInfoExStat, error) {
pid := p.Pid
memPath := common.HostProc(strconv.Itoa(int(pid)), "statm")
memPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "statm")
contents, err := ioutil.ReadFile(memPath)
if err != nil {
return nil, nil, err
@ -791,7 +791,7 @@ func (p *Process) fillFromStatmWithContext() (*MemoryInfoStat, *MemoryInfoExStat
// Get name from /proc/(pid)/comm or /proc/(pid)/status
func (p *Process) fillNameWithContext(ctx context.Context) error {
err := p.fillFromCommWithContext()
err := p.fillFromCommWithContext(ctx)
if err == nil && p.name != "" && len(p.name) < 15 {
return nil
}
@ -799,9 +799,9 @@ func (p *Process) fillNameWithContext(ctx context.Context) error {
}
// Get name from /proc/(pid)/comm
func (p *Process) fillFromCommWithContext() error {
func (p *Process) fillFromCommWithContext(ctx context.Context) error {
pid := p.Pid
statPath := common.HostProc(strconv.Itoa(int(pid)), "comm")
statPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "comm")
contents, err := ioutil.ReadFile(statPath)
if err != nil {
return err
@ -818,7 +818,7 @@ func (p *Process) fillFromStatus() error {
func (p *Process) fillFromStatusWithContext(ctx context.Context) error {
pid := p.Pid
statPath := common.HostProc(strconv.Itoa(int(pid)), "status")
statPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "status")
contents, err := ioutil.ReadFile(statPath)
if err != nil {
return err
@ -1023,9 +1023,9 @@ func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (ui
var statPath string
if tid == -1 {
statPath = common.HostProc(strconv.Itoa(int(pid)), "stat")
statPath = common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "stat")
} else {
statPath = common.HostProc(strconv.Itoa(int(pid)), "task", strconv.Itoa(int(tid)), "stat")
statPath = common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "task", strconv.Itoa(int(tid)), "stat")
}
contents, err := ioutil.ReadFile(statPath)
@ -1129,7 +1129,7 @@ func (p *Process) fillFromStatWithContext(ctx context.Context) (uint64, int32, *
}
func pidsWithContext(ctx context.Context) ([]int32, error) {
return readPidsFromDir(common.HostProc())
return readPidsFromDir(common.HostProcWithContext(ctx))
}
func ProcessesWithContext(ctx context.Context) ([]*Process, error) {

@ -4,6 +4,7 @@
package process
import (
"context"
"fmt"
"io/ioutil"
"os"
@ -107,7 +108,7 @@ func Test_fillFromCommWithContext(t *testing.T) {
continue
}
p, _ := NewProcess(int32(pid))
if err := p.fillFromCommWithContext(); err != nil {
if err := p.fillFromCommWithContext(context.Background()); err != nil {
t.Error(err)
}
}
@ -139,7 +140,7 @@ func Benchmark_fillFromCommWithContext(b *testing.B) {
pid := 1060
p, _ := NewProcess(int32(pid))
for i := 0; i < b.N; i++ {
p.fillFromCommWithContext()
p.fillFromCommWithContext(context.Background())
}
}

@ -109,8 +109,8 @@ func PidExistsWithContext(ctx context.Context, pid int32) (bool, error) {
return false, err
}
if isMount(common.HostProc()) { // if /<HOST_PROC>/proc exists and is mounted, check if /<HOST_PROC>/proc/<PID> folder exists
_, err := os.Stat(common.HostProc(strconv.Itoa(int(pid))))
if isMount(common.HostProcWithContext(ctx)) { // if /<HOST_PROC>/proc exists and is mounted, check if /<HOST_PROC>/proc/<PID> folder exists
_, err := os.Stat(common.HostProcWithContext(ctx, strconv.Itoa(int(pid))))
if os.IsNotExist(err) {
return false, nil
}

@ -30,7 +30,7 @@ type MemoryMapsStat struct {
type MemoryInfoExStat struct{}
func pidsWithContext(ctx context.Context) ([]int32, error) {
return readPidsFromDir(common.HostProc())
return readPidsFromDir(common.HostProcWithContext(ctx))
}
func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
@ -199,7 +199,7 @@ func (p *Process) EnvironWithContext(ctx context.Context) ([]string, error) {
func (p *Process) fillFromfdListWithContext(ctx context.Context) (string, []string, error) {
pid := p.Pid
statPath := common.HostProc(strconv.Itoa(int(pid)), "fd")
statPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "fd")
d, err := os.Open(statPath)
if err != nil {
return statPath, []string{}, err
@ -211,7 +211,7 @@ func (p *Process) fillFromfdListWithContext(ctx context.Context) (string, []stri
func (p *Process) fillFromPathCwdWithContext(ctx context.Context) (string, error) {
pid := p.Pid
cwdPath := common.HostProc(strconv.Itoa(int(pid)), "path", "cwd")
cwdPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "path", "cwd")
cwd, err := os.Readlink(cwdPath)
if err != nil {
return "", err
@ -221,7 +221,7 @@ func (p *Process) fillFromPathCwdWithContext(ctx context.Context) (string, error
func (p *Process) fillFromPathAOutWithContext(ctx context.Context) (string, error) {
pid := p.Pid
cwdPath := common.HostProc(strconv.Itoa(int(pid)), "path", "a.out")
cwdPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "path", "a.out")
exe, err := os.Readlink(cwdPath)
if err != nil {
return "", err
@ -231,7 +231,7 @@ func (p *Process) fillFromPathAOutWithContext(ctx context.Context) (string, erro
func (p *Process) fillFromExecnameWithContext(ctx context.Context) (string, error) {
pid := p.Pid
execNamePath := common.HostProc(strconv.Itoa(int(pid)), "execname")
execNamePath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "execname")
exe, err := ioutil.ReadFile(execNamePath)
if err != nil {
return "", err
@ -241,7 +241,7 @@ func (p *Process) fillFromExecnameWithContext(ctx context.Context) (string, erro
func (p *Process) fillFromCmdlineWithContext(ctx context.Context) (string, error) {
pid := p.Pid
cmdPath := common.HostProc(strconv.Itoa(int(pid)), "cmdline")
cmdPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "cmdline")
cmdline, err := ioutil.ReadFile(cmdPath)
if err != nil {
return "", err
@ -258,7 +258,7 @@ func (p *Process) fillFromCmdlineWithContext(ctx context.Context) (string, error
func (p *Process) fillSliceFromCmdlineWithContext(ctx context.Context) ([]string, error) {
pid := p.Pid
cmdPath := common.HostProc(strconv.Itoa(int(pid)), "cmdline")
cmdPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "cmdline")
cmdline, err := ioutil.ReadFile(cmdPath)
if err != nil {
return nil, err

Loading…
Cancel
Save