github.com/mackerelio/mackerel-agent-plugins@v0.89.3/mackerel-plugin-unicorn/lib/unicorn_worker.go (about) 1 package mpunicorn 2 3 import ( 4 "fmt" 5 "time" 6 7 "strconv" 8 "strings" 9 ) 10 11 func idleWorkerCount(pids []string) (int, error) { 12 var beforeCPU []string 13 var afterCPU []string 14 idles := 0 15 16 for _, pid := range pids { 17 cputime, err := cpuTime(pid) 18 if err != nil { 19 return idles, err 20 } 21 beforeCPU = append(beforeCPU, cputime) 22 } 23 time.Sleep(1 * time.Second) 24 for _, pid := range pids { 25 cputime, err := cpuTime(pid) 26 if err != nil { 27 return idles, err 28 } 29 afterCPU = append(afterCPU, cputime) 30 } 31 for i := range pids { 32 b, _ := strconv.Atoi(beforeCPU[i]) 33 a, _ := strconv.Atoi(afterCPU[i]) 34 if (a - b) == 0 { 35 idles++ 36 } 37 } 38 39 return idles, nil 40 } 41 42 func fetchUnicornWorkerPids(m string) ([]string, error) { 43 var workerPids []string 44 45 out, err := command.Output("ps", "wh", "--ppid", m) 46 if err != nil { 47 return workerPids, fmt.Errorf("Failed to ps of command: %s", err) // nolint 48 } 49 50 for _, line := range strings.Split(string(out), "\n") { 51 if !strings.Contains(line, "worker") { 52 continue 53 } 54 words := strings.SplitN(strings.TrimSpace(line), " ", 5) 55 if len(words) < 5 { 56 continue 57 } 58 workerPids = append(workerPids, words[0]) 59 } 60 61 if len(workerPids) > 0 { 62 return workerPids, nil 63 } 64 65 return workerPids, fmt.Errorf("Cannot get unicorn worker pids") // nolint 66 } 67 68 func cpuTime(pid string) (string, error) { 69 out, err := pipedCommands.Output( 70 []string{"cat", fmt.Sprintf("/proc/%s/stat", pid)}, 71 []string{"awk", "{print $14+$15}"}, 72 ) 73 if err != nil { 74 return "", fmt.Errorf("Failed to cat /proc/%s/stat: %s", pid, err) // nolint 75 } 76 77 return strings.Trim(string(out), "\n"), nil 78 }