diff --git a/collector/cs.go b/collector/cs.go index a7eacc485..f593b4ca3 100644 --- a/collector/cs.go +++ b/collector/cs.go @@ -3,7 +3,7 @@ package collector import ( - "github.com/prometheus-community/windows_exporter/sysinfoapi" + "github.com/prometheus-community/windows_exporter/headers/sysinfoapi" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/common/log" @@ -60,9 +60,11 @@ func (c *CSCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) e } func (c *CSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { - cs := sysinfoapi.GetNumLogicalProcessors() + // Get systeminfo for number of processors + systemInfo := sysinfoapi.GetSystemInfo() - pm, err := sysinfoapi.GetPhysicalMemory() + // Get memory status for physical memory + mem, err := sysinfoapi.GlobalMemoryStatusEx() if err != nil { return nil, err } @@ -70,13 +72,13 @@ func (c *CSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, er ch <- prometheus.MustNewConstMetric( c.LogicalProcessors, prometheus.GaugeValue, - float64(cs), + float64(systemInfo.DwNumberOfProcessors), ) ch <- prometheus.MustNewConstMetric( c.PhysicalMemoryBytes, prometheus.GaugeValue, - float64(pm), + float64(mem.UllTotalPhys), ) hostname, err := sysinfoapi.GetComputerName(sysinfoapi.ComputerNameDNSHostname) diff --git a/headers/sysinfoapi/sysinfoapi.go b/headers/sysinfoapi/sysinfoapi.go index d9c292022..181baab9f 100644 --- a/headers/sysinfoapi/sysinfoapi.go +++ b/headers/sysinfoapi/sysinfoapi.go @@ -1,6 +1,7 @@ package sysinfoapi import ( + "unicode/utf16" "unsafe" "golang.org/x/sys/windows" @@ -20,10 +21,49 @@ type MemoryStatusEx struct { UllAvailExtendedVirtual uint64 } +// wProcessorArchitecture is a wrapper for the union found in LP_SYSTEM_INFO +// https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/ns-sysinfoapi-system_info +type wProcessorArchitecture struct { + WReserved uint16 + WProcessorArchitecture uint16 +} + +// LpSystemInfo is a wrapper for LPSYSTEM_INFO +// https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/ns-sysinfoapi-system_info +type LpSystemInfo struct { + Arch wProcessorArchitecture + DwPageSize uint32 + LpMinimumApplicationAddress *byte + LpMaximumApplicationAddress *byte + DwActiveProcessorMask *uint32 + DwNumberOfProcessors uint32 + DwProcessorType uint32 + DwAllocationGranularity uint32 + WProcessorLevel uint16 + WProcessorRevision uint16 +} + +// WinComputerNameFormat is a wrapper for COMPUTER_NAME_FORMAT +type WinComputerNameFormat int + +// Definitions for WinComputerNameFormat constants +const ( + ComputerNameNetBIOS WinComputerNameFormat = iota + ComputerNameDNSHostname + ComputerNameDNSDomain + ComputerNameDNSFullyQualified + ComputerNamePhysicalNetBIOS + ComputerNamePhysicalDNSHostname + ComputerNamePhysicalDNSDomain + ComputerNamePhysicalDNSFullyQualified + ComputerNameMax +) + var ( kernel32 = windows.NewLazySystemDLL("kernel32.dll") procGetSystemInfo = kernel32.NewProc("GetSystemInfo") procGlobalMemoryStatusEx = kernel32.NewProc("GlobalMemoryStatusEx") + procGetComputerNameExW = kernel32.NewProc("GetComputerNameExW") ) // GlobalMemoryStatusEx retrieves information about the system's current usage of both physical and virtual memory. @@ -41,3 +81,28 @@ func GlobalMemoryStatusEx() (MemoryStatusEx, error) { return mse, nil } + +// GetSystemInfo wraps the GetSystemInfo function from sysinfoapi +// https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsysteminfo +func GetSystemInfo() LpSystemInfo { + var info LpSystemInfo + pInfo := uintptr(unsafe.Pointer(&info)) + procGetSystemInfo.Call(pInfo) + return info +} + +// GetComputerName wraps the GetComputerNameW function in a more Go-like way +// https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getcomputernamew +func GetComputerName(f WinComputerNameFormat) (string, error) { + // 1kb buffer to accept computer name. This should be more than enough as the maximum size + // returned is the max length of a DNS name, which this author believes is 253 characters. + size := 1024 + var buffer [4096]uint16 + r1, _, err := procGetComputerNameExW.Call(uintptr(f), uintptr(unsafe.Pointer(&buffer)), uintptr(unsafe.Pointer(&size))) + if r1 == 0 { + return "", err + } + bytes := buffer[0:size] + out := utf16.Decode(bytes) + return string(out), nil +} diff --git a/sysinfoapi/sysinfoapi.go b/sysinfoapi/sysinfoapi.go deleted file mode 100644 index fcddf2d3f..000000000 --- a/sysinfoapi/sysinfoapi.go +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2020 Prometheus Team -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package sysinfoapi wraps some WinAPI sysinfoapi functions used by the exporter to produce metrics. -// It is fairly opinionated for the exporter's internal use, and is not intended to be a -// generic wrapper for the WinAPI's sysinfoapi. -package sysinfoapi - -import ( - "unicode/utf16" - "unsafe" - - "golang.org/x/sys/windows" -) - -// WinProcInfo is a wrapper for -type WinProcInfo struct { - WReserved uint16 - WProcessorArchitecture uint16 -} - -// WinSystemInfo is a wrapper for LPSYSTEM_INFO -type WinSystemInfo struct { - Arch WinProcInfo - DwPageSize uint32 - LpMinimumApplicationAddress *byte - LpMaximumApplicationAddress *byte - DwActiveProcessorMask *uint32 - DwNumberOfProcessors uint32 - DwProcessorType uint32 - DwAllocationGranularity uint32 - WProcessorLevel uint16 - WProcessorRevision uint16 -} - -// WinComputerNameFormat is a wrapper for COMPUTER_NAME_FORMAT -type WinComputerNameFormat int - -// Definitions for WinComputerNameFormat constants -const ( - ComputerNameNetBIOS WinComputerNameFormat = iota - ComputerNameDNSHostname - ComputerNameDNSDomain - ComputerNameDNSFullyQualified - ComputerNamePhysicalNetBIOS - ComputerNamePhysicalDNSHostname - ComputerNamePhysicalDNSDomain - ComputerNamePhysicalDNSFullyQualified - ComputerNameMax -) - -// WinMemoryStatus is a wrapper for LPMEMORYSTATUSEX -type WinMemoryStatus struct { - dwLength uint32 - dwMemoryLoad uint32 - ullTotalPhys uint64 - ullAvailPhys uint64 - ullTotalPageFile uint64 - ullAvailPageFile uint64 - ullTotalVirtual uint64 - ullAvailVirtual uint64 - ullAvailExtendedVirtual uint64 -} - -var ( - kernel32 = windows.NewLazySystemDLL("kernel32.dll") - procGetSystemInfo = kernel32.NewProc("GetSystemInfo") - procGlobalMemoryStatusEx = kernel32.NewProc("GlobalMemoryStatusEx") - procGetComputerNameExW = kernel32.NewProc("GetComputerNameExW") -) - -// GetNumLogicalProcessors returns the number of logical processes provided by sysinfoapi's GetSystemInfo function. -func GetNumLogicalProcessors() int { - var sysInfo WinSystemInfo - pInfo := uintptr(unsafe.Pointer(&sysInfo)) - procGetSystemInfo.Call(pInfo) - return int(sysInfo.DwNumberOfProcessors) -} - -// GetPhysicalMemory returns the system's installed physical memory provided by sysinfoapi's GlobalMemoryStatusEx function. -func GetPhysicalMemory() (int, error) { - var wm WinMemoryStatus - wm.dwLength = (uint32)(unsafe.Sizeof(wm)) - r1, _, err := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&wm))) - if r1 != 1 { - return 0, err - } - return int(wm.ullTotalPhys), nil -} - -// GetComputerName provides the requested computer name provided by sysinfoapi's GetComputerNameEx function. -func GetComputerName(f WinComputerNameFormat) (string, error) { - size := 4096 - var buffer [4096]uint16 - r1, _, err := procGetComputerNameExW.Call(uintptr(f), uintptr(unsafe.Pointer(&buffer)), uintptr(unsafe.Pointer(&size))) - if r1 == 0 { - return "", err - } - bytes := buffer[0:size] - out := utf16.Decode(bytes) - return string(out), nil -}