| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 | package performanceimport (	"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 informationfunc 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}
 |