Skip to content

Commit

Permalink
[7.17](backport #32305) Changed collection method of the second count…
Browse files Browse the repository at this point in the history
…er value in the Windows Perfmon module of Metricbeat (#32992)

* Changed collection method of the second counter value in the Windows Perfmon module of Metricbeat (#32305)

* changed collection method of the second counter value required to create a displayable value

Co-authored-by: Craig MacKenzie <[email protected]>
Co-authored-by: Dan Kortschak <[email protected]>
Co-authored-by: Tiago Queiroz <[email protected]>
(cherry picked from commit f0bc6c8)

# Conflicts:
#	metricbeat/module/windows/perfmon/reader.go

* Resolve merge conflicts.

Co-authored-by: Jørgen Taule <[email protected]>
Co-authored-by: Craig MacKenzie <[email protected]>
  • Loading branch information
3 people authored Sep 9, 2022
1 parent 40f67f3 commit 42d3bf0
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 47 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d

*Metricbeat*

- in module/windows/perfmon, changed collection method of the second counter value required to create a displayable value {pull}32305[32305]
- Fix and improve AWS metric period calculation to avoid zero-length intervals {pull}32724[32724]

*Packetbeat*
Expand Down
66 changes: 19 additions & 47 deletions metricbeat/module/windows/perfmon/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,11 @@ import (
"fmt"
"regexp"
"strings"
"time"
"unicode"

"github.com/elastic/beats/v7/metricbeat/helper/windows/pdh"

"github.com/pkg/errors"

"math/rand"

"golang.org/x/sys/windows"

"github.com/elastic/beats/v7/libbeat/logp"
"github.com/elastic/beats/v7/metricbeat/helper/windows/pdh"
"github.com/elastic/beats/v7/metricbeat/mb"
)

Expand All @@ -52,7 +46,6 @@ type Reader struct {
log *logp.Logger //
config Config // Metricset configuration
counters []PerfCounter
event windows.Handle
}

type PerfCounter struct {
Expand All @@ -72,18 +65,13 @@ func NewReader(config Config) (*Reader, error) {
if err := query.Open(); err != nil {
return nil, err
}
event, err := windows.CreateEvent(nil, 0, 0, nil)
if err != nil {
return nil, err
}
r := &Reader{
query: query,
log: logp.NewLogger("perfmon"),
config: config,
event: event,
}
r.mapCounters(config)
_, err = r.getCounterPaths()
_, err := r.getCounterPaths()
if err != nil {
return nil, err
}
Expand All @@ -94,11 +82,11 @@ func NewReader(config Config) (*Reader, error) {
func (re *Reader) RefreshCounterPaths() error {
newCounters, err := re.getCounterPaths()
if err != nil {
return errors.Wrap(err, "failed retrieving counter paths")
return fmt.Errorf("failed retrieving counter paths: %w", err)
}
err = re.query.RemoveUnusedCounters(newCounters)
if err != nil {
return errors.Wrap(err, "failed removing unused counter values")
return fmt.Errorf("failed removing unused counter values: %w", err)
}
return nil
}
Expand All @@ -110,17 +98,17 @@ func (re *Reader) Read() ([]mb.Event, error) {
if err := re.query.CollectData(); err != nil {
// users can encounter the case no counters are found (services/processes stopped), this should not generate an event with the error message,
//could be the case the specific services are started after and picked up by the next RefreshCounterPaths func
if err == pdh.PDH_NO_COUNTERS {
if err == pdh.PDH_NO_COUNTERS { //nolint:errorlint // Bad linter! This is always errno or nil.
re.log.Warnf("%s %v", collectFailedMsg, err)
} else {
return nil, errors.Wrap(err, collectFailedMsg)
return nil, fmt.Errorf("%v: %w", collectFailedMsg, err)
}
}

// Get the values.
values, err := re.getValues()
if err != nil {
return nil, errors.Wrap(err, "failed formatting counter values")
return nil, fmt.Errorf("failed formatting counter values: %w", err)
}
var events []mb.Event
// GroupAllCountersTo config option where counters for all instances are aggregated and instance count is added in the event under the string value provided by this option.
Expand All @@ -135,41 +123,25 @@ func (re *Reader) Read() ([]mb.Event, error) {

func (re *Reader) getValues() (map[string][]pdh.CounterValue, error) {
var val map[string][]pdh.CounterValue
var sec uint32 = 1
err := re.query.CollectDataEx(sec, re.event)
// Sleep for one second before collecting the second raw value-
time.Sleep(time.Second)

// Collect the second raw value.
err := re.query.CollectData()
if err != nil {
return nil, err
}
waitFor, err := windows.WaitForSingleObject(re.event, windows.INFINITE)

// Collect the displayable value.
val, err = re.query.GetFormattedCounterValues()
if err != nil {
return nil, err
}
switch waitFor {
case windows.WAIT_OBJECT_0:
val, err = re.query.GetFormattedCounterValues()
if err != nil {
return nil, err
}
case windows.WAIT_FAILED:
return nil, errors.New("WaitForSingleObject has failed")
default:
return nil, errors.New("WaitForSingleObject was abandoned or still waiting for completion")
}
return val, err
}

func randSeq(n int) string {
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
b := make([]rune, n)
for i := range b {
b[i] = letters[rand.Intn(len(letters))]
}
return string(b)
}

// Close will close the PDH query for now.
func (re *Reader) Close() error {
defer windows.CloseHandle(re.event)
return re.query.Close()
}

Expand All @@ -181,23 +153,23 @@ func (re *Reader) getCounterPaths() ([]string, error) {
childQueries, err := re.query.GetCounterPaths(counter.QueryName)
if err != nil {
if re.config.IgnoreNECounters {
switch err {
switch err { //nolint:errorlint // Bad linter! This is always errno or nil.
case pdh.PDH_CSTATUS_NO_COUNTER, pdh.PDH_CSTATUS_NO_COUNTERNAME,
pdh.PDH_CSTATUS_NO_INSTANCE, pdh.PDH_CSTATUS_NO_OBJECT:
re.log.Infow("Ignoring non existent counter", "error", err,
logp.Namespace("perfmon"), "query", counter.QueryName)
continue
}
} else {
return newCounters, errors.Wrapf(err, `failed to expand counter (query="%v")`, counter.QueryName)
return newCounters, fmt.Errorf("failed to expand counter (query='%v'): %w", counter.QueryName, err)
}
}
newCounters = append(newCounters, childQueries...)
// there are cases when the ExpandWildCardPath will retrieve a successful status but not an expanded query so we need to check for the size of the list
if err == nil && len(childQueries) >= 1 && !strings.Contains(childQueries[0], "*") {
for _, v := range childQueries {
if err := re.query.AddCounter(v, counter.InstanceName, counter.Format, isWildcard(childQueries, counter.InstanceName)); err != nil {
return newCounters, errors.Wrapf(err, "failed to add counter (query='%v')", counter.QueryName)
return newCounters, fmt.Errorf("failed to add counter (query='%v'): %w", counter.QueryName, err)
}
re.counters[i].ChildQueries = append(re.counters[i].ChildQueries, v)
}
Expand Down

0 comments on commit 42d3bf0

Please sign in to comment.