123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- package performance
- import (
- "fmt"
- "math"
- "runtime"
- "strings"
- "time"
- "github.com/shirou/gopsutil/v4/process"
- )
- type NginxProcessInfo struct {
- Workers int `json:"workers"`
- Master int `json:"master"`
- Cache int `json:"cache"`
- Other int `json:"other"`
- CPUUsage float64 `json:"cpu_usage"`
- MemoryUsage float64 `json:"memory_usage"`
- }
- // GetNginxProcessInfo Get Nginx process information
- func GetNginxProcessInfo() (*NginxProcessInfo, error) {
- result := &NginxProcessInfo{
- Workers: 0,
- Master: 0,
- Cache: 0,
- Other: 0,
- CPUUsage: 0.0,
- MemoryUsage: 0.0,
- }
- // Find all Nginx processes
- processes, err := process.Processes()
- if err != nil {
- return result, fmt.Errorf("failed to get processes: %v", err)
- }
- totalMemory := 0.0
- workerCount := 0
- masterCount := 0
- cacheCount := 0
- otherCount := 0
- nginxProcesses := []*process.Process{}
- // Get the number of system CPU cores
- numCPU := runtime.NumCPU()
- // Get the PID of the Nginx master process
- var masterPID int32 = -1
- for _, p := range processes {
- name, err := p.Name()
- if err != nil {
- continue
- }
- cmdline, err := p.Cmdline()
- if err != nil {
- continue
- }
- // Check if it is the Nginx master process
- if strings.Contains(strings.ToLower(name), "nginx") &&
- (strings.Contains(cmdline, "master process") ||
- !strings.Contains(cmdline, "worker process")) &&
- p.Pid > 0 {
- masterPID = p.Pid
- masterCount++
- nginxProcesses = append(nginxProcesses, p)
- // Get the memory usage
- mem, err := p.MemoryInfo()
- if err == nil && mem != nil {
- // Convert to MB
- memoryUsage := float64(mem.RSS) / 1024 / 1024
- totalMemory += memoryUsage
- }
- break
- }
- }
- // Iterate through all processes, distinguishing between worker processes and other Nginx processes
- for _, p := range processes {
- if p.Pid == masterPID {
- continue // Already calculated the master process
- }
- name, err := p.Name()
- if err != nil {
- continue
- }
- // Only process Nginx related processes
- if !strings.Contains(strings.ToLower(name), "nginx") {
- continue
- }
- // Add to the Nginx process list
- nginxProcesses = append(nginxProcesses, p)
- // Get the parent process PID
- ppid, err := p.Ppid()
- if err != nil {
- continue
- }
- cmdline, err := p.Cmdline()
- if err != nil {
- continue
- }
- // Get the memory usage
- mem, err := p.MemoryInfo()
- if err == nil && mem != nil {
- // Convert to MB
- memoryUsage := float64(mem.RSS) / 1024 / 1024
- totalMemory += memoryUsage
- }
- // Distinguish between worker processes, cache processes, and other processes
- if ppid == masterPID && strings.Contains(cmdline, "worker process") {
- workerCount++
- } else if ppid == masterPID && strings.Contains(cmdline, "cache") {
- cacheCount++
- } else {
- otherCount++
- }
- }
- // Calculate the CPU usage
- // First, measure the initial CPU time
- times1 := make(map[int32]float64)
- for _, p := range nginxProcesses {
- times, err := p.Times()
- if err == nil {
- // CPU time = user time + system time
- times1[p.Pid] = times.User + times.System
- }
- }
- // Wait for a short period of time
- time.Sleep(100 * time.Millisecond)
- // Measure the CPU time again
- totalCPUPercent := 0.0
- for _, p := range nginxProcesses {
- times, err := p.Times()
- if err != nil {
- continue
- }
- // Calculate the CPU time difference
- currentTotal := times.User + times.System
- if previousTotal, ok := times1[p.Pid]; ok {
- // Calculate the CPU usage percentage during this period (considering multiple cores)
- cpuDelta := currentTotal - previousTotal
- // Calculate the CPU usage per second (considering the sampling time)
- cpuPercent := (cpuDelta / 0.1) * 100.0 / float64(numCPU)
- totalCPUPercent += cpuPercent
- }
- }
- // Round to the nearest integer, which is more consistent with the top display
- totalCPUPercent = math.Round(totalCPUPercent)
- // Round the memory usage to two decimal places
- totalMemory = math.Round(totalMemory*100) / 100
- result.Workers = workerCount
- result.Master = masterCount
- result.Cache = cacheCount
- result.Other = otherCount
- result.CPUUsage = totalCPUPercent
- result.MemoryUsage = totalMemory
- return result, nil
- }
|