From 49e8024953a4edb0c55a06f751bc9deca1b9638a Mon Sep 17 00:00:00 2001 From: Mariana Dima Date: Mon, 24 Aug 2020 13:37:15 +0200 Subject: [PATCH] windows/perfmon fix for `There is more data to return than will fit in the supplied buffer` (#20630) * mofidy doc * fix * changelog --- CHANGELOG.next.asciidoc | 1 + metricbeat/helper/windows/pdh/pdh_query_windows.go | 6 ++++++ metricbeat/module/windows/perfmon/perfmon.go | 2 +- metricbeat/module/windows/perfmon/reader.go | 9 ++++++++- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index 4e0906a12818..2cf2c21d78a0 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -326,6 +326,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d - Add required option for `metrics` in app_insights. {pull}20406[20406] - Groups same timestamp metric values to one event in the app_insights metricset. {pull}20403[20403] - Updates vm_compute metricset with more info on guest metrics. {pull}20448[20448] +- Add fallback for PdhExpandWildCardPathW failing in perfmon metricset. {issue}20139[20139] {pull}20630[20630] - Fix resource tags in aws cloudwatch metricset {issue}20326[20326] {pull}20385[20385] - Fix ec2 disk and network metrics to use Sum statistic method. {pull}20680[20680] - Fill cloud.account.name with accountID if account alias doesn't exist. {pull}20736[20736] diff --git a/metricbeat/helper/windows/pdh/pdh_query_windows.go b/metricbeat/helper/windows/pdh/pdh_query_windows.go index 65ad0372fcb9..3c51df5073a0 100644 --- a/metricbeat/helper/windows/pdh/pdh_query_windows.go +++ b/metricbeat/helper/windows/pdh/pdh_query_windows.go @@ -212,6 +212,12 @@ func (q *Query) ExpandWildCardPath(wildCardPath string) ([]string, error) { expdPaths, err = PdhExpandCounterPath(utfPath) } else { expdPaths, err = PdhExpandWildCardPath(utfPath) + // rarely the PdhExpandWildCardPathW will not retrieve the expanded buffer size initially so the next call will encounter the PDH_MORE_DATA error since the specified size on the input is still less than + // the required size. If this is the case we will fallback on the PdhExpandCounterPathW api since it looks to act in a more stable manner. The PdhExpandCounterPathW api does come with some limitations but will + // satisfy most cases and return valid paths. + if err == PDH_MORE_DATA { + expdPaths, err = PdhExpandCounterPath(utfPath) + } } if err != nil { return nil, err diff --git a/metricbeat/module/windows/perfmon/perfmon.go b/metricbeat/module/windows/perfmon/perfmon.go index 7f4712a5f3b2..52865a281074 100644 --- a/metricbeat/module/windows/perfmon/perfmon.go +++ b/metricbeat/module/windows/perfmon/perfmon.go @@ -61,7 +61,7 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { func (m *MetricSet) Fetch(report mb.ReporterV2) error { // if the ignore_non_existent_counters flag is set and no valid counter paths are found the Read func will still execute, a check is done before if len(m.reader.query.Counters) == 0 { - return errors.New("no counters to read") + m.log.Error("no counter paths were found") } // refresh performance counter list diff --git a/metricbeat/module/windows/perfmon/reader.go b/metricbeat/module/windows/perfmon/reader.go index c65c4a8118ae..6f90b18e3489 100644 --- a/metricbeat/module/windows/perfmon/reader.go +++ b/metricbeat/module/windows/perfmon/reader.go @@ -38,6 +38,7 @@ const ( defaultInstanceField = "instance" defaultObjectField = "object" replaceUpperCaseRegex = `(?:[^A-Z_\W])([A-Z])[^A-Z]` + collectFailedMsg = "failed collecting counter values" ) // Reader will contain the config options @@ -152,7 +153,13 @@ func (re *Reader) Read() ([]mb.Event, error) { // Some counters, such as rate counters, require two counter values in order to compute a displayable value. In this case we must call PdhCollectQueryData twice before calling PdhGetFormattedCounterValue. // For more information, see Collecting Performance Data (https://docs.microsoft.com/en-us/windows/desktop/PerfCtrs/collecting-performance-data). if err := re.query.CollectData(); err != nil { - return nil, errors.Wrap(err, "failed querying counter values") + // 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 { + re.log.Warnf("%s %v", collectFailedMsg, err) + } else { + return nil, errors.Wrap(err, collectFailedMsg) + } } // Get the values.