From dc9fdf897beb6dc9ad56cd31903232a6a91fd9f4 Mon Sep 17 00:00:00 2001 From: CityFun <31820853+zhengkunwang223@users.noreply.github.com> Date: Thu, 27 Nov 2025 11:21:44 +0800 Subject: [PATCH] feat: add more fields to process detail view (#11093) --- agent/app/service/process.go | 185 ++++++++++++++++-- agent/utils/websocket/process_data.go | 5 + frontend/src/api/interface/process.ts | 5 + .../host/process/process/detail/index.vue | 5 + 4 files changed, 182 insertions(+), 18 deletions(-) diff --git a/agent/app/service/process.go b/agent/app/service/process.go index 5c770b699..3bcefe9f1 100644 --- a/agent/app/service/process.go +++ b/agent/app/service/process.go @@ -1,11 +1,15 @@ package service import ( + "bufio" "fmt" "github.com/1Panel-dev/1Panel/agent/app/dto/request" "github.com/1Panel-dev/1Panel/agent/utils/common" "github.com/1Panel-dev/1Panel/agent/utils/websocket" "github.com/shirou/gopsutil/v4/process" + "os" + "strconv" + "strings" "time" ) @@ -103,24 +107,20 @@ func (ps *ProcessService) GetProcessInfoByPID(pid int32) (*websocket.PsProcessDa data.CmdLine = cmdline } - if memInfo, err := p.MemoryInfo(); err == nil { - data.Rss = common.FormatBytes(memInfo.RSS) - data.VMS = common.FormatBytes(memInfo.VMS) - data.HWM = common.FormatBytes(memInfo.HWM) - data.Data = common.FormatBytes(memInfo.Data) - data.Stack = common.FormatBytes(memInfo.Stack) - data.Locked = common.FormatBytes(memInfo.Locked) - data.Swap = common.FormatBytes(memInfo.Swap) - data.RssValue = memInfo.RSS - } else { - data.Rss = "--" - data.Data = "--" - data.VMS = "--" - data.HWM = "--" - data.Stack = "--" - data.Locked = "--" - data.Swap = "--" - data.RssValue = 0 + if memDetail, err := getMemoryDetail(p.Pid); err == nil { + data.Rss = common.FormatBytes(memDetail.RSS) + data.VMS = common.FormatBytes(memDetail.VMS) + data.HWM = common.FormatBytes(memDetail.HWM) + data.Data = common.FormatBytes(memDetail.Data) + data.Stack = common.FormatBytes(memDetail.Stack) + data.Locked = common.FormatBytes(memDetail.Locked) + data.Swap = common.FormatBytes(memDetail.Swap) + data.Dirty = common.FormatBytes(memDetail.Dirty) + data.RssValue = memDetail.RSS + data.PSS = common.FormatBytes(memDetail.PSS) + data.USS = common.FormatBytes(memDetail.USS) + data.Shared = common.FormatBytes(memDetail.Shared) + data.Text = common.FormatBytes(memDetail.Text) } if envs, err := p.Environ(); err == nil { @@ -133,3 +133,152 @@ func (ps *ProcessService) GetProcessInfoByPID(pid int32) (*websocket.PsProcessDa return data, nil } + +type MemoryDetail struct { + RSS uint64 + VMS uint64 + HWM uint64 + Data uint64 + Stack uint64 + Locked uint64 + Swap uint64 + + PSS uint64 + USS uint64 + Shared uint64 + Text uint64 + Dirty uint64 +} + +func getMemoryDetail(pid int32) (*MemoryDetail, error) { + mem := &MemoryDetail{} + + if err := readStatus(pid, mem); err != nil { + return nil, err + } + + if err := readSmapsRollup(pid, mem); err != nil { + if err := readSmaps(pid, mem); err != nil { + return nil, err + } + } + return mem, nil +} + +func readStatus(pid int32, mem *MemoryDetail) error { + filePath := fmt.Sprintf("/proc/%d/status", pid) + file, err := os.Open(filePath) + if err != nil { + return err + } + defer file.Close() + + scanner := bufio.NewScanner(file) + + for scanner.Scan() { + line := scanner.Text() + fields := strings.Fields(line) + if len(fields) < 2 { + continue + } + + key := strings.TrimSuffix(fields[0], ":") + value, _ := strconv.ParseUint(fields[1], 10, 64) + value *= 1024 + + switch key { + case "VmRSS": + mem.RSS = value + case "VmSize": + mem.VMS = value + case "VmData": + mem.Data = value + case "VmSwap": + mem.Swap = value + case "VmExe": + mem.Text = value + case "RssShmem": + mem.Shared = value + case "VmHWM": + mem.HWM = value + case "VmStk": + mem.Stack = value + case "VmLck": + mem.Locked = value + } + } + + return scanner.Err() +} + +func readSmapsRollup(pid int32, mem *MemoryDetail) error { + filePath := fmt.Sprintf("/proc/%d/smaps_rollup", pid) + file, err := os.Open(filePath) + if err != nil { + return err + } + defer file.Close() + + scanner := bufio.NewScanner(file) + + for scanner.Scan() { + line := scanner.Text() + fields := strings.Fields(line) + if len(fields) < 2 { + continue + } + + key := strings.TrimSuffix(fields[0], ":") + value, _ := strconv.ParseUint(fields[1], 10, 64) + value *= 1024 + + switch key { + case "Pss": + mem.PSS = value + case "Private_Clean", "Private_Dirty": + mem.USS += value + case "Shared_Clean", "Shared_Dirty": + if mem.Shared == 0 { + mem.Shared = value + } + } + } + + return scanner.Err() +} + +func readSmaps(pid int32, mem *MemoryDetail) error { + filePath := fmt.Sprintf("/proc/%d/smaps", pid) + file, err := os.Open(filePath) + if err != nil { + return err + } + defer file.Close() + + scanner := bufio.NewScanner(file) + + for scanner.Scan() { + line := scanner.Text() + fields := strings.Fields(line) + if len(fields) < 2 { + continue + } + + key := strings.TrimSuffix(fields[0], ":") + value, _ := strconv.ParseUint(fields[1], 10, 64) + value *= 1024 + + switch key { + case "Pss": + mem.PSS += value + case "Private_Clean", "Private_Dirty": + mem.USS += value + case "Shared_Clean", "Shared_Dirty": + if mem.Shared == 0 { + mem.Shared += value + } + } + } + + return scanner.Err() +} diff --git a/agent/utils/websocket/process_data.go b/agent/utils/websocket/process_data.go index ec71cc97b..8f8cd01d1 100644 --- a/agent/utils/websocket/process_data.go +++ b/agent/utils/websocket/process_data.go @@ -67,6 +67,11 @@ type PsProcessData struct { Stack string `json:"stack"` Locked string `json:"locked"` Swap string `json:"swap"` + Dirty string `json:"dirty"` + PSS string `json:"pss"` + USS string `json:"uss"` + Shared string `json:"shared"` + Text string `json:"text"` CpuValue float64 `json:"cpuValue"` RssValue uint64 `json:"rssValue"` diff --git a/frontend/src/api/interface/process.ts b/frontend/src/api/interface/process.ts index 869a2fe19..a20093ea8 100644 --- a/frontend/src/api/interface/process.ts +++ b/frontend/src/api/interface/process.ts @@ -25,6 +25,11 @@ export namespace Process { stack: string; locked: string; swap: string; + dirty: string; + pss: string; + uss: string; + shared: string; + text: string; cpuValue: number; rssValue: number; diff --git a/frontend/src/views/host/process/process/detail/index.vue b/frontend/src/views/host/process/process/detail/index.vue index 0e023c406..2bc7bf8eb 100644 --- a/frontend/src/views/host/process/process/detail/index.vue +++ b/frontend/src/views/host/process/process/detail/index.vue @@ -38,12 +38,17 @@ {{ data.rss }} + {{ data.pss }} + {{ data.uss }} {{ data.swap }} + {{ data.shared }} {{ data.vms }} {{ data.hwm }} {{ data.data }} {{ data.stack }} {{ data.locked }} + {{ data.text }} + {{ data.dirty }}