chore: release 0.29.0.rc0 (#1600)

This commit is contained in:
Jan-Otto Kröpke
2024-09-11 00:34:10 +02:00
committed by GitHub
parent 83b0aa8f62
commit f712c07c38
119 changed files with 5113 additions and 2255 deletions

236
pkg/perfdata/collector.go Normal file
View File

@@ -0,0 +1,236 @@
//go:build windows
package perfdata
import (
"errors"
"fmt"
"strings"
"time"
"unsafe"
"github.com/prometheus/client_golang/prometheus"
"golang.org/x/sys/windows"
)
const EmptyInstance = "------"
type Collector struct {
time time.Time
object string
counters []Counter
handle pdhQueryHandle
}
type Counter struct {
Name string
Instances map[string]pdhCounterHandle
Type uint32
Frequency float64
}
type CounterValues struct {
Type prometheus.ValueType
FirstValue float64
SecondValue float64
}
func NewCollector(object string, instances []string, counters []string) (*Collector, error) {
var handle pdhQueryHandle
if ret := PdhOpenQuery(0, 0, &handle); ret != ErrorSuccess {
return nil, NewPdhError(ret)
}
if len(instances) == 0 {
instances = []string{EmptyInstance}
}
collector := &Collector{
object: object,
counters: make([]Counter, 0, len(counters)),
handle: handle,
}
for _, counterName := range counters {
if counterName == "*" {
return nil, errors.New("wildcard counters are not supported")
}
counter := Counter{
Name: counterName,
Instances: make(map[string]pdhCounterHandle, len(instances)),
}
var counterPath string
for _, instance := range instances {
counterPath = formatCounterPath(object, instance, counterName)
var counterHandle pdhCounterHandle
if ret := PdhAddEnglishCounter(handle, counterPath, 0, &counterHandle); ret != ErrorSuccess {
return nil, fmt.Errorf("failed to add counter %s: %w", counterPath, NewPdhError(ret))
}
counter.Instances[instance] = counterHandle
if counter.Type == 0 {
// Get the info with the current buffer size
bufLen := uint32(0)
if ret := PdhGetCounterInfo(counterHandle, 0, &bufLen, nil); ret != PdhMoreData {
return nil, fmt.Errorf("PdhGetCounterInfo: %w", NewPdhError(ret))
}
buf := make([]byte, bufLen)
if ret := PdhGetCounterInfo(counterHandle, 0, &bufLen, &buf[0]); ret != ErrorSuccess {
return nil, fmt.Errorf("PdhGetCounterInfo: %w", NewPdhError(ret))
}
ci := (*PdhCounterInfo)(unsafe.Pointer(&buf[0]))
counter.Type = ci.DwType
frequency := float64(0)
if ret := PdhGetCounterTimeBase(counterHandle, &frequency); ret != ErrorSuccess {
return nil, fmt.Errorf("PdhGetCounterTimeBase: %w", NewPdhError(ret))
}
counter.Frequency = frequency
}
}
collector.counters = append(collector.counters, counter)
}
if len(collector.counters) == 0 {
return nil, errors.New("no counters configured")
}
if _, err := collector.Collect(); err != nil {
return nil, fmt.Errorf("failed to collect initial data: %w", err)
}
return collector, nil
}
func (c *Collector) Collect() (map[string]map[string]CounterValues, error) {
if len(c.counters) == 0 {
return map[string]map[string]CounterValues{}, nil
}
if ret := PdhCollectQueryData(c.handle); ret != ErrorSuccess {
return nil, fmt.Errorf("failed to collect query data: %w", NewPdhError(ret))
}
c.time = time.Now()
var data map[string]map[string]CounterValues
for _, counter := range c.counters {
for _, instance := range counter.Instances {
// Get the info with the current buffer size
var itemCount uint32
// Get the info with the current buffer size
bufLen := uint32(0)
ret := PdhGetRawCounterArray(instance, &bufLen, &itemCount, nil)
if ret != PdhMoreData {
return nil, fmt.Errorf("PdhGetRawCounterArray: %w", NewPdhError(ret))
}
buf := make([]byte, bufLen)
ret = PdhGetRawCounterArray(instance, &bufLen, &itemCount, &buf[0])
if ret != ErrorSuccess {
if err := NewPdhError(ret); !isKnownCounterDataError(err) {
return nil, fmt.Errorf("PdhGetRawCounterArray: %w", err)
}
continue
}
items := (*[1 << 20]PdhRawCounterItem)(unsafe.Pointer(&buf[0]))[:itemCount]
if data == nil {
data = make(map[string]map[string]CounterValues, itemCount)
}
var metricType prometheus.ValueType
if val, ok := supportedCounterTypes[counter.Type]; ok {
metricType = val
} else {
metricType = prometheus.GaugeValue
}
for _, item := range items {
if item.RawValue.CStatus == PdhCstatusValidData || item.RawValue.CStatus == PdhCstatusNewData {
instanceName := windows.UTF16PtrToString(item.SzName)
if strings.HasSuffix(instanceName, "_Total") {
continue
}
if instanceName == "" {
instanceName = EmptyInstance
}
if _, ok := data[instanceName]; !ok {
data[instanceName] = make(map[string]CounterValues, len(c.counters))
}
values := CounterValues{
Type: metricType,
}
// This is a workaround for the issue with the elapsed time counter type.
// Source: https://github.com/prometheus-community/windows_exporter/pull/335/files#diff-d5d2528f559ba2648c2866aec34b1eaa5c094dedb52bd0ff22aa5eb83226bd8dR76-R83
switch counter.Type {
case PERF_ELAPSED_TIME:
values.FirstValue = float64(item.RawValue.FirstValue-WindowsEpoch) / counter.Frequency
values.SecondValue = float64(item.RawValue.SecondValue-WindowsEpoch) / counter.Frequency
case PERF_100NSEC_TIMER, PERF_PRECISION_100NS_TIMER:
values.FirstValue = float64(item.RawValue.FirstValue) * TicksToSecondScaleFactor
values.SecondValue = float64(item.RawValue.SecondValue) * TicksToSecondScaleFactor
default:
values.FirstValue = float64(item.RawValue.FirstValue)
values.SecondValue = float64(item.RawValue.SecondValue)
}
data[instanceName][counter.Name] = values
}
}
}
}
return data, nil
}
func (c *Collector) Close() {
PdhCloseQuery(c.handle)
}
func formatCounterPath(object, instance, counterName string) string {
var counterPath string
if instance == EmptyInstance {
counterPath = fmt.Sprintf(`\%s\%s`, object, counterName)
} else {
counterPath = fmt.Sprintf(`\%s(%s)\%s`, object, instance, counterName)
}
return counterPath
}
func isKnownCounterDataError(err error) bool {
var pdhErr *Error
return errors.As(err, &pdhErr) && (pdhErr.ErrorCode == PdhInvalidData ||
pdhErr.ErrorCode == PdhCalcNegativeDenominator ||
pdhErr.ErrorCode == PdhCalcNegativeValue ||
pdhErr.ErrorCode == PdhCstatusInvalidData ||
pdhErr.ErrorCode == PdhCstatusNoInstance ||
pdhErr.ErrorCode == PdhNoData)
}

View File

@@ -0,0 +1,49 @@
package perfdata_test
import (
"testing"
"github.com/prometheus-community/windows_exporter/pkg/perfdata"
"github.com/stretchr/testify/require"
)
func BenchmarkTestCollector(b *testing.B) {
counters := []string{
"% Processor Time",
"% Privileged Time",
"% User Time",
"Creating Process ID",
"Elapsed Time",
"Handle Count",
"ID Process",
"IO Data Bytes/sec",
"IO Data Operations/sec",
"IO Other Bytes/sec",
"IO Other Operations/sec",
"IO Read Bytes/sec",
"IO Read Operations/sec",
"IO Write Bytes/sec",
"IO Write Operations/sec",
"Page Faults/sec",
"Page File Bytes Peak",
"Page File Bytes",
"Pool Nonpaged Bytes",
"Pool Paged Bytes",
"Priority Base",
"Private Bytes",
"Thread Count",
"Virtual Bytes Peak",
"Virtual Bytes",
"Working Set - Private",
"Working Set Peak",
"Working Set",
}
performanceData, err := perfdata.NewCollector("Process", []string{"*"}, counters)
require.NoError(b, err)
for i := 0; i < b.N; i++ {
_, _ = performanceData.Collect()
}
performanceData.Close()
}

View File

@@ -0,0 +1,86 @@
//go:build windows
package perfdata_test
import (
"testing"
"time"
"github.com/prometheus-community/windows_exporter/pkg/perfdata"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestCollector(t *testing.T) {
t.Parallel()
for _, tc := range []struct {
object string
instances []string
counters []string
}{
{
object: "Memory",
counters: []string{
"Available Bytes",
"Available KBytes",
"Available MBytes",
"Cache Bytes",
"Cache Bytes Peak",
"Cache Faults/sec",
"Commit Limit",
"Committed Bytes",
"Demand Zero Faults/sec",
"Free & Zero Page List Bytes",
"Free System Page Table Entries",
"Modified Page List Bytes",
"Page Reads/sec",
},
}, {
object: "TCPv4",
counters: []string{
"Connection Failures",
"Connections Active",
"Connections Established",
"Connections Passive",
"Connections Reset",
"Segments/sec",
"Segments Received/sec",
"Segments Retransmitted/sec",
"Segments Sent/sec",
},
}, {
object: "Process",
instances: []string{"*"},
counters: []string{
"Thread Count",
"ID Process",
},
},
} {
t.Run(tc.object, func(t *testing.T) {
t.Parallel()
performanceData, err := perfdata.NewCollector(tc.object, tc.instances, tc.counters)
require.NoError(t, err)
time.Sleep(100 * time.Millisecond)
data, err := performanceData.Collect()
require.NoError(t, err)
require.NotEmpty(t, data)
for instance, d := range data {
require.NotEmpty(t, d)
if instance == "Idle" || instance == "Secure System" {
continue
}
for _, c := range tc.counters {
assert.NotZerof(t, d[c].FirstValue, "object: %s, instance: %s, counter: %s", tc.object, instance, c)
}
}
})
}
}

78
pkg/perfdata/const.go Normal file
View File

@@ -0,0 +1,78 @@
//go:build windows
package perfdata
import "github.com/prometheus/client_golang/prometheus"
// Conversion factors.
const (
TicksToSecondScaleFactor = 1 / 1e7
WindowsEpoch = 116444736000000000
)
// Based on https://github.com/leoluk/perflib_exporter/blob/master/collector/mapper.go
//
//goland:noinspection GoUnusedConst
const (
PERF_COUNTER_RAWCOUNT_HEX = 0x00000000
PERF_COUNTER_LARGE_RAWCOUNT_HEX = 0x00000100
PERF_COUNTER_TEXT = 0x00000b00
PERF_COUNTER_RAWCOUNT = 0x00010000
PERF_COUNTER_LARGE_RAWCOUNT = 0x00010100
PERF_DOUBLE_RAW = 0x00012000
PERF_COUNTER_DELTA = 0x00400400
PERF_COUNTER_LARGE_DELTA = 0x00400500
PERF_SAMPLE_COUNTER = 0x00410400
PERF_COUNTER_QUEUELEN_TYPE = 0x00450400
PERF_COUNTER_LARGE_QUEUELEN_TYPE = 0x00450500
PERF_COUNTER_100NS_QUEUELEN_TYPE = 0x00550500
PERF_COUNTER_OBJ_TIME_QUEUELEN_TYPE = 0x00650500
PERF_COUNTER_COUNTER = 0x10410400
PERF_COUNTER_BULK_COUNT = 0x10410500
PERF_RAW_FRACTION = 0x20020400
PERF_LARGE_RAW_FRACTION = 0x20020500
PERF_COUNTER_TIMER = 0x20410500
PERF_PRECISION_SYSTEM_TIMER = 0x20470500
PERF_100NSEC_TIMER = 0x20510500
PERF_PRECISION_100NS_TIMER = 0x20570500
PERF_OBJ_TIME_TIMER = 0x20610500
PERF_PRECISION_OBJECT_TIMER = 0x20670500
PERF_SAMPLE_FRACTION = 0x20c20400
PERF_COUNTER_TIMER_INV = 0x21410500
PERF_100NSEC_TIMER_INV = 0x21510500
PERF_COUNTER_MULTI_TIMER = 0x22410500
PERF_100NSEC_MULTI_TIMER = 0x22510500
PERF_COUNTER_MULTI_TIMER_INV = 0x23410500
PERF_100NSEC_MULTI_TIMER_INV = 0x23510500
PERF_AVERAGE_TIMER = 0x30020400
PERF_ELAPSED_TIME = 0x30240500
PERF_COUNTER_NODATA = 0x40000200
PERF_AVERAGE_BULK = 0x40020500
PERF_SAMPLE_BASE = 0x40030401
PERF_AVERAGE_BASE = 0x40030402
PERF_RAW_BASE = 0x40030403
PERF_PRECISION_TIMESTAMP = 0x40030500
PERF_LARGE_RAW_BASE = 0x40030503
PERF_COUNTER_MULTI_BASE = 0x42030500
PERF_COUNTER_HISTOGRAM_TYPE = 0x80000000
)
var supportedCounterTypes = map[uint32]prometheus.ValueType{
PERF_COUNTER_RAWCOUNT_HEX: prometheus.GaugeValue,
PERF_COUNTER_LARGE_RAWCOUNT_HEX: prometheus.GaugeValue,
PERF_COUNTER_RAWCOUNT: prometheus.GaugeValue,
PERF_COUNTER_LARGE_RAWCOUNT: prometheus.GaugeValue,
PERF_COUNTER_DELTA: prometheus.CounterValue,
PERF_COUNTER_COUNTER: prometheus.CounterValue,
PERF_COUNTER_BULK_COUNT: prometheus.CounterValue,
PERF_RAW_FRACTION: prometheus.GaugeValue,
PERF_LARGE_RAW_FRACTION: prometheus.GaugeValue,
PERF_100NSEC_TIMER: prometheus.CounterValue,
PERF_PRECISION_100NS_TIMER: prometheus.CounterValue,
PERF_SAMPLE_FRACTION: prometheus.GaugeValue,
PERF_100NSEC_TIMER_INV: prometheus.CounterValue,
PERF_ELAPSED_TIME: prometheus.GaugeValue,
PERF_SAMPLE_BASE: prometheus.GaugeValue,
PERF_RAW_BASE: prometheus.GaugeValue,
PERF_LARGE_RAW_BASE: prometheus.GaugeValue,
}

18
pkg/perfdata/error.go Normal file
View File

@@ -0,0 +1,18 @@
package perfdata
// Error represents error returned from Performance Counters API.
type Error struct {
ErrorCode uint32
errorText string
}
func (m *Error) Error() string {
return m.errorText
}
func NewPdhError(code uint32) error {
return &Error{
ErrorCode: code,
errorText: PdhFormatError(code),
}
}

638
pkg/perfdata/pdh.go Normal file
View File

@@ -0,0 +1,638 @@
// Copyright (c) 2010-2024 The win Authors. All rights reserved.
// Copyright (c) 2024 The prometheus-community Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. The names of the authors may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// This is the official list of 'win' authors for copyright purposes.
//
// Alexander Neumann <an2048@googlemail.com>
// Joseph Watson <jtwatson@linux-consulting.us>
// Kevin Pors <krpors@gmail.com>
//go:build windows
package perfdata
import (
"fmt"
"time"
"unsafe"
"github.com/prometheus-community/windows_exporter/pkg/headers/kernel32"
"golang.org/x/sys/windows"
)
// Error codes.
const (
ErrorSuccess = 0
ErrorFailure = 1
ErrorInvalidFunction = 1
EpochDifferenceMicros int64 = 11644473600000000
)
type (
HANDLE uintptr
)
// PDH error codes, which can be returned by all Pdh* functions. Taken from mingw-w64 pdhmsg.h
const (
PdhCstatusValidData = 0x00000000 // The returned data is valid.
PdhCstatusNewData = 0x00000001 // The return data value is valid and different from the last sample.
PdhCstatusNoMachine = 0x800007D0 // Unable to connect to the specified computer, or the computer is offline.
PdhCstatusNoInstance = 0x800007D1
PdhMoreData = 0x800007D2 // The PdhGetFormattedCounterArray* function can return this if there's 'more data to be displayed'.
PdhCstatusItemNotValidated = 0x800007D3
PdhRetry = 0x800007D4
PdhNoData = 0x800007D5 // The query does not currently contain any counters (for example, limited access)
PdhCalcNegativeDenominator = 0x800007D6
PdhCalcNegativeTimebase = 0x800007D7
PdhCalcNegativeValue = 0x800007D8
PdhDialogCancelled = 0x800007D9
PdhEndOfLogFile = 0x800007DA
PdhAsyncQueryTimeout = 0x800007DB
PdhCannotSetDefaultRealtimeDatasource = 0x800007DC
PdhCstatusNoObject = 0xC0000BB8
PdhCstatusNoCounter = 0xC0000BB9 // The specified counter could not be found.
PdhCstatusInvalidData = 0xC0000BBA // The counter was successfully found, but the data returned is not valid.
PdhMemoryAllocationFailure = 0xC0000BBB
PdhInvalidHandle = 0xC0000BBC
PdhInvalidArgument = 0xC0000BBD // Required argument is missing or incorrect.
PdhFunctionNotFound = 0xC0000BBE
PdhCstatusNoCountername = 0xC0000BBF
PdhCstatusBadCountername = 0xC0000BC0 // Unable to parse the counter path. Check the format and syntax of the specified path.
PdhInvalidBuffer = 0xC0000BC1
PdhInsufficientBuffer = 0xC0000BC2
PdhCannotConnectMachine = 0xC0000BC3
PdhInvalidPath = 0xC0000BC4
PdhInvalidInstance = 0xC0000BC5
PdhInvalidData = 0xC0000BC6 // specified counter does not contain valid data or a successful status code.
PdhNoDialogData = 0xC0000BC7
PdhCannotReadNameStrings = 0xC0000BC8
PdhLogFileCreateError = 0xC0000BC9
PdhLogFileOpenError = 0xC0000BCA
PdhLogTypeNotFound = 0xC0000BCB
PdhNoMoreData = 0xC0000BCC
PdhEntryNotInLogFile = 0xC0000BCD
PdhDataSourceIsLogFile = 0xC0000BCE
PdhDataSourceIsRealTime = 0xC0000BCF
PdhUnableReadLogHeader = 0xC0000BD0
PdhFileNotFound = 0xC0000BD1
PdhFileAlreadyExists = 0xC0000BD2
PdhNotImplemented = 0xC0000BD3
PdhStringNotFound = 0xC0000BD4
PdhUnableMapNameFiles = 0x80000BD5
PdhUnknownLogFormat = 0xC0000BD6
PdhUnknownLogsvcCommand = 0xC0000BD7
PdhLogsvcQueryNotFound = 0xC0000BD8
PdhLogsvcNotOpened = 0xC0000BD9
PdhWbemError = 0xC0000BDA
PdhAccessDenied = 0xC0000BDB
PdhLogFileTooSmall = 0xC0000BDC
PdhInvalidDatasource = 0xC0000BDD
PdhInvalidSqldb = 0xC0000BDE
PdhNoCounters = 0xC0000BDF
PdhSQLAllocFailed = 0xC0000BE0
PdhSQLAllocconFailed = 0xC0000BE1
PdhSQLExecDirectFailed = 0xC0000BE2
PdhSQLFetchFailed = 0xC0000BE3
PdhSQLRowcountFailed = 0xC0000BE4
PdhSQLMoreResultsFailed = 0xC0000BE5
PdhSQLConnectFailed = 0xC0000BE6
PdhSQLBindFailed = 0xC0000BE7
PdhCannotConnectWmiServer = 0xC0000BE8
PdhPlaCollectionAlreadyRunning = 0xC0000BE9
PdhPlaErrorScheduleOverlap = 0xC0000BEA
PdhPlaCollectionNotFound = 0xC0000BEB
PdhPlaErrorScheduleElapsed = 0xC0000BEC
PdhPlaErrorNostart = 0xC0000BED
PdhPlaErrorAlreadyExists = 0xC0000BEE
PdhPlaErrorTypeMismatch = 0xC0000BEF
PdhPlaErrorFilepath = 0xC0000BF0
PdhPlaServiceError = 0xC0000BF1
PdhPlaValidationError = 0xC0000BF2
PdhPlaValidationWarning = 0x80000BF3
PdhPlaErrorNameTooLong = 0xC0000BF4
PdhInvalidSQLLogFormat = 0xC0000BF5
PdhCounterAlreadyInQuery = 0xC0000BF6
PdhBinaryLogCorrupt = 0xC0000BF7
PdhLogSampleTooSmall = 0xC0000BF8
PdhOsLaterVersion = 0xC0000BF9
PdhOsEarlierVersion = 0xC0000BFA
PdhIncorrectAppendTime = 0xC0000BFB
PdhUnmatchedAppendCounter = 0xC0000BFC
PdhSQLAlterDetailFailed = 0xC0000BFD
PdhQueryPerfDataTimeout = 0xC0000BFE
)
var PDHErrors = map[uint32]string{
PdhCstatusValidData: "PDH_CSTATUS_VALID_DATA",
PdhCstatusNewData: "PDH_CSTATUS_NEW_DATA",
PdhCstatusNoMachine: "PDH_CSTATUS_NO_MACHINE",
PdhCstatusNoInstance: "PDH_CSTATUS_NO_INSTANCE",
PdhMoreData: "PDH_MORE_DATA",
PdhCstatusItemNotValidated: "PDH_CSTATUS_ITEM_NOT_VALIDATED",
PdhRetry: "PDH_RETRY",
PdhNoData: "PDH_NO_DATA",
PdhCalcNegativeDenominator: "PDH_CALC_NEGATIVE_DENOMINATOR",
PdhCalcNegativeTimebase: "PDH_CALC_NEGATIVE_TIMEBASE",
PdhCalcNegativeValue: "PDH_CALC_NEGATIVE_VALUE",
PdhDialogCancelled: "PDH_DIALOG_CANCELLED",
PdhEndOfLogFile: "PDH_END_OF_LOG_FILE",
PdhAsyncQueryTimeout: "PDH_ASYNC_QUERY_TIMEOUT",
PdhCannotSetDefaultRealtimeDatasource: "PDH_CANNOT_SET_DEFAULT_REALTIME_DATASOURCE",
PdhCstatusNoObject: "PDH_CSTATUS_NO_OBJECT",
PdhCstatusNoCounter: "PDH_CSTATUS_NO_COUNTER",
PdhCstatusInvalidData: "PDH_CSTATUS_INVALID_DATA",
PdhMemoryAllocationFailure: "PDH_MEMORY_ALLOCATION_FAILURE",
PdhInvalidHandle: "PDH_INVALID_HANDLE",
PdhInvalidArgument: "PDH_INVALID_ARGUMENT",
PdhFunctionNotFound: "PDH_FUNCTION_NOT_FOUND",
PdhCstatusNoCountername: "PDH_CSTATUS_NO_COUNTERNAME",
PdhCstatusBadCountername: "PDH_CSTATUS_BAD_COUNTERNAME",
PdhInvalidBuffer: "PDH_INVALID_BUFFER",
PdhInsufficientBuffer: "PDH_INSUFFICIENT_BUFFER",
PdhCannotConnectMachine: "PDH_CANNOT_CONNECT_MACHINE",
PdhInvalidPath: "PDH_INVALID_PATH",
PdhInvalidInstance: "PDH_INVALID_INSTANCE",
PdhInvalidData: "PDH_INVALID_DATA",
PdhNoDialogData: "PDH_NO_DIALOG_DATA",
PdhCannotReadNameStrings: "PDH_CANNOT_READ_NAME_STRINGS",
PdhLogFileCreateError: "PDH_LOG_FILE_CREATE_ERROR",
PdhLogFileOpenError: "PDH_LOG_FILE_OPEN_ERROR",
PdhLogTypeNotFound: "PDH_LOG_TYPE_NOT_FOUND",
PdhNoMoreData: "PDH_NO_MORE_DATA",
PdhEntryNotInLogFile: "PDH_ENTRY_NOT_IN_LOG_FILE",
PdhDataSourceIsLogFile: "PDH_DATA_SOURCE_IS_LOG_FILE",
PdhDataSourceIsRealTime: "PDH_DATA_SOURCE_IS_REAL_TIME",
PdhUnableReadLogHeader: "PDH_UNABLE_READ_LOG_HEADER",
PdhFileNotFound: "PDH_FILE_NOT_FOUND",
PdhFileAlreadyExists: "PDH_FILE_ALREADY_EXISTS",
PdhNotImplemented: "PDH_NOT_IMPLEMENTED",
PdhStringNotFound: "PDH_STRING_NOT_FOUND",
PdhUnableMapNameFiles: "PDH_UNABLE_MAP_NAME_FILES",
PdhUnknownLogFormat: "PDH_UNKNOWN_LOG_FORMAT",
PdhUnknownLogsvcCommand: "PDH_UNKNOWN_LOGSVC_COMMAND",
PdhLogsvcQueryNotFound: "PDH_LOGSVC_QUERY_NOT_FOUND",
PdhLogsvcNotOpened: "PDH_LOGSVC_NOT_OPENED",
PdhWbemError: "PDH_WBEM_ERROR",
PdhAccessDenied: "PDH_ACCESS_DENIED",
PdhLogFileTooSmall: "PDH_LOG_FILE_TOO_SMALL",
PdhInvalidDatasource: "PDH_INVALID_DATASOURCE",
PdhInvalidSqldb: "PDH_INVALID_SQLDB",
PdhNoCounters: "PDH_NO_COUNTERS",
PdhSQLAllocFailed: "PDH_SQL_ALLOC_FAILED",
PdhSQLAllocconFailed: "PDH_SQL_ALLOCCON_FAILED",
PdhSQLExecDirectFailed: "PDH_SQL_EXEC_DIRECT_FAILED",
PdhSQLFetchFailed: "PDH_SQL_FETCH_FAILED",
PdhSQLRowcountFailed: "PDH_SQL_ROWCOUNT_FAILED",
PdhSQLMoreResultsFailed: "PDH_SQL_MORE_RESULTS_FAILED",
PdhSQLConnectFailed: "PDH_SQL_CONNECT_FAILED",
PdhSQLBindFailed: "PDH_SQL_BIND_FAILED",
PdhCannotConnectWmiServer: "PDH_CANNOT_CONNECT_WMI_SERVER",
PdhPlaCollectionAlreadyRunning: "PDH_PLA_COLLECTION_ALREADY_RUNNING",
PdhPlaErrorScheduleOverlap: "PDH_PLA_ERROR_SCHEDULE_OVERLAP",
PdhPlaCollectionNotFound: "PDH_PLA_COLLECTION_NOT_FOUND",
PdhPlaErrorScheduleElapsed: "PDH_PLA_ERROR_SCHEDULE_ELAPSED",
PdhPlaErrorNostart: "PDH_PLA_ERROR_NOSTART",
PdhPlaErrorAlreadyExists: "PDH_PLA_ERROR_ALREADY_EXISTS",
PdhPlaErrorTypeMismatch: "PDH_PLA_ERROR_TYPE_MISMATCH",
PdhPlaErrorFilepath: "PDH_PLA_ERROR_FILEPATH",
PdhPlaServiceError: "PDH_PLA_SERVICE_ERROR",
PdhPlaValidationError: "PDH_PLA_VALIDATION_ERROR",
PdhPlaValidationWarning: "PDH_PLA_VALIDATION_WARNING",
PdhPlaErrorNameTooLong: "PDH_PLA_ERROR_NAME_TOO_LONG",
PdhInvalidSQLLogFormat: "PDH_INVALID_SQL_LOG_FORMAT",
PdhCounterAlreadyInQuery: "PDH_COUNTER_ALREADY_IN_QUERY",
PdhBinaryLogCorrupt: "PDH_BINARY_LOG_CORRUPT",
PdhLogSampleTooSmall: "PDH_LOG_SAMPLE_TOO_SMALL",
PdhOsLaterVersion: "PDH_OS_LATER_VERSION",
PdhOsEarlierVersion: "PDH_OS_EARLIER_VERSION",
PdhIncorrectAppendTime: "PDH_INCORRECT_APPEND_TIME",
PdhUnmatchedAppendCounter: "PDH_UNMATCHED_APPEND_COUNTER",
PdhSQLAlterDetailFailed: "PDH_SQL_ALTER_DETAIL_FAILED",
PdhQueryPerfDataTimeout: "PDH_QUERY_PERF_DATA_TIMEOUT",
}
// Formatting options for GetFormattedCounterValue().
//
//goland:noinspection GoUnusedConst
const (
PdhFmtRaw = 0x00000010
PdhFmtAnsi = 0x00000020
PdhFmtUnicode = 0x00000040
PdhFmtLong = 0x00000100 // Return data as a long int.
PdhFmtDouble = 0x00000200 // Return data as a double precision floating point real.
PdhFmtLarge = 0x00000400 // Return data as a 64 bit integer.
PdhFmtNoscale = 0x00001000 // can be OR-ed: Do not apply the counter's default scaling factor.
PdhFmt1000 = 0x00002000 // can be OR-ed: multiply the actual value by 1,000.
PdhFmtNodata = 0x00004000 // can be OR-ed: unknown what this is for, MSDN says nothing.
PdhFmtNocap100 = 0x00008000 // can be OR-ed: do not cap values > 100.
PerfDetailCostly = 0x00010000
PerfDetailStandard = 0x0000FFFF
)
type (
pdhQueryHandle HANDLE // query handle
pdhCounterHandle HANDLE // counter handle
)
var (
libPdhDll = windows.NewLazySystemDLL("pdh.dll")
pdhAddCounterW = libPdhDll.NewProc("PdhAddCounterW")
pdhAddEnglishCounterW = libPdhDll.NewProc("PdhAddEnglishCounterW")
pdhCloseQuery = libPdhDll.NewProc("PdhCloseQuery")
pdhCollectQueryData = libPdhDll.NewProc("PdhCollectQueryData")
pdhCollectQueryDataWithTime = libPdhDll.NewProc("PdhCollectQueryDataWithTime")
pdhGetFormattedCounterValue = libPdhDll.NewProc("PdhGetFormattedCounterValue")
pdhGetFormattedCounterArrayW = libPdhDll.NewProc("PdhGetFormattedCounterArrayW")
pdhOpenQuery = libPdhDll.NewProc("PdhOpenQuery")
pdhValidatePathW = libPdhDll.NewProc("PdhValidatePathW")
pdhExpandWildCardPathW = libPdhDll.NewProc("PdhExpandWildCardPathW")
pdhGetCounterInfoW = libPdhDll.NewProc("PdhGetCounterInfoW")
pdhGetRawCounterValue = libPdhDll.NewProc("PdhGetRawCounterValue")
pdhGetRawCounterArrayW = libPdhDll.NewProc("PdhGetRawCounterArrayW")
pdhPdhGetCounterTimeBase = libPdhDll.NewProc("PdhGetCounterTimeBase")
)
// PdhAddCounter adds the specified counter to the query. This is the internationalized version. Preferably, use the
// function PdhAddEnglishCounter instead. hQuery is the query handle, which has been fetched by PdhOpenQuery.
// szFullCounterPath is a full, internationalized counter path (this will differ per Windows language version).
// dwUserData is a 'user-defined value', which becomes part of the counter information. To retrieve this value
// later, call PdhGetCounterInfo() and access dwQueryUserData of the PdhCounterInfo structure.
//
// Examples of szFullCounterPath (in an English version of Windows):
//
// \\Processor(_Total)\\% Idle Time
// \\Processor(_Total)\\% Processor Time
// \\LogicalDisk(C:)\% Free Space
//
// To view all (internationalized...) counters on a system, there are three non-programmatic ways: perfmon utility,
// the typeperf command, and the registry editor. perfmon.exe is perhaps the easiest way, because it's basically a
// full implementation of the pdh.dll API, except with a GUI and all that. The registry setting also provides an
// interface to the available counters, and can be found at the following key:
//
// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\CurrentLanguage
//
// This registry key contains several values as follows:
//
// 1
// 1847
// 2
// System
// 4
// Memory
// 6
// % Processor Time
// ... many, many more
//
// Somehow, these numeric values can be used as szFullCounterPath too:
//
// \2\6 will correspond to \\System\% Processor Time
//
// The typeperf command may also be pretty easy. To find all performance counters, simply execute:
//
// typeperf -qx
func PdhAddCounter(hQuery pdhQueryHandle, szFullCounterPath string, dwUserData uintptr, phCounter *pdhCounterHandle) uint32 {
ptxt, _ := windows.UTF16PtrFromString(szFullCounterPath)
ret, _, _ := pdhAddCounterW.Call(
uintptr(hQuery),
uintptr(unsafe.Pointer(ptxt)),
dwUserData,
uintptr(unsafe.Pointer(phCounter)))
return uint32(ret)
}
// PdhAddEnglishCounterSupported returns true if PdhAddEnglishCounterW Win API function was found in pdh.dll.
// PdhAddEnglishCounterW function is not supported on pre-Windows Vista systems.
func PdhAddEnglishCounterSupported() bool {
return pdhAddEnglishCounterW != nil
}
// PdhAddEnglishCounter adds the specified language-neutral counter to the query. See the PdhAddCounter function. This function only exists on
// Windows versions higher than Vista.
func PdhAddEnglishCounter(hQuery pdhQueryHandle, szFullCounterPath string, dwUserData uintptr, phCounter *pdhCounterHandle) uint32 {
if pdhAddEnglishCounterW == nil {
return ErrorInvalidFunction
}
ptxt, _ := windows.UTF16PtrFromString(szFullCounterPath)
ret, _, _ := pdhAddEnglishCounterW.Call(
uintptr(hQuery),
uintptr(unsafe.Pointer(ptxt)),
dwUserData,
uintptr(unsafe.Pointer(phCounter)))
return uint32(ret)
}
// PdhCloseQuery closes all counters contained in the specified query, closes all handles related to the query,
// and frees all memory associated with the query.
func PdhCloseQuery(hQuery pdhQueryHandle) uint32 {
ret, _, _ := pdhCloseQuery.Call(uintptr(hQuery))
return uint32(ret)
}
// PdhCollectQueryData collects the current raw data value for all counters in the specified query and updates the status
// code of each counter. With some counters, this function needs to be repeatedly called before the value
// of the counter can be extracted with PdhGetFormattedCounterValue(). For example, the following code
// requires at least two calls:
//
// var handle win.PDH_HQUERY
// var counterHandle win.PDH_HCOUNTER
// ret := win.PdhOpenQuery(0, 0, &handle)
// ret = win.PdhAddEnglishCounter(handle, "\\Processor(_Total)\\% Idle Time", 0, &counterHandle)
// var derp win.PDH_FMT_COUNTERVALUE_DOUBLE
//
// ret = win.PdhCollectQueryData(handle)
// fmt.Printf("Collect return code is %x\n", ret) // return code will be PDH_CSTATUS_INVALID_DATA
// ret = win.PdhGetFormattedCounterValueDouble(counterHandle, 0, &derp)
//
// ret = win.PdhCollectQueryData(handle)
// fmt.Printf("Collect return code is %x\n", ret) // return code will be ERROR_SUCCESS
// ret = win.PdhGetFormattedCounterValueDouble(counterHandle, 0, &derp)
//
// The PdhCollectQueryData will return an error in the first call because it needs two values for
// displaying the correct data for the processor idle time. The second call will have a 0 return code.
func PdhCollectQueryData(hQuery pdhQueryHandle) uint32 {
ret, _, _ := pdhCollectQueryData.Call(uintptr(hQuery))
return uint32(ret)
}
// PdhCollectQueryDataWithTime queries data from perfmon, retrieving the device/windows timestamp from the node it was collected on.
// Converts the filetime structure to a GO time class and returns the native time.
func PdhCollectQueryDataWithTime(hQuery pdhQueryHandle) (uint32, time.Time) {
var localFileTime windows.Filetime
ret, _, _ := pdhCollectQueryDataWithTime.Call(uintptr(hQuery), uintptr(unsafe.Pointer(&localFileTime)))
if ret == ErrorSuccess {
var utcFileTime windows.Filetime
if ret := kernel32.LocalFileTimeToFileTime(&localFileTime, &utcFileTime); ret == 0 {
return uint32(ErrorFailure), time.Now()
}
retTime := time.Unix(0, utcFileTime.Nanoseconds())
return uint32(ErrorSuccess), retTime
}
return uint32(ret), time.Now()
}
// PdhGetFormattedCounterValueDouble formats the given hCounter using a 'double'. The result is set into the specialized union struct pValue.
// This function does not directly translate to a Windows counterpart due to union specialization tricks.
func PdhGetFormattedCounterValueDouble(hCounter pdhCounterHandle, lpdwType *uint32, pValue *PdhFmtCountervalueDouble) uint32 {
ret, _, _ := pdhGetFormattedCounterValue.Call(
uintptr(hCounter),
uintptr(PdhFmtDouble|PdhFmtNocap100),
uintptr(unsafe.Pointer(lpdwType)),
uintptr(unsafe.Pointer(pValue)))
return uint32(ret)
}
// PdhGetFormattedCounterArrayDouble returns an array of formatted counter values. Use this function when you want to format the counter values of a
// counter that contains a wildcard character for the instance name. The itemBuffer must a slice of type PdhFmtCountervalueItemDouble.
// An example of how this function can be used:
//
// okPath := "\\Process(*)\\% Processor Time" // notice the wildcard * character
//
// // omitted all necessary stuff ...
//
// var bufSize uint32
// var bufCount uint32
// var size uint32 = uint32(unsafe.Sizeof(win.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE{}))
// var emptyBuf [1]win.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE // need at least 1 addressable null ptr.
//
// for {
// // collect
// ret := win.PdhCollectQueryData(queryHandle)
// if ret == win.ERROR_SUCCESS {
// ret = win.PdhGetFormattedCounterArrayDouble(counterHandle, &bufSize, &bufCount, &emptyBuf[0]) // uses null ptr here according to MSDN.
// if ret == win.PDH_MORE_DATA {
// filledBuf := make([]win.PDH_FMT_COUNTERVALUE_ITEM_DOUBLE, bufCount*size)
// ret = win.PdhGetFormattedCounterArrayDouble(counterHandle, &bufSize, &bufCount, &filledBuf[0])
// for i := 0; i < int(bufCount); i++ {
// c := filledBuf[i]
// var s string = win.UTF16PtrToString(c.SzName)
// fmt.Printf("Index %d -> %s, value %v\n", i, s, c.FmtValue.DoubleValue)
// }
//
// filledBuf = nil
// // Need to at least set bufSize to zero, because if not, the function will not
// // return PDH_MORE_DATA and will not set the bufSize.
// bufCount = 0
// bufSize = 0
// }
//
// time.Sleep(2000 * time.Millisecond)
// }
// }
func PdhGetFormattedCounterArrayDouble(hCounter pdhCounterHandle, lpdwBufferSize *uint32, lpdwBufferCount *uint32, itemBuffer *byte) uint32 {
ret, _, _ := pdhGetFormattedCounterArrayW.Call(
uintptr(hCounter),
uintptr(PdhFmtDouble|PdhFmtNocap100),
uintptr(unsafe.Pointer(lpdwBufferSize)),
uintptr(unsafe.Pointer(lpdwBufferCount)),
uintptr(unsafe.Pointer(itemBuffer)))
return uint32(ret)
}
// PdhOpenQuery creates a new query that is used to manage the collection of performance data.
// szDataSource is a null terminated string that specifies the name of the log file from which to
// retrieve the performance data. If 0, performance data is collected from a real-time data source.
// dwUserData is a user-defined value to associate with this query. To retrieve the user data later,
// call PdhGetCounterInfo and access dwQueryUserData of the PdhCounterInfo structure. phQuery is
// the handle to the query, and must be used in subsequent calls. This function returns a PDH_
// constant error code, or ErrorSuccess if the call succeeded.
func PdhOpenQuery(szDataSource uintptr, dwUserData uintptr, phQuery *pdhQueryHandle) uint32 {
ret, _, _ := pdhOpenQuery.Call(
szDataSource,
dwUserData,
uintptr(unsafe.Pointer(phQuery)))
return uint32(ret)
}
// PdhExpandWildCardPath examines the specified computer or log file and returns those counter paths that match the given counter path
// which contains wildcard characters. The general counter path format is as follows:
//
// \\computer\object(parent/instance#index)\counter
//
// The parent, instance, index, and counter components of the counter path may contain either a valid name or a wildcard character.
// The computer, parent, instance, and index components are not necessary for all counters.
//
// The following is a list of the possible formats:
//
// \\computer\object(parent/instance#index)\counter
// \\computer\object(parent/instance)\counter
// \\computer\object(instance#index)\counter
// \\computer\object(instance)\counter
// \\computer\object\counter
// \object(parent/instance#index)\counter
// \object(parent/instance)\counter
// \object(instance#index)\counter
// \object(instance)\counter
// \object\counter
// Use an asterisk (*) as the wildcard character, for example, \object(*)\counter.
//
// If a wildcard character is specified in the parent name, all instances of the specified object
// that match the specified instance and counter fields will be returned.
// For example, \object(*/instance)\counter.
//
// If a wildcard character is specified in the instance name, all instances of the specified object and parent object will be returned if all instance names
// corresponding to the specified index match the wildcard character. For example, \object(parent/*)\counter.
// If the object does not contain an instance, an error occurs.
//
// If a wildcard character is specified in the counter name, all counters of the specified object are returned.
//
// Partial counter path string matches (for example, "pro*") are supported.
func PdhExpandWildCardPath(szWildCardPath string, mszExpandedPathList *uint16, pcchPathListLength *uint32) uint32 {
ptxt, _ := windows.UTF16PtrFromString(szWildCardPath)
flags := uint32(0) // expand instances and counters
ret, _, _ := pdhExpandWildCardPathW.Call(
0, // search counters on local computer
uintptr(unsafe.Pointer(ptxt)),
uintptr(unsafe.Pointer(mszExpandedPathList)),
uintptr(unsafe.Pointer(pcchPathListLength)),
uintptr(unsafe.Pointer(&flags)))
return uint32(ret)
}
// PdhValidatePath validates a path. Will return ErrorSuccess when ok, or PdhCstatusBadCountername when the path is erroneous.
func PdhValidatePath(path string) uint32 {
ptxt, _ := windows.UTF16PtrFromString(path)
ret, _, _ := pdhValidatePathW.Call(uintptr(unsafe.Pointer(ptxt)))
return uint32(ret)
}
func PdhFormatError(msgID uint32) string {
var flags uint32 = windows.FORMAT_MESSAGE_FROM_HMODULE | windows.FORMAT_MESSAGE_ARGUMENT_ARRAY | windows.FORMAT_MESSAGE_IGNORE_INSERTS
buf := make([]uint16, 300)
_, err := windows.FormatMessage(flags, libPdhDll.Handle(), msgID, 0, buf, nil)
if err == nil {
return windows.UTF16PtrToString(&buf[0])
}
return fmt.Sprintf("(pdhErr=%d) %s", msgID, err.Error())
}
// PdhGetCounterInfo retrieves information about a counter, such as data size, counter type, path, and user-supplied data values
// hCounter [in]
// Handle of the counter from which you want to retrieve information. The PdhAddCounter function returns this handle.
//
// bRetrieveExplainText [in]
// Determines whether explain text is retrieved. If you set this parameter to TRUE, the explain text for the counter is retrieved.
// If you set this parameter to FALSE, the field in the returned buffer is NULL.
//
// pdwBufferSize [in, out]
// Size of the lpBuffer buffer, in bytes. If zero on input, the function returns PdhMoreData and sets this parameter to the required buffer size.
// If the buffer is larger than the required size, the function sets this parameter to the actual size of the buffer that was used.
// If the specified size on input is greater than zero but less than the required size, you should not rely on the returned size to reallocate the buffer.
//
// lpBuffer [out]
// Caller-allocated buffer that receives a PdhCounterInfo structure.
// The structure is variable-length, because the string data is appended to the end of the fixed-format portion of the structure.
// This is done so that all data is returned in a single buffer allocated by the caller. Set to NULL if pdwBufferSize is zero.
func PdhGetCounterInfo(hCounter pdhCounterHandle, bRetrieveExplainText int, pdwBufferSize *uint32, lpBuffer *byte) uint32 {
ret, _, _ := pdhGetCounterInfoW.Call(
uintptr(hCounter),
uintptr(bRetrieveExplainText),
uintptr(unsafe.Pointer(pdwBufferSize)),
uintptr(unsafe.Pointer(lpBuffer)))
return uint32(ret)
}
// PdhGetRawCounterValue returns the current raw value of the counter.
// If the specified counter instance does not exist, this function will return ErrorSuccess
// and the CStatus member of the PdhRawCounter structure will contain PdhCstatusNoInstance.
//
// hCounter [in]
// Handle of the counter from which to retrieve the current raw value. The PdhAddCounter function returns this handle.
//
// lpdwType [out]
// Receives the counter type. For a list of counter types, see the Counter Types section of the Windows Server 2003 Deployment Kit.
// This parameter is optional.
//
// pValue [out]
// A PdhRawCounter structure that receives the counter value.
func PdhGetRawCounterValue(hCounter pdhCounterHandle, lpdwType *uint32, pValue *PdhRawCounter) uint32 {
ret, _, _ := pdhGetRawCounterValue.Call(
uintptr(hCounter),
uintptr(unsafe.Pointer(lpdwType)),
uintptr(unsafe.Pointer(pValue)))
return uint32(ret)
}
// PdhGetRawCounterArray returns an array of raw values from the specified counter. Use this function when you want to retrieve the raw counter values
// of a counter that contains a wildcard character for the instance name.
// hCounter
// Handle of the counter for whose current raw instance values you want to retrieve. The PdhAddCounter function returns this handle.
//
// lpdwBufferSize
// Size of the ItemBuffer buffer, in bytes. If zero on input, the function returns PdhMoreData and sets this parameter to the required buffer size.
// If the buffer is larger than the required size, the function sets this parameter to the actual size of the buffer that was used.
// If the specified size on input is greater than zero but less than the required size, you should not rely on the returned size to reallocate the buffer.
//
// lpdwItemCount
// Number of raw counter values in the ItemBuffer buffer.
//
// ItemBuffer
// Caller-allocated buffer that receives the array of PdhRawCounterItem structures; the structures contain the raw instance counter values.
// Set to NULL if lpdwBufferSize is zero.
func PdhGetRawCounterArray(hCounter pdhCounterHandle, lpdwBufferSize *uint32, lpdwBufferCount *uint32, itemBuffer *byte) uint32 {
ret, _, _ := pdhGetRawCounterArrayW.Call(
uintptr(hCounter),
uintptr(unsafe.Pointer(lpdwBufferSize)),
uintptr(unsafe.Pointer(lpdwBufferCount)),
uintptr(unsafe.Pointer(itemBuffer)))
return uint32(ret)
}
// PdhGetCounterTimeBase returns the time base of the specified counter.
// hCounter
// Handle of the counter for whose current raw instance values you want to retrieve. The PdhAddCounter function returns this handle.
//
// lpdwItemCount
// Time base that specifies the number of performance values a counter samples per second.
func PdhGetCounterTimeBase(hCounter pdhCounterHandle, pTimeBase *float64) uint32 {
ret, _, _ := pdhPdhGetCounterTimeBase.Call(
uintptr(hCounter),
uintptr(unsafe.Pointer(pTimeBase)))
return uint32(ret)
}

143
pkg/perfdata/pdh_amd64.go Normal file
View File

@@ -0,0 +1,143 @@
// Copyright (c) 2010-2024 The win Authors. All rights reserved.
// Copyright (c) 2024 The prometheus-community Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. The names of the authors may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// This is the official list of 'win' authors for copyright purposes.
//
// Alexander Neumann <an2048@googlemail.com>
// Joseph Watson <jtwatson@linux-consulting.us>
// Kevin Pors <krpors@gmail.com>
//go:build windows
package perfdata
import "golang.org/x/sys/windows"
// PdhFmtCountervalueDouble is a union specialization for double values.
type PdhFmtCountervalueDouble struct {
CStatus uint32
DoubleValue float64
}
// PdhFmtCounterValueLarge is a union specialization for 64-bit integer values.
type PdhFmtCounterValueLarge struct {
CStatus uint32
LargeValue int64
}
// PdhFmtCounterValueLong is a union specialization for long values.
type PdhFmtCounterValueLong struct {
CStatus uint32
LongValue int32
padding [4]byte //nolint:unused // Memory reservation
}
// PdhFmtCountervalueItemDouble is a union specialization for double values, used by PdhGetFormattedCounterArrayDouble.
type PdhFmtCountervalueItemDouble struct {
SzName *uint16
FmtValue PdhFmtCountervalueDouble
}
// PdhFmtCounterValueItemLarge is a union specialization for 'large' values, used by PdhGetFormattedCounterArrayLarge().
type PdhFmtCounterValueItemLarge struct {
SzName *uint16 // pointer to a string
FmtValue PdhFmtCounterValueLarge
}
// PdhFmtCounterValueItemLong is a union specialization for long values, used by PdhGetFormattedCounterArrayLong().
type PdhFmtCounterValueItemLong struct {
SzName *uint16 // pointer to a string
FmtValue PdhFmtCounterValueLong
}
// PdhCounterInfo structure contains information describing the properties of a counter. This information also includes the counter path.
type PdhCounterInfo struct {
// Size of the structure, including the appended strings, in bytes.
DwLength uint32
// Counter type. For a list of counter types,
// see the Counter Types section of the <a "href=http://go.microsoft.com/fwlink/p/?linkid=84422">Windows Server 2003 Deployment Kit</a>.
// The counter type constants are defined in Winperf.h.
DwType uint32
// Counter version information. Not used.
CVersion uint32
// Counter status that indicates if the counter value is valid. For a list of possible values,
// see <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa371894(v=vs.85).aspx">Checking PDH Interface Return Values</a>.
CStatus uint32
// Scale factor to use when computing the displayable value of the counter. The scale factor is a power of ten.
// The valid range of this parameter is PDH_MIN_SCALE (7) (the returned value is the actual value times 10⁷) to
// Pdh_MAX_SCALE (+7) (the returned value is the actual value times 10⁺⁷). A value of zero will set the scale to one, so that the actual value is returned.
LScale int32
// Default scale factor as suggested by the counter's provider.
LDefaultScale int32
// The value passed in the dwUserData parameter when calling PdhAddCounter.
DwUserData *uint32
// The value passed in the dwUserData parameter when calling PdhOpenQuery.
DwQueryUserData *uint32
// Null-terminated string that specifies the full counter path. The string follows this structure in memory.
SzFullPath *uint16 // pointer to a string
// Null-terminated string that contains the name of the computer specified in the counter path. Is NULL, if the path does not specify a computer.
// The string follows this structure in memory.
SzMachineName *uint16 // pointer to a string
// Null-terminated string that contains the name of the performance object specified in the counter path. The string follows this structure in memory.
SzObjectName *uint16 // pointer to a string
// Null-terminated string that contains the name of the object instance specified in the counter path. Is NULL, if the path does not specify an instance.
// The string follows this structure in memory.
SzInstanceName *uint16 // pointer to a string
// Null-terminated string that contains the name of the parent instance specified in the counter path.
// Is NULL, if the path does not specify a parent instance. The string follows this structure in memory.
SzParentInstance *uint16 // pointer to a string
// Instance index specified in the counter path. Is 0, if the path does not specify an instance index.
DwInstanceIndex uint32 // pointer to a string
// Null-terminated string that contains the counter name. The string follows this structure in memory.
SzCounterName *uint16 // pointer to a string
// Help text that describes the counter. Is NULL if the source is a log file.
SzExplainText *uint16 // pointer to a string
// Start of the string data that is appended to the structure.
DataBuffer [1]uint32 // pointer to an extra space
}
// The PdhRawCounter structure returns the data as it was collected from the counter provider.
// No translation, formatting, or other interpretation is performed on the data.
type PdhRawCounter struct {
// Counter status that indicates if the counter value is valid. Check this member before using the data in a calculation or displaying its value.
// For a list of possible values, see https://docs.microsoft.com/windows/desktop/PerfCtrs/checking-pdh-interface-return-values
CStatus uint32
// Local time for when the data was collected
TimeStamp windows.Filetime
// First raw counter value.
FirstValue int64
// Second raw counter value. Rate counters require two values in order to compute a displayable value.
SecondValue int64
// If the counter type contains the PERF_MULTI_COUNTER flag, this member contains the additional counter data used in the calculation.
// For example, the PERF_100NSEC_MULTI_TIMER counter type contains the PERF_MULTI_COUNTER flag.
MultiCount uint32
}
type PdhRawCounterItem struct {
// Pointer to a null-terminated string that specifies the instance name of the counter. The string is appended to the end of this structure.
SzName *uint16
// A PdhRawCounter structure that contains the raw counter value of the instance
RawValue PdhRawCounter
}

143
pkg/perfdata/pdh_arm64.go Normal file
View File

@@ -0,0 +1,143 @@
// Copyright (c) 2010-2024 The win Authors. All rights reserved.
// Copyright (c) 2024 The prometheus-community Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. The names of the authors may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// This is the official list of 'win' authors for copyright purposes.
//
// Alexander Neumann <an2048@googlemail.com>
// Joseph Watson <jtwatson@linux-consulting.us>
// Kevin Pors <krpors@gmail.com>
//go:build windows
package perfdata
import "golang.org/x/sys/windows"
// PdhFmtCountervalueDouble is a union specialization for double values.
type PdhFmtCountervalueDouble struct {
CStatus uint32
DoubleValue float64
}
// PdhFmtCounterValueLarge is a union specialization for 64-bit integer values.
type PdhFmtCountervalueLarge struct {
CStatus uint32
LargeValue int64
}
// PdhFmtCounterValueLong is a union specialization for long values.
type PdhFmtCountervalueLong struct {
CStatus uint32
LongValue int32
padding [4]byte //nolint:unused // Memory reservation
}
type PdhFmtCountervalueItemDouble struct {
SzName *uint16
FmtValue PdhFmtCountervalueDouble
}
// PdhFmtCounterValueItemLarge is a union specialization for 'large' values, used by PdhGetFormattedCounterArrayLarge().
type PdhFmtCountervalueItemLarge struct {
SzName *uint16 // pointer to a string
FmtValue PdhFmtCountervalueLarge
}
// PdhFmtCounterValueItemLong is a union specialization for long values, used by PdhGetFormattedCounterArrayLong().
type PdhFmtCountervalueItemLong struct {
SzName *uint16 // pointer to a string
FmtValue PdhFmtCountervalueLong
}
// PdhCounterInfo structure contains information describing the properties of a counter. This information also includes the counter path.
type PdhCounterInfo struct {
// Size of the structure, including the appended strings, in bytes.
DwLength uint32
// Counter type. For a list of counter types, see the Counter Types section
// of the Windows Server 2003 Deployment Kit (http://go.microsoft.com/fwlink/p/?linkid=84422).
// The counter type constants are defined in Winperf.h.
DwType uint32
// Counter version information. Not used.
CVersion uint32
// Counter status that indicates if the counter value is valid. For a list of possible values,
// see <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa371894(v=vs.85).aspx">Checking PDH Interface Return Values</a>.
CStatus uint32
// Scale factor to use when computing the displayable value of the counter. The scale factor is a power of ten.
// The valid range of this parameter is PDH_MIN_SCALE (7) (the returned value is the actual value times 10⁷) to
// Pdh_MAX_SCALE (+7) (the returned value is the actual value times 10⁺⁷). A value of zero will set the scale to one, so that the actual value is returned.
LScale int32
// Default scale factor as suggested by the counter's provider.
LDefaultScale int32
// The value passed in the dwUserData parameter when calling PdhAddCounter.
DwUserData *uint32
// The value passed in the dwUserData parameter when calling PdhOpenQuery.
DwQueryUserData *uint32
// Null-terminated string that specifies the full counter path. The string follows this structure in memory.
SzFullPath *uint16 // pointer to a string
// Null-terminated string that contains the name of the computer specified in the counter path. Is NULL, if the path does not specify a computer.
// The string follows this structure in memory.
SzMachineName *uint16 // pointer to a string
// Null-terminated string that contains the name of the performance object specified in the counter path. The string follows this structure in memory.
SzObjectName *uint16 // pointer to a string
// Null-terminated string that contains the name of the object instance specified in the counter path. Is NULL, if the path does not specify an instance.
// The string follows this structure in memory.
SzInstanceName *uint16 // pointer to a string
// Null-terminated string that contains the name of the parent instance specified in the counter path.
// Is NULL, if the path does not specify a parent instance.
// The string follows this structure in memory.
SzParentInstance *uint16 // pointer to a string
// Instance index specified in the counter path. Is 0, if the path does not specify an instance index.
DwInstanceIndex uint32 // pointer to a string
// Null-terminated string that contains the counter name. The string follows this structure in memory.
SzCounterName *uint16 // pointer to a string
// Help text that describes the counter. Is NULL if the source is a log file.
SzExplainText *uint16 // pointer to a string
// Start of the string data that is appended to the structure.
DataBuffer [1]uint32 // pointer to an extra space
}
// The PdhRawCounter structure returns the data as it was collected from the counter provider.
// No translation, formatting, or other interpretation is performed on the data.
type PdhRawCounter struct {
// Counter status that indicates if the counter value is valid. Check this member before using the data in a calculation or displaying its value.
// For a list of possible values, see https://docs.microsoft.com/windows/desktop/PerfCtrs/checking-pdh-interface-return-values
CStatus uint32
// Local time for when the data was collected
TimeStamp windows.Filetime
// First raw counter value.
FirstValue int64
// Second raw counter value. Rate counters require two values in order to compute a displayable value.
SecondValue int64
// If the counter type contains the PERF_MULTI_COUNTER flag, this member contains the additional counter data used in the calculation.
// For example, the PERF_100NSEC_MULTI_TIMER counter type contains the PERF_MULTI_COUNTER flag.
MultiCount uint32
}
type PdhRawCounterItem struct {
// Pointer to a null-terminated string that specifies the instance name of the counter. The string is appended to the end of this structure.
SzName *uint16
// A PdhRawCounter structure that contains the raw counter value of the instance
RawValue PdhRawCounter
}