Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow to pass context values to override environment variables #1439

Merged
merged 8 commits into from
Jun 4, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions common/env.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package common

type EnvKeyType string

// EnvKey is a context key that can be used to set programmatically the environment
// gopsutil relies on to perform calls against the OS.
// Example of use:
//
// ctx := context.WithValue(context.Background(), common.EnvKey, EnvMap{common.HostProcEnvKey: "/myproc"})
// avg, err := load.AvgWithContext(ctx)
var EnvKey = EnvKeyType("env")

const (
HostProcEnvKey EnvKeyType = "HOST_PROC"
HostSysEnvKey EnvKeyType = "HOST_SYS"
HostEtcEnvKey EnvKeyType = "HOST_ETC"
HostVarEnvKey EnvKeyType = "HOST_VAR"
HostRunEnvKey EnvKeyType = "HOST_RUN"
HostDevEnvKey EnvKeyType = "HOST_DEV"
HostRootEnvKey EnvKeyType = "HOST_ROOT"
)

type EnvMap map[EnvKeyType]string
26 changes: 13 additions & 13 deletions cpu/cpu_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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]
}
Expand All @@ -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 {
Expand Down Expand Up @@ -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
Expand All @@ -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}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand All @@ -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
Expand All @@ -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 {
Expand All @@ -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
Expand Down
24 changes: 12 additions & 12 deletions disk/disk_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand All @@ -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
}
Expand Down Expand Up @@ -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
}
Expand All @@ -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)
}
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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() {
Expand All @@ -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 {
Expand All @@ -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
Expand Down
30 changes: 15 additions & 15 deletions docker/docker_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -159,19 +159,19 @@ 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) {
return CgroupMemWithContext(context.Background(), containerID, base)
}

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 {
Expand Down Expand Up @@ -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
}
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions docker/docker_notlinux.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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 CgroupMemWithContext(ctx, containerid, common.HostSysWithContext(ctx, "fs/cgroup/memory/docker"))
}
Loading