Refactor remaining sysinfoapi calls into header package

Signed-off-by: Ben Ridley <benridley29@gmail.com>
This commit is contained in:
Ben Ridley 2021-01-20 11:20:23 +11:00
parent d063bc0842
commit d947d0f6db
3 changed files with 73 additions and 117 deletions

View File

@ -3,8 +3,9 @@
package collector
import (
"github.com/prometheus-community/windows_exporter/headers/sysinfoapi"
"github.com/prometheus-community/windows_exporter/log"
"github.com/prometheus-community/windows_exporter/sysinfoapi"
"github.com/prometheus/client_golang/prometheus"
)
@ -59,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
}
@ -69,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)

View File

@ -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
}

View File

@ -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
}