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

     1  //go:build windows
     2  // +build windows
     3  
     4  package load
     5  
     6  import (
     7  	"context"
     8  	"log"
     9  	"math"
    10  	"sync"
    11  	"time"
    12  
    13  	"github.com/gofiber/fiber/v2/internal/gopsutil/common"
    14  )
    15  
    16  var (
    17  	loadErr              error
    18  	loadAvg1M            float64 = 0.0
    19  	loadAvg5M            float64 = 0.0
    20  	loadAvg15M           float64 = 0.0
    21  	loadAvgMutex         sync.RWMutex
    22  	loadAvgGoroutineOnce sync.Once
    23  )
    24  
    25  // loadAvgGoroutine updates avg data by fetching current load by interval
    26  // TODO instead of this goroutine, we can register a Win32 counter just as psutil does
    27  // see https://psutil.readthedocs.io/en/latest/#psutil.getloadavg
    28  // code https://github.com/giampaolo/psutil/blob/8415355c8badc9c94418b19bdf26e622f06f0cce/psutil/arch/windows/wmi.c
    29  func loadAvgGoroutine() {
    30  	var (
    31  		samplingFrequency time.Duration = 5 * time.Second
    32  		loadAvgFactor1M   float64       = 1 / math.Exp(samplingFrequency.Seconds()/time.Minute.Seconds())
    33  		loadAvgFactor5M   float64       = 1 / math.Exp(samplingFrequency.Seconds()/(5*time.Minute).Seconds())
    34  		loadAvgFactor15M  float64       = 1 / math.Exp(samplingFrequency.Seconds()/(15*time.Minute).Seconds())
    35  		currentLoad       float64
    36  	)
    37  
    38  	counter, err := common.ProcessorQueueLengthCounter()
    39  	if err != nil || counter == nil {
    40  		log.Println("gopsutil: unexpected processor queue length counter error, please file an issue on github: err")
    41  		return
    42  	}
    43  
    44  	tick := time.NewTicker(samplingFrequency).C
    45  	for {
    46  		currentLoad, err = counter.GetValue()
    47  		loadAvgMutex.Lock()
    48  		loadErr = err
    49  		loadAvg1M = loadAvg1M*loadAvgFactor1M + currentLoad*(1-loadAvgFactor1M)
    50  		loadAvg5M = loadAvg5M*loadAvgFactor5M + currentLoad*(1-loadAvgFactor5M)
    51  		loadAvg15M = loadAvg15M*loadAvgFactor15M + currentLoad*(1-loadAvgFactor15M)
    52  		loadAvgMutex.Unlock()
    53  		<-tick
    54  	}
    55  }
    56  
    57  // Avg for Windows may return 0 values for the first few 5 second intervals
    58  func Avg() (*AvgStat, error) {
    59  	return AvgWithContext(context.Background())
    60  }
    61  
    62  func AvgWithContext(ctx context.Context) (*AvgStat, error) {
    63  	loadAvgGoroutineOnce.Do(func() {
    64  		go loadAvgGoroutine()
    65  	})
    66  	loadAvgMutex.RLock()
    67  	defer loadAvgMutex.RUnlock()
    68  	ret := AvgStat{
    69  		Load1:  loadAvg1M,
    70  		Load5:  loadAvg5M,
    71  		Load15: loadAvg15M,
    72  	}
    73  
    74  	return &ret, loadErr
    75  }
    76  
    77  func Misc() (*MiscStat, error) {
    78  	return MiscWithContext(context.Background())
    79  }
    80  
    81  func MiscWithContext(ctx context.Context) (*MiscStat, error) {
    82  	ret := MiscStat{}
    83  
    84  	return &ret, common.ErrNotImplementedError
    85  }