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

windows/perfmon fix for There is more data to return than will fit in the supplied buffer #20630

Merged
merged 12 commits into from
Aug 24, 2020
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
6 changes: 6 additions & 0 deletions metricbeat/helper/windows/pdh/pdh_query_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion metricbeat/module/windows/perfmon/perfmon.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 8 additions & 1 deletion metricbeat/module/windows/perfmon/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down