mirror of
https://github.com/prometheus-community/windows_exporter.git
synced 2026-02-15 01:16:35 +00:00
logical_disk: Implement Perfdata collector (#1673)
This commit is contained in:
@@ -2,6 +2,7 @@ package v1
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
@@ -43,11 +44,23 @@ func (c *Collector) Collect() (map[string]map[string]perftypes.CounterValues, er
|
||||
return nil, fmt.Errorf("QueryPerformanceData: %w", err)
|
||||
}
|
||||
|
||||
if len(perfObjects) == 0 {
|
||||
return map[string]map[string]perftypes.CounterValues{}, nil
|
||||
}
|
||||
|
||||
data := make(map[string]map[string]perftypes.CounterValues, len(perfObjects[0].Instances))
|
||||
|
||||
for _, perfObject := range perfObjects {
|
||||
if perfObject.Name != c.object {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, perfInstance := range perfObject.Instances {
|
||||
instanceName := perfInstance.Name
|
||||
if strings.HasSuffix(instanceName, "_Total") {
|
||||
continue
|
||||
}
|
||||
|
||||
if instanceName == "" || instanceName == "*" {
|
||||
instanceName = perftypes.EmptyInstance
|
||||
}
|
||||
@@ -57,6 +70,10 @@ func (c *Collector) Collect() (map[string]map[string]perftypes.CounterValues, er
|
||||
}
|
||||
|
||||
for _, perfCounter := range perfInstance.Counters {
|
||||
if perfCounter.Def.IsBaseValue && !perfCounter.Def.IsNanosecondCounter {
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := data[instanceName][perfCounter.Def.Name]; !ok {
|
||||
data[instanceName][perfCounter.Def.Name] = perftypes.CounterValues{
|
||||
Type: prometheus.GaugeValue,
|
||||
|
||||
@@ -117,16 +117,16 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/prometheus-community/windows_exporter/internal/perfdata/perftypes"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// TODO: There's a LittleEndian field in the PERF header - we ought to check it.
|
||||
var bo = binary.LittleEndian
|
||||
|
||||
const averageCount64Type = 1073874176
|
||||
|
||||
// PerfObject Top-level performance object (like "Process").
|
||||
type PerfObject struct {
|
||||
Name string
|
||||
@@ -221,13 +221,18 @@ func queryRawData(query string) ([]byte, error) {
|
||||
(*byte)(unsafe.Pointer(&buffer[0])),
|
||||
&bufLen)
|
||||
|
||||
if errors.Is(err, error(windows.ERROR_MORE_DATA)) {
|
||||
switch {
|
||||
case errors.Is(err, error(windows.ERROR_MORE_DATA)):
|
||||
newBuffer := make([]byte, len(buffer)+16384)
|
||||
copy(newBuffer, buffer)
|
||||
buffer = newBuffer
|
||||
|
||||
continue
|
||||
} else if err != nil {
|
||||
case errors.Is(err, error(windows.ERROR_BUSY)):
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
|
||||
continue
|
||||
case err != nil:
|
||||
var errNo windows.Errno
|
||||
if errors.As(err, &errNo) {
|
||||
return nil, fmt.Errorf("ReqQueryValueEx failed: %w errno %d", err, uint(errNo))
|
||||
@@ -349,7 +354,7 @@ func QueryPerformanceData(query string) ([]*PerfObject, error) {
|
||||
IsCounter: def.CounterType&0x400 == 0x400,
|
||||
IsBaseValue: def.CounterType&0x00030000 == 0x00030000,
|
||||
IsNanosecondCounter: def.CounterType&0x00100000 == 0x00100000,
|
||||
HasSecondValue: def.CounterType == averageCount64Type,
|
||||
HasSecondValue: def.CounterType == perftypes.PERF_AVERAGE_BULK,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user