86 lines
2.8 KiB
Go
86 lines
2.8 KiB
Go
|
//go:build windows
|
||
|
// +build windows
|
||
|
|
||
|
package metrics
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"io"
|
||
|
"log"
|
||
|
"syscall"
|
||
|
"unsafe"
|
||
|
|
||
|
"golang.org/x/sys/windows"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
modpsapi = syscall.NewLazyDLL("psapi.dll")
|
||
|
modkernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||
|
|
||
|
// https://learn.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-getprocessmemoryinfo
|
||
|
procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo")
|
||
|
procGetProcessHandleCount = modkernel32.NewProc("GetProcessHandleCount")
|
||
|
)
|
||
|
|
||
|
// https://learn.microsoft.com/en-us/windows/win32/api/psapi/ns-psapi-process_memory_counters_ex
|
||
|
type processMemoryCounters struct {
|
||
|
_ uint32
|
||
|
PageFaultCount uint32
|
||
|
PeakWorkingSetSize uintptr
|
||
|
WorkingSetSize uintptr
|
||
|
QuotaPeakPagedPoolUsage uintptr
|
||
|
QuotaPagedPoolUsage uintptr
|
||
|
QuotaPeakNonPagedPoolUsage uintptr
|
||
|
QuotaNonPagedPoolUsage uintptr
|
||
|
PagefileUsage uintptr
|
||
|
PeakPagefileUsage uintptr
|
||
|
PrivateUsage uintptr
|
||
|
}
|
||
|
|
||
|
func writeProcessMetrics(w io.Writer) {
|
||
|
h := windows.CurrentProcess()
|
||
|
var startTime, exitTime, stime, utime windows.Filetime
|
||
|
err := windows.GetProcessTimes(h, &startTime, &exitTime, &stime, &utime)
|
||
|
if err != nil {
|
||
|
log.Printf("ERROR: metrics: cannot read process times: %s", err)
|
||
|
return
|
||
|
}
|
||
|
var mc processMemoryCounters
|
||
|
r1, _, err := procGetProcessMemoryInfo.Call(
|
||
|
uintptr(h),
|
||
|
uintptr(unsafe.Pointer(&mc)),
|
||
|
unsafe.Sizeof(mc),
|
||
|
)
|
||
|
if r1 != 1 {
|
||
|
log.Printf("ERROR: metrics: cannot read process memory information: %s", err)
|
||
|
return
|
||
|
}
|
||
|
stimeSeconds := (uint64(stime.HighDateTime)<<32 + uint64(stime.LowDateTime)) / 1e7
|
||
|
utimeSeconds := (uint64(utime.HighDateTime)<<32 + uint64(utime.LowDateTime)) / 1e7
|
||
|
fmt.Fprintf(w, "process_cpu_seconds_system_total %d\n", stimeSeconds)
|
||
|
fmt.Fprintf(w, "process_cpu_seconds_total %d\n", stimeSeconds+utimeSeconds)
|
||
|
fmt.Fprintf(w, "process_cpu_seconds_user_total %d\n", stimeSeconds)
|
||
|
fmt.Fprintf(w, "process_pagefaults_total %d\n", mc.PageFaultCount)
|
||
|
fmt.Fprintf(w, "process_start_time_seconds %d\n", startTime.Nanoseconds()/1e9)
|
||
|
fmt.Fprintf(w, "process_virtual_memory_bytes %d\n", mc.PrivateUsage)
|
||
|
fmt.Fprintf(w, "process_resident_memory_peak_bytes %d\n", mc.PeakWorkingSetSize)
|
||
|
fmt.Fprintf(w, "process_resident_memory_bytes %d\n", mc.WorkingSetSize)
|
||
|
}
|
||
|
|
||
|
func writeFDMetrics(w io.Writer) {
|
||
|
h := windows.CurrentProcess()
|
||
|
var count uint32
|
||
|
r1, _, err := procGetProcessHandleCount.Call(
|
||
|
uintptr(h),
|
||
|
uintptr(unsafe.Pointer(&count)),
|
||
|
)
|
||
|
if r1 != 1 {
|
||
|
log.Printf("ERROR: metrics: cannot determine open file descriptors count: %s", err)
|
||
|
return
|
||
|
}
|
||
|
// it seems to be hard-coded limit for 64-bit systems
|
||
|
// https://learn.microsoft.com/en-us/archive/blogs/markrussinovich/pushing-the-limits-of-windows-handles#maximum-number-of-handles
|
||
|
fmt.Fprintf(w, "process_max_fds %d\n", 16777216)
|
||
|
fmt.Fprintf(w, "process_open_fds %d\n", count)
|
||
|
}
|