diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index 0dcde461329..70d010904b7 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -236,6 +236,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d *Metricbeat* +- Move the windows pdh implementation from perfmon to a shared location in order for future modules/metricsets to make use of. {pull}15503[15503] - Add lambda metricset in aws module. {pull}15260[15260] - Expand data for the `system/memory` metricset {pull}15492[15492] - Add azure `storage` metricset in order to retrieve metric values for storage accounts. {issue}14548[14548] {pull}15342[15342] diff --git a/metricbeat/module/windows/perfmon/defs_pdh_windows.go b/metricbeat/helper/windows/pdh/defs_pdh_windows.go similarity index 99% rename from metricbeat/module/windows/perfmon/defs_pdh_windows.go rename to metricbeat/helper/windows/pdh/defs_pdh_windows.go index 97f070a600a..bcc62c4ffd1 100644 --- a/metricbeat/module/windows/perfmon/defs_pdh_windows.go +++ b/metricbeat/helper/windows/pdh/defs_pdh_windows.go @@ -20,7 +20,7 @@ // +build ignore -package perfmon +package pdh /* #include diff --git a/metricbeat/module/windows/perfmon/defs_pdh_windows_386.go b/metricbeat/helper/windows/pdh/defs_pdh_windows_386.go similarity index 99% rename from metricbeat/module/windows/perfmon/defs_pdh_windows_386.go rename to metricbeat/helper/windows/pdh/defs_pdh_windows_386.go index 3995b8b9b01..e794050dcf5 100644 --- a/metricbeat/module/windows/perfmon/defs_pdh_windows_386.go +++ b/metricbeat/helper/windows/pdh/defs_pdh_windows_386.go @@ -18,7 +18,7 @@ // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo.exe -godefs defs_pdh_windows.go -package perfmon +package pdh type PdhErrno uintptr diff --git a/metricbeat/module/windows/perfmon/defs_pdh_windows_amd64.go b/metricbeat/helper/windows/pdh/defs_pdh_windows_amd64.go similarity index 99% rename from metricbeat/module/windows/perfmon/defs_pdh_windows_amd64.go rename to metricbeat/helper/windows/pdh/defs_pdh_windows_amd64.go index 3995b8b9b01..e794050dcf5 100644 --- a/metricbeat/module/windows/perfmon/defs_pdh_windows_amd64.go +++ b/metricbeat/helper/windows/pdh/defs_pdh_windows_amd64.go @@ -18,7 +18,7 @@ // Code generated by cmd/cgo -godefs; DO NOT EDIT. // cgo.exe -godefs defs_pdh_windows.go -package perfmon +package pdh type PdhErrno uintptr diff --git a/metricbeat/module/windows/doc.go b/metricbeat/helper/windows/pdh/doc.go similarity index 62% rename from metricbeat/module/windows/doc.go rename to metricbeat/helper/windows/pdh/doc.go index 7068d9f2ef9..fc6ec0cd132 100644 --- a/metricbeat/module/windows/doc.go +++ b/metricbeat/helper/windows/pdh/doc.go @@ -15,7 +15,10 @@ // specific language governing permissions and limitations // under the License. -/* -Package windows is a Metricbeat module that contains MetricSets. -*/ -package windows +package pdh + +//go:generate go run mkpdh_defs.go +//go:generate go run ../run.go -cmd "go tool cgo -godefs defs_pdh_windows.go" -goarch amd64 -output defs_pdh_windows_amd64.go +//go:generate go run ../run.go -cmd "go tool cgo -godefs defs_pdh_windows.go" -goarch 386 -output defs_pdh_windows_386.go +//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zpdh_windows.go pdh_windows.go +//go:generate gofmt -w defs_pdh_windows_amd64.go defs_pdh_windows_386.go zpdh_windows.go diff --git a/metricbeat/module/windows/perfmon/mkpdh_defs.go b/metricbeat/helper/windows/pdh/mkpdh_defs.go similarity index 99% rename from metricbeat/module/windows/perfmon/mkpdh_defs.go rename to metricbeat/helper/windows/pdh/mkpdh_defs.go index 1f30a1161fb..fd71b98bb27 100644 --- a/metricbeat/module/windows/perfmon/mkpdh_defs.go +++ b/metricbeat/helper/windows/pdh/mkpdh_defs.go @@ -48,7 +48,7 @@ const fileTemplate = ` // +build ignore -package perfmon +package pdh /* #include diff --git a/metricbeat/module/windows/perfmon/pdh_query_windows.go b/metricbeat/helper/windows/pdh/pdh_query_windows.go similarity index 89% rename from metricbeat/module/windows/perfmon/pdh_query_windows.go rename to metricbeat/helper/windows/pdh/pdh_query_windows.go index 5c5a7149d3b..c7d8f0d82bf 100644 --- a/metricbeat/module/windows/perfmon/pdh_query_windows.go +++ b/metricbeat/helper/windows/pdh/pdh_query_windows.go @@ -17,7 +17,7 @@ // +build windows -package perfmon +package pdh import ( "regexp" @@ -43,8 +43,8 @@ type Counter struct { // Query contains the pdh. type Query struct { - handle PdhQueryHandle - counters map[string]*Counter + Handle PdhQueryHandle + Counters map[string]*Counter } // CounterValue contains the performance counter values. @@ -60,42 +60,42 @@ func (q *Query) Open() error { if err != nil { return err } - q.handle = h - q.counters = make(map[string]*Counter) + q.Handle = h + q.Counters = make(map[string]*Counter) return nil } // AddEnglishCounter adds the specified counter to the query. func (q *Query) AddEnglishCounter(counterPath string) (PdhCounterHandle, error) { - h, err := PdhAddEnglishCounter(q.handle, counterPath, 0) + h, err := PdhAddEnglishCounter(q.Handle, counterPath, 0) return h, err } // AddCounter adds the specified counter to the query. -func (q *Query) AddCounter(counterPath string, counter CounterConfig, wildcard bool) error { - if _, found := q.counters[counterPath]; found { +func (q *Query) AddCounter(counterPath string, instance string, format string, wildcard bool) error { + if _, found := q.Counters[counterPath]; found { return nil } var err error var instanceName string // Extract the instance name from the counterPath. - if counter.InstanceName == "" || wildcard { + if instance == "" || wildcard { instanceName, err = matchInstanceName(counterPath) if err != nil { return err } } else { - instanceName = counter.InstanceName + instanceName = instance } - h, err := PdhAddCounter(q.handle, counterPath, 0) + h, err := PdhAddCounter(q.Handle, counterPath, 0) if err != nil { return err } - q.counters[counterPath] = &Counter{ + q.Counters[counterPath] = &Counter{ handle: h, instanceName: instanceName, - format: getPDHFormat(counter.Format), + format: getPDHFormat(format), } return nil } @@ -134,7 +134,7 @@ func (q *Query) RemoveUnusedCounters(counters []string) error { } } unused := make(map[string]*Counter) - for counterPath, counter := range q.counters { + for counterPath, counter := range q.Counters { if !matchCounter(counterPath, counters) { unused[counterPath] = counter } @@ -147,7 +147,7 @@ func (q *Query) RemoveUnusedCounters(counters []string) error { if err != nil { return err } - delete(q.counters, counterPath) + delete(q.Counters, counterPath) } return nil } @@ -163,16 +163,16 @@ func matchCounter(counterPath string, counterList []string) bool { // CollectData collects the value for all counters in the query. func (q *Query) CollectData() error { - return PdhCollectQueryData(q.handle) + return PdhCollectQueryData(q.Handle) } // GetFormattedCounterValues returns an array of formatted values for a query. func (q *Query) GetFormattedCounterValues() (map[string][]CounterValue, error) { - if q.counters == nil || len(q.counters) == 0 { + if q.Counters == nil || len(q.Counters) == 0 { return nil, errors.New("no counter list found") } - rtn := make(map[string][]CounterValue, len(q.counters)) - for path, counter := range q.counters { + rtn := make(map[string][]CounterValue, len(q.Counters)) + for path, counter := range q.Counters { rtn[path] = append(rtn[path], getCounterValue(counter)) } return rtn, nil @@ -206,7 +206,7 @@ func (q *Query) ExpandWildCardPath(wildCardPath string) ([]string, error) { // Close closes the query and all of its counters. func (q *Query) Close() error { - return PdhCloseQuery(q.handle) + return PdhCloseQuery(q.Handle) } // matchInstanceName will check first for instance and then for any objects names. diff --git a/metricbeat/module/windows/perfmon/pdh_query_windows_test.go b/metricbeat/helper/windows/pdh/pdh_query_windows_test.go similarity index 94% rename from metricbeat/module/windows/perfmon/pdh_query_windows_test.go rename to metricbeat/helper/windows/pdh/pdh_query_windows_test.go index 3127a49fd4b..276aba7313d 100644 --- a/metricbeat/module/windows/perfmon/pdh_query_windows_test.go +++ b/metricbeat/helper/windows/pdh/pdh_query_windows_test.go @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -package perfmon +package pdh import ( "syscall" @@ -38,8 +38,7 @@ func TestAddCounterInvalidArgWhenQueryClosed(t *testing.T) { queryPath, err := q.GetCounterPaths(validQuery) // if windows os language is ENG then err will be nil, else the GetCounterPaths will execute the AddCounter if assert.NoError(t, err) { - counter := CounterConfig{Format: "float", InstanceName: "TestInstanceName"} - err = q.AddCounter(queryPath[0], counter, false) + err = q.AddCounter(queryPath[0], "TestInstanceName", "float", false) assert.Error(t, err, PDH_INVALID_HANDLE) } else { assert.Error(t, err, PDH_INVALID_ARGUMENT) @@ -70,12 +69,11 @@ func TestSuccessfulQuery(t *testing.T) { t.Fatal(err) } defer q.Close() - counter := CounterConfig{Format: "float", InstanceName: "TestInstanceName"} queryPath, err := q.GetCounterPaths(validQuery) if err != nil { t.Fatal(err) } - err = q.AddCounter(queryPath[0], counter, false) + err = q.AddCounter(queryPath[0], "TestInstanceName", "floar", false) if err != nil { t.Fatal(err) } diff --git a/metricbeat/module/windows/perfmon/pdh_windows.go b/metricbeat/helper/windows/pdh/pdh_windows.go similarity index 99% rename from metricbeat/module/windows/perfmon/pdh_windows.go rename to metricbeat/helper/windows/pdh/pdh_windows.go index b817ddaec16..bccca2c5784 100644 --- a/metricbeat/module/windows/perfmon/pdh_windows.go +++ b/metricbeat/helper/windows/pdh/pdh_windows.go @@ -17,7 +17,7 @@ // +build windows -package perfmon +package pdh import ( "strconv" diff --git a/metricbeat/module/windows/perfmon/pdh_windows_test.go b/metricbeat/helper/windows/pdh/pdh_windows_test.go similarity index 99% rename from metricbeat/module/windows/perfmon/pdh_windows_test.go rename to metricbeat/helper/windows/pdh/pdh_windows_test.go index be08eac32d2..c17a68c31c3 100644 --- a/metricbeat/module/windows/perfmon/pdh_windows_test.go +++ b/metricbeat/helper/windows/pdh/pdh_windows_test.go @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -package perfmon +package pdh import ( "syscall" diff --git a/metricbeat/module/windows/perfmon/zpdh_windows.go b/metricbeat/helper/windows/pdh/zpdh_windows.go similarity index 99% rename from metricbeat/module/windows/perfmon/zpdh_windows.go rename to metricbeat/helper/windows/pdh/zpdh_windows.go index 85cb93dcc75..8d2891b73cb 100644 --- a/metricbeat/module/windows/perfmon/zpdh_windows.go +++ b/metricbeat/helper/windows/pdh/zpdh_windows.go @@ -17,7 +17,7 @@ // Code generated by 'go generate'; DO NOT EDIT. -package perfmon +package pdh import ( "syscall" diff --git a/metricbeat/module/windows/run.go b/metricbeat/helper/windows/run.go similarity index 100% rename from metricbeat/module/windows/run.go rename to metricbeat/helper/windows/run.go diff --git a/metricbeat/module/windows/perfmon/doc.go b/metricbeat/module/windows/perfmon/doc.go index 66e0df7b5da..bab02b5f128 100644 --- a/metricbeat/module/windows/perfmon/doc.go +++ b/metricbeat/module/windows/perfmon/doc.go @@ -15,12 +15,4 @@ // specific language governing permissions and limitations // under the License. -// Package perfmon implements a Metricbeat metricset for reading Windows -// performance counters. package perfmon - -//go:generate go run mkpdh_defs.go -//go:generate go run ../run.go -cmd "go tool cgo -godefs defs_pdh_windows.go" -goarch amd64 -output defs_pdh_windows_amd64.go -//go:generate go run ../run.go -cmd "go tool cgo -godefs defs_pdh_windows.go" -goarch 386 -output defs_pdh_windows_386.go -//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zpdh_windows.go pdh_windows.go -//go:generate gofmt -w defs_pdh_windows_amd64.go defs_pdh_windows_386.go zpdh_windows.go diff --git a/metricbeat/module/windows/perfmon/perfmon.go b/metricbeat/module/windows/perfmon/perfmon.go index 05210599854..a3d048ebcf7 100644 --- a/metricbeat/module/windows/perfmon/perfmon.go +++ b/metricbeat/module/windows/perfmon/perfmon.go @@ -90,7 +90,7 @@ func New(base mb.BaseMetricSet) (mb.MetricSet, error) { // Fetch fetches events and reports them upstream 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 { + if len(m.reader.query.Counters) == 0 { return errors.New("no counters to read") } diff --git a/metricbeat/module/windows/perfmon/pdh_integration_windows_test.go b/metricbeat/module/windows/perfmon/perfmon_test.go similarity index 94% rename from metricbeat/module/windows/perfmon/pdh_integration_windows_test.go rename to metricbeat/module/windows/perfmon/perfmon_test.go index 366b4a57013..1d43286e151 100644 --- a/metricbeat/module/windows/perfmon/pdh_integration_windows_test.go +++ b/metricbeat/module/windows/perfmon/perfmon_test.go @@ -25,6 +25,8 @@ import ( "testing" "time" + "github.com/elastic/beats/metricbeat/helper/windows/pdh" + "github.com/elastic/beats/libbeat/common" "github.com/pkg/errors" @@ -107,7 +109,7 @@ func TestCounterWithNoInstanceName(t *testing.T) { } func TestQuery(t *testing.T) { - var q Query + var q pdh.Query err := q.Open() if err != nil { t.Fatal(err) @@ -118,7 +120,7 @@ func TestQuery(t *testing.T) { if err != nil { t.Fatal(err) } - err = q.AddCounter(path[0], counter, false) + err = q.AddCounter(path[0], counter.InstanceName, counter.Format, false) if err != nil { t.Fatal(err) } @@ -178,7 +180,7 @@ func TestNonExistingCounter(t *testing.T) { config.CounterConfig[0].Format = "float" handle, err := NewReader(config) if assert.Error(t, err) { - assert.EqualValues(t, PDH_CSTATUS_NO_COUNTER, errors.Cause(err)) + assert.EqualValues(t, pdh.PDH_CSTATUS_NO_COUNTER, errors.Cause(err)) } if handle != nil { @@ -201,7 +203,7 @@ func TestIgnoreNonExistentCounter(t *testing.T) { values, err := handle.Read() if assert.Error(t, err) { - assert.EqualValues(t, PDH_NO_DATA, errors.Cause(err)) + assert.EqualValues(t, pdh.PDH_NO_DATA, errors.Cause(err)) } if handle != nil { @@ -222,7 +224,7 @@ func TestNonExistingObject(t *testing.T) { config.CounterConfig[0].Format = "float" handle, err := NewReader(config) if assert.Error(t, err) { - assert.EqualValues(t, PDH_CSTATUS_NO_OBJECT, errors.Cause(err)) + assert.EqualValues(t, pdh.PDH_CSTATUS_NO_OBJECT, errors.Cause(err)) } if handle != nil { @@ -232,7 +234,7 @@ func TestNonExistingObject(t *testing.T) { } func TestLongOutputFormat(t *testing.T) { - var query Query + var query pdh.Query err := query.Open() if err != nil { t.Fatal(err) @@ -244,8 +246,8 @@ func TestLongOutputFormat(t *testing.T) { t.Fatal(err) } assert.NotZero(t, len(path)) - err = query.AddCounter(path[0], counter, false) - if err != nil && err != PDH_NO_MORE_DATA { + err = query.AddCounter(path[0], counter.InstanceName, counter.Format, false) + if err != nil && err != pdh.PDH_NO_MORE_DATA { t.Fatal(err) } @@ -272,7 +274,7 @@ func TestLongOutputFormat(t *testing.T) { } func TestFloatOutputFormat(t *testing.T) { - var query Query + var query pdh.Query err := query.Open() if err != nil { t.Fatal(err) @@ -284,8 +286,8 @@ func TestFloatOutputFormat(t *testing.T) { t.Fatal(err) } assert.NotZero(t, len(path)) - err = query.AddCounter(path[0], counter, false) - if err != nil && err != PDH_NO_MORE_DATA { + err = query.AddCounter(path[0], counter.InstanceName, counter.Format, false) + if err != nil && err != pdh.PDH_NO_MORE_DATA { t.Fatal(err) } diff --git a/metricbeat/module/windows/perfmon/reader.go b/metricbeat/module/windows/perfmon/reader.go index b7837862ffc..51eef6b7e95 100644 --- a/metricbeat/module/windows/perfmon/reader.go +++ b/metricbeat/module/windows/perfmon/reader.go @@ -24,6 +24,8 @@ import ( "strconv" "strings" + "github.com/elastic/beats/metricbeat/helper/windows/pdh" + "github.com/pkg/errors" "github.com/elastic/beats/libbeat/common" @@ -37,7 +39,7 @@ var ( // Reader will contain the config options type Reader struct { - query Query // PDH Query + query pdh.Query // PDH Query instanceLabel map[string]string // Mapping of counter path to key used for the label (e.g. processor.name) measurement map[string]string // Mapping of counter path to key used for the value (e.g. processor.cpu_time). executed bool // Indicates if the query has been executed. @@ -47,7 +49,7 @@ type Reader struct { // NewReader creates a new instance of Reader. func NewReader(config Config) (*Reader, error) { - var query Query + var query pdh.Query if err := query.Open(); err != nil { return nil, err } @@ -63,8 +65,8 @@ func NewReader(config Config) (*Reader, error) { if err != nil { if config.IgnoreNECounters { switch err { - case PDH_CSTATUS_NO_COUNTER, PDH_CSTATUS_NO_COUNTERNAME, - PDH_CSTATUS_NO_INSTANCE, PDH_CSTATUS_NO_OBJECT: + case pdh.PDH_CSTATUS_NO_COUNTER, pdh.PDH_CSTATUS_NO_COUNTERNAME, + pdh.PDH_CSTATUS_NO_INSTANCE, pdh.PDH_CSTATUS_NO_OBJECT: r.log.Infow("Ignoring non existent counter", "error", err, logp.Namespace("perfmon"), "query", counter.Query) continue @@ -85,7 +87,7 @@ func NewReader(config Config) (*Reader, error) { return nil, errors.Errorf(`failed to expand counter (query="%v")`, counter.Query) } for _, v := range childQueries { - if err := query.AddCounter(v, counter, len(childQueries) > 1); err != nil { + if err := query.AddCounter(v, counter.InstanceName, counter.Format, len(childQueries) > 1); err != nil { return nil, errors.Wrapf(err, `failed to add counter (query="%v")`, counter.Query) } r.instanceLabel[v] = counter.InstanceLabel @@ -104,8 +106,8 @@ func (r *Reader) RefreshCounterPaths() error { if err != nil { if r.config.IgnoreNECounters { switch err { - case PDH_CSTATUS_NO_COUNTER, PDH_CSTATUS_NO_COUNTERNAME, - PDH_CSTATUS_NO_INSTANCE, PDH_CSTATUS_NO_OBJECT: + case pdh.PDH_CSTATUS_NO_COUNTER, pdh.PDH_CSTATUS_NO_COUNTERNAME, + pdh.PDH_CSTATUS_NO_INSTANCE, pdh.PDH_CSTATUS_NO_OBJECT: r.log.Infow("Ignoring non existent counter", "error", err, logp.Namespace("perfmon"), "query", counter.Query) continue @@ -118,7 +120,7 @@ func (r *Reader) RefreshCounterPaths() error { // 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 := r.query.AddCounter(v, counter, len(childQueries) > 1); err != nil { + if err := r.query.AddCounter(v, counter.InstanceName, counter.Format, len(childQueries) > 1); err != nil { return errors.Wrapf(err, "failed to add counter (query='%v')", counter.Query) } r.instanceLabel[v] = counter.InstanceLabel diff --git a/metricbeat/module/windows/perfmon/reader_test.go b/metricbeat/module/windows/perfmon/reader_test.go index 8b4a921b3c3..dd5a58aa522 100644 --- a/metricbeat/module/windows/perfmon/reader_test.go +++ b/metricbeat/module/windows/perfmon/reader_test.go @@ -25,6 +25,8 @@ import ( "github.com/stretchr/testify/assert" ) +var validQuery = `\Processor Information(_Total)\% Processor Time` + // TestNewReaderWhenQueryPathNotProvided will check for invalid/no query. func TestNewReaderWhenQueryPathNotProvided(t *testing.T) { counter := CounterConfig{Format: "float", InstanceName: "TestInstanceName"} @@ -51,9 +53,9 @@ func TestNewReaderWithValidQueryPath(t *testing.T) { assert.Nil(t, err) assert.NotNil(t, reader) assert.NotNil(t, reader.query) - assert.NotNil(t, reader.query.handle) - assert.NotNil(t, reader.query.counters) - assert.NotZero(t, len(reader.query.counters)) + assert.NotNil(t, reader.query.Handle) + assert.NotNil(t, reader.query.Counters) + assert.NotZero(t, len(reader.query.Counters)) defer reader.Close() } diff --git a/metricbeat/module/windows/service/doc.go b/metricbeat/module/windows/service/doc.go index 608c063433b..1bcbc98e250 100644 --- a/metricbeat/module/windows/service/doc.go +++ b/metricbeat/module/windows/service/doc.go @@ -18,7 +18,7 @@ // Package service implements a Metricbeat metricset for reading Windows Services package service -//go:generate go run ../run.go -cmd "go tool cgo -godefs defs_service_windows.go" -goarch amd64 -output defs_service_windows_amd64.go -//go:generate go run ../run.go -cmd "go tool cgo -godefs defs_service_windows.go" -goarch 386 -output defs_service_windows_386.go +//go:generate go run ../../../helper/windows/run.go -cmd "go tool cgo -godefs defs_service_windows.go" -goarch amd64 -output defs_service_windows_amd64.go +//go:generate go run ../../../helper/windows/run.go -cmd "go tool cgo -godefs defs_service_windows.go" -goarch 386 -output defs_service_windows_386.go //go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zservice_windows.go service_windows.go //go:generate gofmt -w defs_service_windows_amd64.go defs_service_windows_386.go