diff --git a/process/process.go b/process/process.go index 1a7fe1b80..495a36645 100644 --- a/process/process.go +++ b/process/process.go @@ -26,6 +26,7 @@ type Process struct { Pid int32 `json:"pid"` name string status string + cgroup string parent int32 parentMutex sync.RWMutex // for windows ppid cache numCtxSwitches *NumCtxSwitchesStat @@ -375,6 +376,11 @@ func (p *Process) Name() (string, error) { return p.NameWithContext(context.Background()) } +// Cgroup returns cgroup of the process. +func (p *Process) Cgroup() (string, error) { + return p.CgroupWithContext(context.Background()) +} + // Exe returns executable path of the process. func (p *Process) Exe() (string, error) { return p.ExeWithContext(context.Background()) diff --git a/process/process_darwin.go b/process/process_darwin.go index 176661cbd..f74bf44a9 100644 --- a/process/process_darwin.go +++ b/process/process_darwin.go @@ -89,6 +89,10 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) { return name, nil } +func (p *Process) CgroupWithContext(ctx context.Context) (string, error) { + return "", common.ErrNotImplementedError +} + func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) { k, err := p.getKProc() if err != nil { diff --git a/process/process_fallback.go b/process/process_fallback.go index 1a5d0c4b4..e59aacf48 100644 --- a/process/process_fallback.go +++ b/process/process_fallback.go @@ -50,6 +50,10 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) { return "", common.ErrNotImplementedError } +func (p *Process) CgroupWithContext(ctx context.Context) (string, error) { + return "", common.ErrNotImplementedError +} + func (p *Process) TgidWithContext(ctx context.Context) (int32, error) { return 0, common.ErrNotImplementedError } diff --git a/process/process_freebsd.go b/process/process_freebsd.go index 40b10e14f..20032e61d 100644 --- a/process/process_freebsd.go +++ b/process/process_freebsd.go @@ -62,6 +62,10 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) { return name, nil } +func (p *Process) CgroupWithContext(ctx context.Context) (string, error) { + return "", common.ErrNotImplementedError +} + func (p *Process) CwdWithContext(ctx context.Context) (string, error) { return "", common.ErrNotImplementedError } diff --git a/process/process_linux.go b/process/process_linux.go index f7989cd21..5ecc5ec22 100644 --- a/process/process_linux.go +++ b/process/process_linux.go @@ -90,6 +90,15 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) { return p.name, nil } +func (p *Process) CgroupWithContext(ctx context.Context) (string, error) { + if p.cgroup == "" { + if err := p.fillCgroupWithContext(ctx); err != nil { + return "", err + } + } + return p.cgroup, nil +} + func (p *Process) TgidWithContext(ctx context.Context) (int32, error) { if p.tgid == 0 { if err := p.fillFromStatusWithContext(ctx); err != nil { @@ -810,6 +819,19 @@ func (p *Process) fillFromCommWithContext(ctx context.Context) error { return nil } +// Get cgroup from /proc/(pid)/cgroup +func (p *Process) fillCgroupWithContext(ctx context.Context) error { + pid := p.Pid + statPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "cgroup") + contents, err := os.ReadFile(statPath) + if err != nil { + return err + } + + p.cgroup = strings.TrimSuffix(string(contents), "\n") + return nil +} + // Get various status from /proc/(pid)/status func (p *Process) fillFromStatus() error { return p.fillFromStatusWithContext(context.Background()) diff --git a/process/process_openbsd.go b/process/process_openbsd.go index a58c5eb11..58536b1a1 100644 --- a/process/process_openbsd.go +++ b/process/process_openbsd.go @@ -67,6 +67,10 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) { return name, nil } +func (p *Process) CgroupWithContext(ctx context.Context) (string, error) { + return "", nil +} + func (p *Process) CwdWithContext(ctx context.Context) (string, error) { return "", common.ErrNotImplementedError } diff --git a/process/process_plan9.go b/process/process_plan9.go index bc4bc062a..56ab021d8 100644 --- a/process/process_plan9.go +++ b/process/process_plan9.go @@ -50,6 +50,10 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) { return "", common.ErrNotImplementedError } +func (p *Process) CgroupWithContext(ctx context.Context) (string, error) { + return "", common.ErrNotImplementedError +} + func (p *Process) TgidWithContext(ctx context.Context) (int32, error) { return 0, common.ErrNotImplementedError } diff --git a/process/process_solaris.go b/process/process_solaris.go index dd4bd4760..63ddbe683 100644 --- a/process/process_solaris.go +++ b/process/process_solaris.go @@ -59,6 +59,10 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) { return "", common.ErrNotImplementedError } +func (p *Process) CgroupWithContext(ctx context.Context) (string, error) { + return "", common.ErrNotImplementedError +} + func (p *Process) TgidWithContext(ctx context.Context) (int32, error) { return 0, common.ErrNotImplementedError } diff --git a/process/process_test.go b/process/process_test.go index 877992b25..c55f642e3 100644 --- a/process/process_test.go +++ b/process/process_test.go @@ -467,6 +467,16 @@ func Test_Process_Exe(t *testing.T) { } } +func Test_Process_Cgroup(t *testing.T) { + p := testGetProcess() + + _, err := p.Cgroup() + skipIfNotImplementedErr(t, err) + if err != nil { + t.Errorf("getting cgroup error %v", err) + } +} + func Test_Process_CpuPercent(t *testing.T) { p := testGetProcess() _, err := p.Percent(0) @@ -862,6 +872,13 @@ func BenchmarkProcessName(b *testing.B) { } } +func BenchmarkProcessCgroup(b *testing.B) { + p := testGetProcess() + for i := 0; i < b.N; i++ { + p.Cgroup() + } +} + func BenchmarkProcessPpid(b *testing.B) { p := testGetProcess() for i := 0; i < b.N; i++ { diff --git a/process/process_windows.go b/process/process_windows.go index 14ed0309f..701097a18 100644 --- a/process/process_windows.go +++ b/process/process_windows.go @@ -335,6 +335,10 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) { return filepath.Base(exe), nil } +func (p *Process) CgroupWithContext(ctx context.Context) (string, error) { + return "", common.ErrNotImplementedError +} + func (p *Process) TgidWithContext(ctx context.Context) (int32, error) { return 0, common.ErrNotImplementedError }