104 lines
2.0 KiB
Go
104 lines
2.0 KiB
Go
package metrics
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"zlh-agent/internal/state"
|
|
"zlh-agent/internal/system"
|
|
)
|
|
|
|
type ProcessSection struct {
|
|
PID int `json:"pid"`
|
|
Status string `json:"status"`
|
|
UptimeSeconds *int64 `json:"uptime_seconds"`
|
|
RestartCount int `json:"restart_count"`
|
|
}
|
|
|
|
type MemorySection struct {
|
|
RSSBytes int64 `json:"rss_bytes"`
|
|
VMSBytes int64 `json:"vms_bytes"`
|
|
}
|
|
|
|
type ProcessMetricsResponse struct {
|
|
Process ProcessSection `json:"process"`
|
|
Memory MemorySection `json:"memory"`
|
|
}
|
|
|
|
func ProcessMetrics() (ProcessMetricsResponse, bool, error) {
|
|
pid, ok := system.GetServerPID()
|
|
if !ok {
|
|
return ProcessMetricsResponse{
|
|
Process: ProcessSection{
|
|
PID: 0,
|
|
Status: "stopped",
|
|
RestartCount: state.GetCrashCount(),
|
|
},
|
|
}, true, nil
|
|
}
|
|
|
|
rss, vms, err := readMemoryFromStatus(pid)
|
|
if err != nil {
|
|
return ProcessMetricsResponse{}, false, err
|
|
}
|
|
|
|
return ProcessMetricsResponse{
|
|
Process: ProcessSection{
|
|
PID: pid,
|
|
Status: "running",
|
|
UptimeSeconds: nil,
|
|
RestartCount: state.GetCrashCount(),
|
|
},
|
|
Memory: MemorySection{
|
|
RSSBytes: rss,
|
|
VMSBytes: vms,
|
|
},
|
|
}, false, nil
|
|
}
|
|
|
|
func readMemoryFromStatus(pid int) (int64, int64, error) {
|
|
statusPath := filepath.Join("/proc", strconv.Itoa(pid), "status")
|
|
f, err := os.Open(statusPath)
|
|
if err != nil {
|
|
return 0, 0, err
|
|
}
|
|
defer f.Close()
|
|
|
|
var rssKB int64
|
|
var vmsKB int64
|
|
|
|
s := bufio.NewScanner(f)
|
|
for s.Scan() {
|
|
line := s.Text()
|
|
if strings.HasPrefix(line, "VmRSS:") {
|
|
rssKB = parseKBLine(line)
|
|
}
|
|
if strings.HasPrefix(line, "VmSize:") {
|
|
vmsKB = parseKBLine(line)
|
|
}
|
|
}
|
|
if err := s.Err(); err != nil {
|
|
return 0, 0, err
|
|
}
|
|
if rssKB == 0 && vmsKB == 0 {
|
|
return 0, 0, fmt.Errorf("missing VmRSS/VmSize in %s", statusPath)
|
|
}
|
|
return rssKB * 1024, vmsKB * 1024, nil
|
|
}
|
|
|
|
func parseKBLine(line string) int64 {
|
|
fields := strings.Fields(line)
|
|
if len(fields) < 2 {
|
|
return 0
|
|
}
|
|
n, err := strconv.ParseInt(fields[1], 10, 64)
|
|
if err != nil {
|
|
return 0
|
|
}
|
|
return n
|
|
}
|