mirror of
https://github.com/prometheus-community/windows_exporter.git
synced 2026-02-16 09:46:35 +00:00
chore: release 0.29.0.rc0 (#1600)
This commit is contained in:
@@ -31,11 +31,13 @@ type NameTable struct {
|
||||
|
||||
func (t *NameTable) LookupString(index uint32) string {
|
||||
t.initialize()
|
||||
|
||||
return t.table.index[index]
|
||||
}
|
||||
|
||||
func (t *NameTable) LookupIndex(str string) uint32 {
|
||||
t.initialize()
|
||||
|
||||
return t.table.string[str]
|
||||
}
|
||||
|
||||
@@ -56,7 +58,9 @@ func (t *NameTable) initialize() {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
r := bytes.NewReader(buffer)
|
||||
|
||||
for {
|
||||
index, err := readUTF16String(r)
|
||||
if err != nil {
|
||||
|
||||
@@ -119,6 +119,8 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// TODO: There's a LittleEndian field in the PERF header - we ought to check it.
|
||||
@@ -204,7 +206,7 @@ func queryRawData(query string) ([]byte, error) {
|
||||
|
||||
buffer = make([]byte, bufLen)
|
||||
|
||||
name, err := syscall.UTF16PtrFromString(query)
|
||||
name, err := windows.UTF16PtrFromString(query)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to encode query string: %w", err)
|
||||
}
|
||||
@@ -212,21 +214,23 @@ func queryRawData(query string) ([]byte, error) {
|
||||
for {
|
||||
bufLen := uint32(len(buffer))
|
||||
|
||||
//nolint:forbidigo // Legacy Code
|
||||
err := syscall.RegQueryValueEx(
|
||||
syscall.HKEY_PERFORMANCE_DATA,
|
||||
windows.HKEY_PERFORMANCE_DATA,
|
||||
name,
|
||||
nil,
|
||||
&valType,
|
||||
(*byte)(unsafe.Pointer(&buffer[0])),
|
||||
&bufLen)
|
||||
|
||||
if errors.Is(err, error(syscall.ERROR_MORE_DATA)) {
|
||||
if errors.Is(err, error(syscall.ERROR_MORE_DATA)) { //nolint:forbidigo // Legacy Code
|
||||
newBuffer := make([]byte, len(buffer)+16384)
|
||||
copy(newBuffer, buffer)
|
||||
buffer = newBuffer
|
||||
|
||||
continue
|
||||
} else if err != nil {
|
||||
var errNo syscall.Errno
|
||||
var errNo syscall.Errno //nolint:forbidigo // Legacy Code
|
||||
if errors.As(err, &errNo) {
|
||||
return nil, fmt.Errorf("ReqQueryValueEx failed: %w errno %d", err, uint(errNo))
|
||||
}
|
||||
@@ -276,6 +280,7 @@ func QueryPerformanceData(query string) ([]*PerfObject, error) {
|
||||
// Read global header
|
||||
|
||||
header := new(perfDataBlock)
|
||||
|
||||
err = header.BinaryReadFrom(r)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read performance data block for %q with: %w", query, err)
|
||||
@@ -300,6 +305,7 @@ func QueryPerformanceData(query string) ([]*PerfObject, error) {
|
||||
}
|
||||
|
||||
obj := new(perfObjectType)
|
||||
|
||||
err = obj.BinaryReadFrom(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -329,6 +335,7 @@ func QueryPerformanceData(query string) ([]*PerfObject, error) {
|
||||
|
||||
for i := range numCounterDefs {
|
||||
def := new(perfCounterDefinition)
|
||||
|
||||
err := def.BinaryReadFrom(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -410,7 +417,9 @@ func parseCounterBlock(b []byte, r io.ReadSeeker, pos int64, defs []*PerfCounter
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
block := new(perfCounterBlock)
|
||||
|
||||
err = block.BinaryReadFrom(r)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
@@ -453,7 +462,6 @@ func convertCounterValue(counterDef *perfCounterDefinition, buffer []byte, value
|
||||
272696576 64bit rate
|
||||
|
||||
*/
|
||||
|
||||
switch counterDef.CounterSize {
|
||||
case 4:
|
||||
value = int64(bo.Uint32(buffer[valueOffset:(valueOffset + 4)]))
|
||||
|
||||
@@ -3,7 +3,8 @@ package perflib
|
||||
import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
/*
|
||||
@@ -36,7 +37,7 @@ type perfDataBlock struct {
|
||||
HeaderLength uint32
|
||||
NumObjectTypes uint32
|
||||
DefaultObject int32
|
||||
SystemTime syscall.Systemtime
|
||||
SystemTime windows.Systemtime
|
||||
_ uint32 // TODO
|
||||
PerfTime int64
|
||||
PerfFreq int64
|
||||
|
||||
@@ -3,11 +3,9 @@ package perflib
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
)
|
||||
|
||||
// Conversion factors.
|
||||
@@ -16,14 +14,16 @@ const (
|
||||
WindowsEpoch = 116444736000000000
|
||||
)
|
||||
|
||||
func UnmarshalObject(obj *PerfObject, vs interface{}, logger log.Logger) error {
|
||||
func UnmarshalObject(obj *PerfObject, vs interface{}, logger *slog.Logger) error {
|
||||
if obj == nil {
|
||||
return errors.New("counter not found")
|
||||
}
|
||||
|
||||
rv := reflect.ValueOf(vs)
|
||||
if rv.Kind() != reflect.Ptr || rv.IsNil() {
|
||||
return fmt.Errorf("%v is nil or not a pointer to slice", reflect.TypeOf(vs))
|
||||
}
|
||||
|
||||
ev := rv.Elem()
|
||||
if ev.Kind() != reflect.Slice {
|
||||
return fmt.Errorf("%v is not slice", reflect.TypeOf(vs))
|
||||
@@ -40,6 +40,7 @@ func UnmarshalObject(obj *PerfObject, vs interface{}, logger log.Logger) error {
|
||||
rt := target.Type()
|
||||
|
||||
counters := make(map[string]*PerfCounter, len(instance.Counters))
|
||||
|
||||
for _, ctr := range instance.Counters {
|
||||
if ctr.Def.IsBaseValue && !ctr.Def.IsNanosecondCounter {
|
||||
counters[ctr.Def.Name+"_Base"] = ctr
|
||||
@@ -50,10 +51,12 @@ func UnmarshalObject(obj *PerfObject, vs interface{}, logger log.Logger) error {
|
||||
|
||||
for i := range target.NumField() {
|
||||
f := rt.Field(i)
|
||||
|
||||
tag := f.Tag.Get("perflib")
|
||||
if tag == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
secondValue := false
|
||||
|
||||
st := strings.Split(tag, ",")
|
||||
@@ -67,12 +70,15 @@ func UnmarshalObject(obj *PerfObject, vs interface{}, logger log.Logger) error {
|
||||
|
||||
ctr, found := counters[tag]
|
||||
if !found {
|
||||
_ = level.Debug(logger).Log("msg", fmt.Sprintf("missing counter %q, have %v", tag, counterMapKeys(counters)))
|
||||
logger.Debug(fmt.Sprintf("missing counter %q, have %v", tag, counterMapKeys(counters)))
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if !target.Field(i).CanSet() {
|
||||
return fmt.Errorf("tagged field %v cannot be written to", f.Name)
|
||||
}
|
||||
|
||||
if fieldType := target.Field(i).Type(); fieldType != reflect.TypeOf((*float64)(nil)).Elem() {
|
||||
return fmt.Errorf("tagged field %v has wrong type %v, must be float64", f.Name, fieldType)
|
||||
}
|
||||
@@ -81,7 +87,9 @@ func UnmarshalObject(obj *PerfObject, vs interface{}, logger log.Logger) error {
|
||||
if !ctr.Def.HasSecondValue {
|
||||
return fmt.Errorf("tagged field %v expected a SecondValue, which was not present", f.Name)
|
||||
}
|
||||
|
||||
target.Field(i).SetFloat(float64(ctr.SecondValue))
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -108,5 +116,6 @@ func counterMapKeys(m map[string]*PerfCounter) []string {
|
||||
for k := range m {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
|
||||
return keys
|
||||
}
|
||||
|
||||
@@ -3,12 +3,14 @@ package perflib
|
||||
import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// readUTF16StringAtPos Read an unterminated UTF16 string at a given position, specifying its length.
|
||||
func readUTF16StringAtPos(r io.ReadSeeker, absPos int64, length uint32) (string, error) {
|
||||
value := make([]uint16, length/2)
|
||||
|
||||
_, err := r.Seek(absPos, io.SeekStart)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -19,7 +21,7 @@ func readUTF16StringAtPos(r io.ReadSeeker, absPos int64, length uint32) (string,
|
||||
return "", err
|
||||
}
|
||||
|
||||
return syscall.UTF16ToString(value), nil
|
||||
return windows.UTF16ToString(value), nil
|
||||
}
|
||||
|
||||
// readUTF16String Reads a null-terminated UTF16 string at the current offset.
|
||||
@@ -43,5 +45,5 @@ func readUTF16String(r io.Reader) (string, error) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return syscall.UTF16ToString(out), nil
|
||||
return windows.UTF16ToString(out), nil
|
||||
}
|
||||
|
||||
@@ -18,5 +18,6 @@ func GetPerflibSnapshot(objNames string) (map[string]*PerfObject, error) {
|
||||
for _, obj := range objects {
|
||||
indexed[obj.Name] = obj
|
||||
}
|
||||
|
||||
return indexed, nil
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package perflib
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log/slog"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/go-kit/log"
|
||||
)
|
||||
|
||||
type simple struct {
|
||||
@@ -114,11 +114,14 @@ func TestUnmarshalPerflib(t *testing.T) {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
logger := slog.New(slog.NewTextHandler(io.Discard, nil))
|
||||
output := make([]simple, 0)
|
||||
err := UnmarshalObject(c.obj, &output, log.NewNopLogger())
|
||||
|
||||
err := UnmarshalObject(c.obj, &output, logger)
|
||||
if err != nil && !c.expectError {
|
||||
t.Errorf("Did not expect error, got %q", err)
|
||||
}
|
||||
|
||||
if err == nil && c.expectError {
|
||||
t.Errorf("Expected an error, but got ok")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user