github.com/distbuild/reclient@v0.0.0-20240401075343-3de72e395564/internal/pkg/localresources/usage/usage.go (about)

     1  package usage
     2  
     3  import (
     4  	"os"
     5  	"time"
     6  
     7  	log "github.com/golang/glog"
     8  	"github.com/shirou/gopsutil/v3/process"
     9  )
    10  
    11  // These are the names of the proxy's resource usage stats.
    12  const (
    13  	CPUPct = "CPU_pct"
    14  	MemPct = "MEM_pct"
    15  	// MemVirt is the total amount of virtual memory used by the current process,
    16  	// includes physically memory used by code, data and libraries, also pages
    17  	// have been swapped out and pages have been mapped but not used yet.
    18  	MemVirt = "MEM_VIRT_mbs"
    19  	// MemRes is a subset of MemVirt, includes the non-swapping physical memory
    20  	// the process is actively using only.
    21  	MemRes        = "MEM_RES_mbs"
    22  	mb     uint64 = 1024 * 1024
    23  )
    24  
    25  // PsutilSampler is an instance that reports the usage of OS resource.
    26  type PsutilSampler struct {
    27  	Sampler
    28  }
    29  
    30  // Sampler is an interface that can provide the sampled system resource usage.
    31  type Sampler interface {
    32  	Percent(interval time.Duration) (float64, error)
    33  	MemoryPercent() (float32, error)
    34  	MemoryInfo() (*process.MemoryInfoStat, error)
    35  }
    36  
    37  // New a PsutilSampler instance with current process's pid.
    38  func New() *PsutilSampler {
    39  	p, err := process.NewProcess(int32(os.Getpid()))
    40  	if err != nil {
    41  		log.Errorf("Cannot create a NewProcess instance to monitor proxy resource usage.")
    42  		return nil
    43  	}
    44  	return &PsutilSampler{p}
    45  }
    46  
    47  // Sample returns the current resource usage data by performing a new measurement.
    48  func Sample(uSampler Sampler) map[string]int64 {
    49  	if uSampler == nil {
    50  		return nil
    51  	}
    52  	// resource usage by current proxy's process
    53  	cPercent, err := uSampler.Percent(0)
    54  	if err != nil {
    55  		log.Errorf("Failed to get current process's CPU percent: %v", err)
    56  		return nil
    57  	}
    58  	mPercent, err := uSampler.MemoryPercent()
    59  	if err != nil {
    60  		log.Errorf("Failed to get current process's Mem percent: %v", err)
    61  		return nil
    62  	}
    63  	mInfo, err := uSampler.MemoryInfo()
    64  	if err != nil {
    65  		log.Errorf("Failed to get current process's Mem info: %v", err)
    66  		return nil
    67  	}
    68  	res := map[string]int64{}
    69  	res[CPUPct] = int64(cPercent)
    70  	res[MemPct] = int64(mPercent)
    71  	res[MemVirt] = int64(mInfo.VMS / mb)
    72  	res[MemRes] = int64(mInfo.RSS / mb)
    73  	return res
    74  }