Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(inputs.win_perf_counter): Extend logging #15794

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 42 additions & 30 deletions plugins/inputs/win_perf_counters/performance_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ package win_perf_counters

import (
"errors"
"fmt"
"syscall"
"time"
"unsafe"

"github.com/influxdata/telegraf"
)

// Initial buffer size for return buffers
Expand Down Expand Up @@ -42,6 +45,7 @@ type PerformanceQuery interface {

type PerformanceQueryCreator interface {
NewPerformanceQuery(string, uint32) PerformanceQuery
SetLogger(telegraf.Logger)
}

// PdhError represents error returned from Performance Counters API
Expand All @@ -65,12 +69,19 @@ func NewPdhError(code uint32) error {
type PerformanceQueryImpl struct {
maxBufferSize uint32
query pdhQueryHandle
log telegraf.Logger
}

type PerformanceQueryCreatorImpl struct {
log telegraf.Logger
}

type PerformanceQueryCreatorImpl struct{}
func (m *PerformanceQueryCreatorImpl) NewPerformanceQuery(_ string, maxBufferSize uint32) PerformanceQuery {
return &PerformanceQueryImpl{maxBufferSize: maxBufferSize, log: m.log}
}

func (m PerformanceQueryCreatorImpl) NewPerformanceQuery(_ string, maxBufferSize uint32) PerformanceQuery {
return &PerformanceQueryImpl{maxBufferSize: maxBufferSize}
func (m *PerformanceQueryCreatorImpl) SetLogger(l telegraf.Logger) {
m.log = l
}

// Open creates a new counterPath that is used to manage the collection of performance data.
Expand Down Expand Up @@ -195,38 +206,37 @@ func (m *PerformanceQueryImpl) GetFormattedCounterValueDouble(hCounter pdhCounte
}

func (m *PerformanceQueryImpl) GetFormattedCounterArrayDouble(hCounter pdhCounterHandle) ([]CounterValue, error) {
for buflen := initialBufferSize; buflen <= m.maxBufferSize; buflen *= 2 {
buf := make([]byte, buflen)

// Get the info with the current buffer size
var itemCount uint32
size := buflen
ret := PdhGetFormattedCounterArrayDouble(hCounter, &size, &itemCount, &buf[0])
if ret == ErrorSuccess {
//nolint:gosec // G103: Valid use of unsafe call to create PDH_FMT_COUNTERVALUE_ITEM_DOUBLE
items := (*[1 << 20]PdhFmtCountervalueItemDouble)(unsafe.Pointer(&buf[0]))[:itemCount]
values := make([]CounterValue, 0, itemCount)
for _, item := range items {
if item.FmtValue.CStatus == PdhCstatusValidData || item.FmtValue.CStatus == PdhCstatusNewData {
val := CounterValue{UTF16PtrToString(item.SzName), item.FmtValue.DoubleValue}
values = append(values, val)
}
}
return values, nil
}
// Determine the required buffer size
var itemCount uint32
var buflen uint32
if ret := PdhGetFormattedCounterArrayDouble(hCounter, &buflen, &itemCount, nil); ret != PdhMoreData {
return nil, fmt.Errorf("getting buffer size failed: %w", NewPdhError(ret))
}
if buflen > m.maxBufferSize {
return nil, errBufferLimitReached
}

// Use the size as a hint if it exceeds the current buffer size
if size > buflen {
buflen = size
}
// Do the actual formatting
buf := make([]byte, buflen)
size := buflen
ret := PdhGetFormattedCounterArrayDouble(hCounter, &size, &itemCount, &buf[0])
if ret != ErrorSuccess {
return nil, NewPdhError(ret)
}

// We got a non-recoverable error so exit here
if ret != PdhMoreData {
return nil, NewPdhError(ret)
//nolint:gosec // G103: Valid use of unsafe call to create PDH_FMT_COUNTERVALUE_ITEM_DOUBLE
items := (*[1 << 20]PdhFmtCountervalueItemDouble)(unsafe.Pointer(&buf[0]))[:itemCount]
values := make([]CounterValue, 0, itemCount)
for _, item := range items {
if item.FmtValue.CStatus == PdhCstatusValidData || item.FmtValue.CStatus == PdhCstatusNewData {
v := CounterValue{UTF16PtrToString(item.SzName), item.FmtValue.DoubleValue}
values = append(values, v)
} else {
m.log.Debugf("got status %d for item %+v", item.FmtValue.CStatus, item)
}
}

return nil, errBufferLimitReached
return values, nil
}

func (m *PerformanceQueryImpl) GetRawCounterArray(hCounter pdhCounterHandle) ([]CounterValue, error) {
Expand All @@ -245,6 +255,8 @@ func (m *PerformanceQueryImpl) GetRawCounterArray(hCounter pdhCounterHandle) ([]
if item.RawValue.CStatus == PdhCstatusValidData || item.RawValue.CStatus == PdhCstatusNewData {
val := CounterValue{UTF16PtrToString(item.SzName), item.RawValue.FirstValue}
values = append(values, val)
} else {
m.log.Debugf("got status %d for item %+v", item.RawValue.CStatus, item)
}
}
return values, nil
Expand Down
2 changes: 2 additions & 0 deletions plugins/inputs/win_perf_counters/win_perf_counters.go
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,8 @@ func isKnownCounterDataError(err error) bool {
}

func (m *WinPerfCounters) Init() error {
m.queryCreator.SetLogger(m.Log)

// Check the buffer size
if m.MaxBufferSize < config.Size(initialBufferSize) {
return fmt.Errorf("maximum buffer size should at least be %d", 2*initialBufferSize)
Expand Down
7 changes: 6 additions & 1 deletion plugins/inputs/win_perf_counters/win_perf_counters_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/stretchr/testify/require"

"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/config"
"github.com/influxdata/telegraf/testutil"
)
Expand Down Expand Up @@ -215,7 +216,7 @@ type FakePerformanceQueryCreator struct {
fakeQueries map[string]*FakePerformanceQuery
}

func (m FakePerformanceQueryCreator) NewPerformanceQuery(computer string, _ uint32) PerformanceQuery {
func (m *FakePerformanceQueryCreator) NewPerformanceQuery(computer string, _ uint32) PerformanceQuery {
var ret PerformanceQuery
var ok bool
if ret, ok = m.fakeQueries[computer]; !ok {
Expand All @@ -224,6 +225,8 @@ func (m FakePerformanceQueryCreator) NewPerformanceQuery(computer string, _ uint
return ret
}

func (m *FakePerformanceQueryCreator) SetLogger(telegraf.Logger) {}

//nolint:revive //argument-limit allowed for helper function
func createPerfObject(
computer string,
Expand Down Expand Up @@ -2019,13 +2022,15 @@ func TestNoWildcards(t *testing.T) {
UseWildcardsExpansion: true,
LocalizeWildcardsExpansion: false,
Log: testutil.Logger{},
queryCreator: &PerformanceQueryCreatorImpl{},
}
require.Error(t, m.Init())
m = WinPerfCounters{
Object: createPerfObject("", "measurement", "object?", []string{"instance"}, []string{"counter"}, false, false, false),
UseWildcardsExpansion: true,
LocalizeWildcardsExpansion: false,
Log: testutil.Logger{},
queryCreator: &PerformanceQueryCreatorImpl{},
}
require.Error(t, m.Init())
}
Expand Down
Loading