github.com/gofiber/fiber/v2@v2.47.0/internal/gopsutil/load/load_darwin.go (about)

     1  //go:build darwin
     2  // +build darwin
     3  
     4  package load
     5  
     6  import (
     7  	"context"
     8  	"os/exec"
     9  	"strings"
    10  	"unsafe"
    11  
    12  	"github.com/gofiber/fiber/v2/internal/gopsutil/common"
    13  	"golang.org/x/sys/unix"
    14  )
    15  
    16  var invoke common.Invoker = common.Invoke{}
    17  
    18  func Avg() (*AvgStat, error) {
    19  	return AvgWithContext(context.Background())
    20  }
    21  
    22  func AvgWithContext(ctx context.Context) (*AvgStat, error) {
    23  	// This SysctlRaw method borrowed from
    24  	// https://github.com/prometheus/node_exporter/blob/master/collector/loadavg_freebsd.go
    25  	// this implementation is common with BSDs
    26  	type loadavg struct {
    27  		load  [3]uint32
    28  		scale int
    29  	}
    30  	b, err := unix.SysctlRaw("vm.loadavg")
    31  	if err != nil {
    32  		return nil, err
    33  	}
    34  	load := *(*loadavg)(unsafe.Pointer((&b[0])))
    35  	scale := float64(load.scale)
    36  	ret := &AvgStat{
    37  		Load1:  float64(load.load[0]) / scale,
    38  		Load5:  float64(load.load[1]) / scale,
    39  		Load15: float64(load.load[2]) / scale,
    40  	}
    41  
    42  	return ret, nil
    43  }
    44  
    45  // Misc returnes miscellaneous host-wide statistics.
    46  // darwin use ps command to get process running/blocked count.
    47  // Almost same as FreeBSD implementation, but state is different.
    48  // U means 'Uninterruptible Sleep'.
    49  func Misc() (*MiscStat, error) {
    50  	return MiscWithContext(context.Background())
    51  }
    52  
    53  func MiscWithContext(ctx context.Context) (*MiscStat, error) {
    54  	bin, err := exec.LookPath("ps")
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  	out, err := invoke.CommandWithContext(ctx, bin, "axo", "state")
    59  	if err != nil {
    60  		return nil, err
    61  	}
    62  	lines := strings.Split(string(out), "\n")
    63  
    64  	ret := MiscStat{}
    65  	for _, l := range lines {
    66  		if strings.Contains(l, "R") {
    67  			ret.ProcsRunning++
    68  		} else if strings.Contains(l, "U") {
    69  			// uninterruptible sleep == blocked
    70  			ret.ProcsBlocked++
    71  		}
    72  	}
    73  
    74  	return &ret, nil
    75  }