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  }