diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index e576471ea9d..ad086bc8a76 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -324,6 +324,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d - Add test for documented fields check for metricsets without a http input. {issue}17315[17315] {pull}17334[17334] - Add final tests and move label to GA for the azure module in metricbeat. {pull}17319[17319] - Reference kubernetes manifests mount data directory from the host when running metricbeat as daemonset, so data persist between executions in the same node. {pull}17429[17429] +- Stack Monitoring modules now auto-configure required metricsets when `xpack.enabled: true` is set. {issue}16471[[16471] {pull}17609[17609] *Packetbeat* diff --git a/metricbeat/docs/modules/beat.asciidoc b/metricbeat/docs/modules/beat.asciidoc index 53c25d91b84..ea09af28a83 100644 --- a/metricbeat/docs/modules/beat.asciidoc +++ b/metricbeat/docs/modules/beat.asciidoc @@ -5,16 +5,20 @@ This file is generated! See scripts/mage/docs_collector.go [[metricbeat-module-beat]] == Beat module -The Beat module contains a minimal set of metrics to enable monitoring of any Beat or other software based on libbeat across -multiple versions. To monitor more Beat metrics, use our {stack} -{monitor-features}. - -The default metricsets are `state` and `stats`. +The `beat` module collects metrics about any Beat or other software based on libbeat. [float] === Compatibility -The Beat module works with Beats 7.3.0 and later. +The `beat` module works with {beats} 7.3.0 and later. + +[float] +=== Usage for Stack Monitoring + +The `beat` module can be used to collect metrics shown in our {stack} {monitor-features} +UI in {kib}. To enable this usage, set `xpack.enabled: true` and remove any `metricsets` +from the module's configuration. Alternatively, run `metricbeat modules disable beat` and +`metricbeat modules enable beat-xpack`. [float] diff --git a/metricbeat/docs/modules/elasticsearch.asciidoc b/metricbeat/docs/modules/elasticsearch.asciidoc index e5da54c0e0b..6dc13a8dd5c 100644 --- a/metricbeat/docs/modules/elasticsearch.asciidoc +++ b/metricbeat/docs/modules/elasticsearch.asciidoc @@ -5,20 +5,20 @@ This file is generated! See scripts/mage/docs_collector.go [[metricbeat-module-elasticsearch]] == Elasticsearch module -There are two modules that collect metrics about {es}: - -* The Elasticsearch module contains a minimal set of metrics to enable -monitoring of Elasticsearch across multiple versions. The default metricsets in -this module are `node` and `node_stats`. -* The Elasticsearch X-Pack module enables you to monitor more Elasticsearch -metrics with our {stack} {monitor-features}. The default metricsets in this -module are `ccr`, `cluster_stats`, `enrich`, ``index`, `index_recovery`, -`index_summary`, `ml_job`, `node_stats`, and `shard`. +The `elasticsearch` module collects metrics about {es}. [float] === Compatibility -The Elasticsearch module works with Elasticsearch 6.7.0 and later. +The `elasticsearch` module works with {es} 6.7.0 and later. + +[float] +=== Usage for Stack Monitoring + +The `elasticsearch` module can be used to collect metrics shown in our {stack} {monitor-features} +UI in {kib}. To enable this usage, set `xpack.enabled: true` and remove any `metricsets` +from the module's configuration. Alternatively, run `metricbeat modules disable elasticsearch` and +`metricbeat modules enable elasticsearch-xpack`. [float] diff --git a/metricbeat/docs/modules/kibana.asciidoc b/metricbeat/docs/modules/kibana.asciidoc index f03e1838db5..7a60f978048 100644 --- a/metricbeat/docs/modules/kibana.asciidoc +++ b/metricbeat/docs/modules/kibana.asciidoc @@ -5,17 +5,20 @@ This file is generated! See scripts/mage/docs_collector.go [[metricbeat-module-kibana]] == Kibana module -There are two modules that collect metrics about {kib}: - -* The Kibana module tracks only the high-level metrics. The default metricset in -this module is `status`. -* The Kibana X-Pack module enables you to monitor more Kibana metrics with our -{stack} {monitor-features}. The default metricset in this module is `stats`. +The `kibana` module collects metrics about {kib}. [float] === Compatibility -The Kibana module works with Kibana 6.7.0 and later. +The `kibana` module works with {kib} 6.7.0 and later. + +[float] +=== Usage for Stack Monitoring + +The `kibana` module can be used to collect metrics shown in our {stack} {monitor-features} +UI in {kib}. To enable this usage, set `xpack.enabled: true` and remove any `metricsets` +from the module's configuration. Alternatively, run `metricbeat modules disable kibana` and +`metricbeat modules enable kibana-xpack`. [float] diff --git a/metricbeat/docs/modules/logstash.asciidoc b/metricbeat/docs/modules/logstash.asciidoc index 8ffc5514ec9..d3e50c4036e 100644 --- a/metricbeat/docs/modules/logstash.asciidoc +++ b/metricbeat/docs/modules/logstash.asciidoc @@ -5,14 +5,20 @@ This file is generated! See scripts/mage/docs_collector.go [[metricbeat-module-logstash]] == Logstash module -This is the Logstash module. - -The default metricsets are `node` and `node_stats`. +The `logstash` module collects metrics about {ls}. [float] === Compatibility -The Logstash module works with Logstash 7.3.0 and later. +The `logstash` module works with {ls} 7.3.0 and later. + +[float] +=== Usage for Stack Monitoring + +The `logstash` module can be used to collect metrics shown in our {stack} {monitor-features} +UI in {kib}. To enable this usage, set `xpack.enabled: true` and remove any `metricsets` +from the module's configuration. Alternatively, run `metricbeat modules disable logstash` and +`metricbeat modules enable logstash-xpack`. [float] diff --git a/metricbeat/helper/elastic/elastic.go b/metricbeat/helper/elastic/elastic.go index b4b9f6195ab..92cdb10b49c 100644 --- a/metricbeat/helper/elastic/elastic.go +++ b/metricbeat/helper/elastic/elastic.go @@ -21,6 +21,8 @@ import ( "fmt" "strings" + "github.com/pkg/errors" + "github.com/elastic/beats/v7/libbeat/logp" "github.com/elastic/beats/v7/libbeat/common" @@ -127,3 +129,42 @@ func FixTimestampField(m common.MapStr, field string) error { } return nil } + +// NewModule returns a new Elastic stack module with the appropriate metricsets configured. +func NewModule(base *mb.BaseModule, xpackEnabledMetricsets []string, logger *logp.Logger) (*mb.BaseModule, error) { + moduleName := base.Name() + + config := struct { + XPackEnabled bool `config:"xpack.enabled"` + }{} + if err := base.UnpackConfig(&config); err != nil { + return nil, errors.Wrapf(err, "could not unpack configuration for module %v", moduleName) + } + + // No special configuration is needed if xpack.enabled != true + if !config.XPackEnabled { + return base, nil + } + + var raw common.MapStr + if err := base.UnpackConfig(&raw); err != nil { + return nil, errors.Wrapf(err, "could not unpack configuration for module %v", moduleName) + } + + // These metricsets are exactly the ones required if xpack.enabled == true + raw["metricsets"] = xpackEnabledMetricsets + + newConfig, err := common.NewConfigFrom(raw) + if err != nil { + return nil, errors.Wrapf(err, "could not create new configuration for module %v", moduleName) + } + + newModule, err := base.WithConfig(*newConfig) + if err != nil { + return nil, errors.Wrapf(err, "could not reconfigure module %v", moduleName) + } + + logger.Debugf("Configuration for module %v modified because xpack.enabled was set to true", moduleName) + + return newModule, nil +} diff --git a/metricbeat/helper/elastic/elastic_test.go b/metricbeat/helper/elastic/elastic_test.go index 14f6a119eb7..8630488dfcd 100644 --- a/metricbeat/helper/elastic/elastic_test.go +++ b/metricbeat/helper/elastic/elastic_test.go @@ -22,7 +22,10 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/beats/v7/libbeat/logp" "github.com/elastic/beats/v7/metricbeat/mb" ) @@ -97,7 +100,7 @@ func TestFixTimestampField(t *testing.T) { { "converts float64s in scientific notation to ints", map[string]interface{}{ - "foo": 1.571284349E12, + "foo": 1.571284349e12, }, map[string]interface{}{ "foo": 1571284349000, @@ -140,3 +143,86 @@ func TestFixTimestampField(t *testing.T) { }) } } + +func TestConfigureModule(t *testing.T) { + mockRegistry := mb.NewRegister() + + const moduleName = "test_module" + + err := mockRegistry.AddMetricSet(moduleName, "foo", mockMetricSetFactory) + require.NoError(t, err) + err = mockRegistry.AddMetricSet(moduleName, "bar", mockMetricSetFactory) + require.NoError(t, err) + err = mockRegistry.AddMetricSet(moduleName, "qux", mockMetricSetFactory) + require.NoError(t, err) + err = mockRegistry.AddMetricSet(moduleName, "baz", mockMetricSetFactory) + require.NoError(t, err) + + tests := map[string]struct { + initConfig metricSetConfig + xpackEnabledMetricsets []string + newConfig metricSetConfig + }{ + "no_xpack_enabled": { + metricSetConfig{ + Module: moduleName, + MetricSets: []string{"foo", "bar"}, + }, + []string{"baz", "qux", "foo"}, + metricSetConfig{ + Module: moduleName, + MetricSets: []string{"foo", "bar"}, + }, + }, + "xpack_enabled": { + metricSetConfig{ + Module: moduleName, + XPackEnabled: true, + MetricSets: []string{"foo", "bar"}, + }, + []string{"baz", "qux", "foo"}, + metricSetConfig{ + Module: moduleName, + XPackEnabled: true, + MetricSets: []string{"baz", "qux", "foo"}, + }, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + cfg := common.MustNewConfigFrom(test.initConfig) + m, _, err := mb.NewModule(cfg, mockRegistry) + require.NoError(t, err) + + bm, ok := m.(*mb.BaseModule) + if !ok { + require.Fail(t, "expecting module to be base module") + } + + newM, err := NewModule(bm, test.xpackEnabledMetricsets, logp.L()) + require.NoError(t, err) + + var newConfig metricSetConfig + err = newM.UnpackConfig(&newConfig) + require.NoError(t, err) + require.Equal(t, test.newConfig, newConfig) + }) + } +} + +type mockMetricSet struct { + mb.BaseMetricSet +} + +func (m *mockMetricSet) Fetch(r mb.ReporterV2) error { return nil } + +type metricSetConfig struct { + Module string `config:"module"` + MetricSets []string `config:"metricsets"` + XPackEnabled bool `config:"xpack.enabled"` +} + +func mockMetricSetFactory(base mb.BaseMetricSet) (mb.MetricSet, error) { + return &mockMetricSet{base}, nil +} diff --git a/metricbeat/mb/mb.go b/metricbeat/mb/mb.go index b22b09debed..2bec71d88e8 100644 --- a/metricbeat/mb/mb.go +++ b/metricbeat/mb/mb.go @@ -27,6 +27,8 @@ import ( "net/url" "time" + "github.com/pkg/errors" + "github.com/elastic/beats/v7/libbeat/common" "github.com/elastic/beats/v7/libbeat/logp" "github.com/elastic/beats/v7/libbeat/monitoring" @@ -94,6 +96,40 @@ func (m *BaseModule) UnpackConfig(to interface{}) error { return m.rawConfig.Unpack(to) } +// WithConfig re-configures the module with the given raw configuration and returns a +// copy of the module. +// Intended to be called from module factories. Note that if metricsets are specified +// in the new configuration, those metricsets must already be registered with +// mb.Registry. +func (m *BaseModule) WithConfig(config common.Config) (*BaseModule, error) { + var chkConfig struct { + Module string `config:"module"` + } + if err := config.Unpack(&chkConfig); err != nil { + return nil, errors.Wrap(err, "error parsing new module configuration") + } + + // Don't allow module name change + if chkConfig.Module != "" && chkConfig.Module != m.name { + return nil, fmt.Errorf("cannot change module name from %v to %v", m.name, chkConfig.Module) + } + + if err := config.SetString("module", -1, m.name); err != nil { + return nil, errors.Wrap(err, "unable to set existing module name in new configuration") + } + + newBM := &BaseModule{ + name: m.name, + rawConfig: &config, + } + + if err := config.Unpack(&newBM.config); err != nil { + return nil, errors.Wrap(err, "error parsing new module configuration") + } + + return newBM, nil +} + // MetricSet interfaces // MetricSet is the common interface for all MetricSet implementations. In diff --git a/metricbeat/mb/mb_test.go b/metricbeat/mb/mb_test.go index 3b734ae9208..83306d51cef 100644 --- a/metricbeat/mb/mb_test.go +++ b/metricbeat/mb/mb_test.go @@ -20,12 +20,14 @@ package mb import ( + "fmt" "testing" "time" - "github.com/elastic/beats/v7/libbeat/common" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/elastic/beats/v7/libbeat/common" ) type testModule struct { @@ -406,3 +408,86 @@ func TestModuleConfigQueryParams(t *testing.T) { assert.NotEqual(t, "&", res[0]) assert.NotEqual(t, "&", res[len(res)-1]) } + +func TestBaseModuleWithConfig(t *testing.T) { + mockRegistry := NewRegister() + + const moduleName = "test_module" + + err := mockRegistry.AddMetricSet(moduleName, "foo", mockMetricSetFactory) + require.NoError(t, err) + err = mockRegistry.AddMetricSet(moduleName, "bar", mockMetricSetFactory) + require.NoError(t, err) + err = mockRegistry.AddMetricSet(moduleName, "qux", mockMetricSetFactory) + require.NoError(t, err) + err = mockRegistry.AddMetricSet(moduleName, "baz", mockMetricSetFactory) + require.NoError(t, err) + + tests := map[string]struct { + newConfig metricSetConfig + expectedConfig metricSetConfig + expectedErrMsg string + }{ + "metricsets": { + metricSetConfig{ + MetricSets: []string{"qux", "baz", "bar"}, + }, + metricSetConfig{ + Module: moduleName, + MetricSets: []string{"qux", "baz", "bar"}, + }, + "", + }, + "module_name": { + metricSetConfig{ + Module: "new_test_module", + }, + metricSetConfig{}, + fmt.Sprintf("cannot change module name from %v to %v", moduleName, "new_test_module"), + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + initConfig := metricSetConfig{ + Module: moduleName, + MetricSets: []string{"foo", "bar"}, + } + + m, _, err := NewModule(common.MustNewConfigFrom(initConfig), mockRegistry) + require.NoError(t, err) + + bm, ok := m.(*BaseModule) + if !ok { + require.Fail(t, "expecting module to be base module") + } + + newBM, err := bm.WithConfig(*common.MustNewConfigFrom(test.newConfig)) + + if err == nil { + var actualNewConfig metricSetConfig + err = newBM.UnpackConfig(&actualNewConfig) + require.NoError(t, err) + require.Equal(t, test.expectedConfig, actualNewConfig) + } else { + require.Equal(t, test.expectedErrMsg, err.Error()) + require.Nil(t, newBM) + } + }) + } +} + +type mockMetricSet struct { + BaseMetricSet +} + +func (m *mockMetricSet) Fetch(r ReporterV2) error { return nil } + +type metricSetConfig struct { + Module string `config:"module"` + MetricSets []string `config:"metricsets"` +} + +func mockMetricSetFactory(base BaseMetricSet) (MetricSet, error) { + return &mockMetricSet{base}, nil +} diff --git a/metricbeat/module/beat/_meta/config-xpack.yml b/metricbeat/module/beat/_meta/config-xpack.yml index 0f72a4e9d03..3c8bca0fbbe 100644 --- a/metricbeat/module/beat/_meta/config-xpack.yml +++ b/metricbeat/module/beat/_meta/config-xpack.yml @@ -1,10 +1,7 @@ - module: beat - metricsets: - - stats - - state + xpack.enabled: true period: 10s hosts: ["http://localhost:5066"] #username: "user" #password: "secret" - xpack.enabled: true diff --git a/metricbeat/module/beat/_meta/docs.asciidoc b/metricbeat/module/beat/_meta/docs.asciidoc index 2f9227502b9..d99b3d21333 100644 --- a/metricbeat/module/beat/_meta/docs.asciidoc +++ b/metricbeat/module/beat/_meta/docs.asciidoc @@ -1,10 +1,14 @@ -The Beat module contains a minimal set of metrics to enable monitoring of any Beat or other software based on libbeat across -multiple versions. To monitor more Beat metrics, use our {stack} -{monitor-features}. - -The default metricsets are `state` and `stats`. +The `beat` module collects metrics about any Beat or other software based on libbeat. [float] === Compatibility -The Beat module works with Beats 7.3.0 and later. +The `beat` module works with {beats} 7.3.0 and later. + +[float] +=== Usage for Stack Monitoring + +The `beat` module can be used to collect metrics shown in our {stack} {monitor-features} +UI in {kib}. To enable this usage, set `xpack.enabled: true` and remove any `metricsets` +from the module's configuration. Alternatively, run `metricbeat modules disable beat` and +`metricbeat modules enable beat-xpack`. diff --git a/metricbeat/module/beat/beat.go b/metricbeat/module/beat/beat.go index 42927977b0f..eb4d9b8f724 100644 --- a/metricbeat/module/beat/beat.go +++ b/metricbeat/module/beat/beat.go @@ -22,10 +22,9 @@ import ( "fmt" "net/url" - "github.com/pkg/errors" - - "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/beats/v7/libbeat/logp" "github.com/elastic/beats/v7/metricbeat/helper" + "github.com/elastic/beats/v7/metricbeat/helper/elastic" "github.com/elastic/beats/v7/metricbeat/mb" ) @@ -36,40 +35,9 @@ func init() { } } -// NewModule creates a new module after performing validation. +// NewModule creates a new module func NewModule(base mb.BaseModule) (mb.Module, error) { - if err := validateXPackMetricsets(base); err != nil { - return nil, err - } - - return &base, nil -} - -// Validate that correct metricsets have been specified if xpack.enabled = true. -func validateXPackMetricsets(base mb.BaseModule) error { - config := struct { - Metricsets []string `config:"metricsets"` - XPackEnabled bool `config:"xpack.enabled"` - }{} - if err := base.UnpackConfig(&config); err != nil { - return err - } - - // Nothing to validate if xpack.enabled != true - if !config.XPackEnabled { - return nil - } - - expectedXPackMetricsets := []string{ - "state", - "stats", - } - - if !common.MakeStringSet(config.Metricsets...).Equals(common.MakeStringSet(expectedXPackMetricsets...)) { - return errors.Errorf("The %v module with xpack.enabled: true must have metricsets: %v", ModuleName, expectedXPackMetricsets) - } - - return nil + return elastic.NewModule(&base, []string{"state", "stats"}, logp.NewLogger(ModuleName)) } // ModuleName is the name of this module. diff --git a/metricbeat/module/beat/beat_test.go b/metricbeat/module/beat/beat_test.go new file mode 100644 index 00000000000..d47441b0668 --- /dev/null +++ b/metricbeat/module/beat/beat_test.go @@ -0,0 +1,50 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package beat_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" + "github.com/elastic/beats/v7/metricbeat/module/beat" + + // Make sure metricsets are registered in mb.Registry + _ "github.com/elastic/beats/v7/metricbeat/module/beat/state" + _ "github.com/elastic/beats/v7/metricbeat/module/beat/stats" +) + +func TestXPackEnabledMetricsets(t *testing.T) { + config := map[string]interface{}{ + "module": beat.ModuleName, + "hosts": []string{"foobar:5066"}, + "xpack.enabled": true, + } + + metricSets := mbtest.NewReportingMetricSetV2Errors(t, config) + require.Len(t, metricSets, 2) + for _, ms := range metricSets { + name := ms.Name() + switch name { + case "state", "stats": + default: + t.Errorf("unexpected metricset name = %v", name) + } + } +} diff --git a/metricbeat/module/elasticsearch/_meta/config-xpack.yml b/metricbeat/module/elasticsearch/_meta/config-xpack.yml index e31e4862dea..4406ba7c050 100644 --- a/metricbeat/module/elasticsearch/_meta/config-xpack.yml +++ b/metricbeat/module/elasticsearch/_meta/config-xpack.yml @@ -1,17 +1,7 @@ - module: elasticsearch - metricsets: - - ccr - - cluster_stats - - enrich - - index - - index_recovery - - index_summary - - ml_job - - node_stats - - shard + xpack.enabled: true period: 10s hosts: ["http://localhost:9200"] #username: "user" #password: "secret" - xpack.enabled: true diff --git a/metricbeat/module/elasticsearch/_meta/docs.asciidoc b/metricbeat/module/elasticsearch/_meta/docs.asciidoc index 3ba64c67487..0a259e61e3c 100644 --- a/metricbeat/module/elasticsearch/_meta/docs.asciidoc +++ b/metricbeat/module/elasticsearch/_meta/docs.asciidoc @@ -1,14 +1,14 @@ -There are two modules that collect metrics about {es}: - -* The Elasticsearch module contains a minimal set of metrics to enable -monitoring of Elasticsearch across multiple versions. The default metricsets in -this module are `node` and `node_stats`. -* The Elasticsearch X-Pack module enables you to monitor more Elasticsearch -metrics with our {stack} {monitor-features}. The default metricsets in this -module are `ccr`, `cluster_stats`, `enrich`, ``index`, `index_recovery`, -`index_summary`, `ml_job`, `node_stats`, and `shard`. +The `elasticsearch` module collects metrics about {es}. [float] === Compatibility -The Elasticsearch module works with Elasticsearch 6.7.0 and later. +The `elasticsearch` module works with {es} 6.7.0 and later. + +[float] +=== Usage for Stack Monitoring + +The `elasticsearch` module can be used to collect metrics shown in our {stack} {monitor-features} +UI in {kib}. To enable this usage, set `xpack.enabled: true` and remove any `metricsets` +from the module's configuration. Alternatively, run `metricbeat modules disable elasticsearch` and +`metricbeat modules enable elasticsearch-xpack`. diff --git a/metricbeat/module/elasticsearch/elasticsearch.go b/metricbeat/module/elasticsearch/elasticsearch.go index 45e8ab17a23..c2264f9d6a8 100644 --- a/metricbeat/module/elasticsearch/elasticsearch.go +++ b/metricbeat/module/elasticsearch/elasticsearch.go @@ -25,13 +25,13 @@ import ( "sync" "time" - "github.com/elastic/beats/v7/metricbeat/mb" - "github.com/pkg/errors" "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/beats/v7/libbeat/logp" "github.com/elastic/beats/v7/metricbeat/helper" "github.com/elastic/beats/v7/metricbeat/helper/elastic" + "github.com/elastic/beats/v7/metricbeat/mb" ) func init() { @@ -41,31 +41,9 @@ func init() { } } -// NewModule creates a new module after performing validation. +// NewModule creates a new module. func NewModule(base mb.BaseModule) (mb.Module, error) { - if err := validateXPackMetricsets(base); err != nil { - return nil, err - } - - return &base, nil -} - -// Validate that correct metricsets have been specified if xpack.enabled = true. -func validateXPackMetricsets(base mb.BaseModule) error { - config := struct { - Metricsets []string `config:"metricsets"` - XPackEnabled bool `config:"xpack.enabled"` - }{} - if err := base.UnpackConfig(&config); err != nil { - return err - } - - // Nothing to validate if xpack.enabled != true - if !config.XPackEnabled { - return nil - } - - expectedXPackMetricsets := []string{ + xpackEnabledMetricSets := []string{ "ccr", "enrich", "cluster_stats", @@ -76,12 +54,7 @@ func validateXPackMetricsets(base mb.BaseModule) error { "node_stats", "shard", } - - if !common.MakeStringSet(config.Metricsets...).Equals(common.MakeStringSet(expectedXPackMetricsets...)) { - return errors.Errorf("The %v module with xpack.enabled: true must have metricsets: %v", ModuleName, expectedXPackMetricsets) - } - - return nil + return elastic.NewModule(&base, xpackEnabledMetricSets, logp.NewLogger(ModuleName)) } // CCRStatsAPIAvailableVersion is the version of Elasticsearch since when the CCR stats API is available. diff --git a/metricbeat/module/elasticsearch/elasticsearch_test.go b/metricbeat/module/elasticsearch/elasticsearch_test.go new file mode 100644 index 00000000000..9b9682aef3b --- /dev/null +++ b/metricbeat/module/elasticsearch/elasticsearch_test.go @@ -0,0 +1,58 @@ +// Licensed to Elasticsearch B.V. under one or more contributor +// license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright +// ownership. Elasticsearch B.V. licenses this file to you under +// the Apache License, Version 2.0 (the "License"); you may +// not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package elasticsearch_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" + "github.com/elastic/beats/v7/metricbeat/module/elasticsearch" + + // Make sure metricsets are registered in mb.Registry + _ "github.com/elastic/beats/v7/metricbeat/module/elasticsearch/ccr" + _ "github.com/elastic/beats/v7/metricbeat/module/elasticsearch/cluster_stats" + _ "github.com/elastic/beats/v7/metricbeat/module/elasticsearch/enrich" + _ "github.com/elastic/beats/v7/metricbeat/module/elasticsearch/index" + _ "github.com/elastic/beats/v7/metricbeat/module/elasticsearch/index_recovery" + _ "github.com/elastic/beats/v7/metricbeat/module/elasticsearch/index_summary" + _ "github.com/elastic/beats/v7/metricbeat/module/elasticsearch/ml_job" + _ "github.com/elastic/beats/v7/metricbeat/module/elasticsearch/node_stats" + _ "github.com/elastic/beats/v7/metricbeat/module/elasticsearch/shard" +) + +func TestXPackEnabledMetricsets(t *testing.T) { + config := map[string]interface{}{ + "module": elasticsearch.ModuleName, + "hosts": []string{"foobar:9200"}, + "xpack.enabled": true, + } + + metricSets := mbtest.NewReportingMetricSetV2Errors(t, config) + require.Len(t, metricSets, 9) + for _, ms := range metricSets { + name := ms.Name() + switch name { + case "ccr", "enrich", "cluster_stats", "index", "index_recovery", + "index_summary", "ml_job", "node_stats", "shard": + default: + t.Errorf("unexpected metricset name = %v", name) + } + } +} diff --git a/metricbeat/module/kibana/_meta/config-xpack.yml b/metricbeat/module/kibana/_meta/config-xpack.yml index ac67948c7ab..73dffedb072 100644 --- a/metricbeat/module/kibana/_meta/config-xpack.yml +++ b/metricbeat/module/kibana/_meta/config-xpack.yml @@ -1,9 +1,7 @@ - module: kibana - metricsets: - - stats + xpack.enabled: true period: 10s hosts: ["localhost:5601"] #basepath: "" #username: "user" #password: "secret" - xpack.enabled: true diff --git a/metricbeat/module/kibana/_meta/docs.asciidoc b/metricbeat/module/kibana/_meta/docs.asciidoc index bcc0c408572..662571b31fa 100644 --- a/metricbeat/module/kibana/_meta/docs.asciidoc +++ b/metricbeat/module/kibana/_meta/docs.asciidoc @@ -1,11 +1,14 @@ -There are two modules that collect metrics about {kib}: - -* The Kibana module tracks only the high-level metrics. The default metricset in -this module is `status`. -* The Kibana X-Pack module enables you to monitor more Kibana metrics with our -{stack} {monitor-features}. The default metricset in this module is `stats`. +The `kibana` module collects metrics about {kib}. [float] === Compatibility -The Kibana module works with Kibana 6.7.0 and later. +The `kibana` module works with {kib} 6.7.0 and later. + +[float] +=== Usage for Stack Monitoring + +The `kibana` module can be used to collect metrics shown in our {stack} {monitor-features} +UI in {kib}. To enable this usage, set `xpack.enabled: true` and remove any `metricsets` +from the module's configuration. Alternatively, run `metricbeat modules disable kibana` and +`metricbeat modules enable kibana-xpack`. diff --git a/metricbeat/module/kibana/kibana.go b/metricbeat/module/kibana/kibana.go index 4acb124695b..819d2b55d95 100644 --- a/metricbeat/module/kibana/kibana.go +++ b/metricbeat/module/kibana/kibana.go @@ -23,10 +23,8 @@ import ( "net/url" "strings" - "github.com/pkg/errors" - "github.com/elastic/beats/v7/libbeat/common" - + "github.com/elastic/beats/v7/libbeat/logp" "github.com/elastic/beats/v7/metricbeat/helper" "github.com/elastic/beats/v7/metricbeat/helper/elastic" "github.com/elastic/beats/v7/metricbeat/mb" @@ -39,39 +37,9 @@ func init() { } } -// NewModule creates a new module after performing validation. +// NewModule creates a new module. func NewModule(base mb.BaseModule) (mb.Module, error) { - if err := validateXPackMetricsets(base); err != nil { - return nil, err - } - - return &base, nil -} - -// Validate that correct metricsets have been specified if xpack.enabled = true. -func validateXPackMetricsets(base mb.BaseModule) error { - config := struct { - Metricsets []string `config:"metricsets"` - XPackEnabled bool `config:"xpack.enabled"` - }{} - if err := base.UnpackConfig(&config); err != nil { - return err - } - - // Nothing to validate if xpack.enabled != true - if !config.XPackEnabled { - return nil - } - - expectedXPackMetricsets := []string{ - "stats", - } - - if !common.MakeStringSet(config.Metricsets...).Equals(common.MakeStringSet(expectedXPackMetricsets...)) { - return errors.Errorf("The %v module with xpack.enabled: true must have metricsets: %v", ModuleName, expectedXPackMetricsets) - } - - return nil + return elastic.NewModule(&base, []string{"stats"}, logp.NewLogger(ModuleName)) } // ModuleName is the name of this module diff --git a/metricbeat/module/kibana/kibana_test.go b/metricbeat/module/kibana/kibana_test.go index be2158019aa..c54d5287142 100644 --- a/metricbeat/module/kibana/kibana_test.go +++ b/metricbeat/module/kibana/kibana_test.go @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -package kibana +package kibana_test import ( "testing" @@ -23,6 +23,11 @@ import ( "github.com/stretchr/testify/require" "github.com/elastic/beats/v7/libbeat/common" + mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" + "github.com/elastic/beats/v7/metricbeat/module/kibana" + + // Make sure metricsets are registered in mb.Registry + _ "github.com/elastic/beats/v7/metricbeat/module/kibana/stats" ) func TestIsStatsAPIAvailable(t *testing.T) { @@ -37,7 +42,19 @@ func TestIsStatsAPIAvailable(t *testing.T) { } for _, test := range tests { - actual := IsStatsAPIAvailable(common.MustNewVersion(test.input)) + actual := kibana.IsStatsAPIAvailable(common.MustNewVersion(test.input)) require.Equal(t, test.expected, actual) } } + +func TestXPackEnabledMetricsets(t *testing.T) { + config := map[string]interface{}{ + "module": kibana.ModuleName, + "hosts": []string{"foobar:5601"}, + "xpack.enabled": true, + } + + metricSets := mbtest.NewReportingMetricSetV2Errors(t, config) + require.Len(t, metricSets, 1) + require.Equal(t, "stats", metricSets[0].Name()) +} diff --git a/metricbeat/module/logstash/_meta/config-xpack.yml b/metricbeat/module/logstash/_meta/config-xpack.yml index 3e8f80b718a..443e87667ec 100644 --- a/metricbeat/module/logstash/_meta/config-xpack.yml +++ b/metricbeat/module/logstash/_meta/config-xpack.yml @@ -1,9 +1,6 @@ - module: logstash - metricsets: - - node - - node_stats + xpack.enabled: true period: 10s hosts: ["localhost:9600"] #username: "user" #password: "secret" - xpack.enabled: true diff --git a/metricbeat/module/logstash/_meta/docs.asciidoc b/metricbeat/module/logstash/_meta/docs.asciidoc index c56c1b38119..3971f461c39 100644 --- a/metricbeat/module/logstash/_meta/docs.asciidoc +++ b/metricbeat/module/logstash/_meta/docs.asciidoc @@ -1,8 +1,14 @@ -This is the Logstash module. - -The default metricsets are `node` and `node_stats`. +The `logstash` module collects metrics about {ls}. [float] === Compatibility -The Logstash module works with Logstash 7.3.0 and later. +The `logstash` module works with {ls} 7.3.0 and later. + +[float] +=== Usage for Stack Monitoring + +The `logstash` module can be used to collect metrics shown in our {stack} {monitor-features} +UI in {kib}. To enable this usage, set `xpack.enabled: true` and remove any `metricsets` +from the module's configuration. Alternatively, run `metricbeat modules disable logstash` and +`metricbeat modules enable logstash-xpack`. diff --git a/metricbeat/module/logstash/logstash.go b/metricbeat/module/logstash/logstash.go index 3e5e57ac1c2..fbc030fa310 100644 --- a/metricbeat/module/logstash/logstash.go +++ b/metricbeat/module/logstash/logstash.go @@ -25,6 +25,7 @@ import ( "github.com/pkg/errors" "github.com/elastic/beats/v7/libbeat/common" + "github.com/elastic/beats/v7/libbeat/logp" "github.com/elastic/beats/v7/metricbeat/helper" "github.com/elastic/beats/v7/metricbeat/helper/elastic" "github.com/elastic/beats/v7/metricbeat/mb" @@ -37,40 +38,9 @@ func init() { } } -// NewModule creates a new module after performing validation. +// NewModule creates a new module func NewModule(base mb.BaseModule) (mb.Module, error) { - if err := validateXPackMetricsets(base); err != nil { - return nil, err - } - - return &base, nil -} - -// Validate that correct metricsets have been specified if xpack.enabled = true. -func validateXPackMetricsets(base mb.BaseModule) error { - config := struct { - Metricsets []string `config:"metricsets"` - XPackEnabled bool `config:"xpack.enabled"` - }{} - if err := base.UnpackConfig(&config); err != nil { - return err - } - - // Nothing to validate if xpack.enabled != true - if !config.XPackEnabled { - return nil - } - - expectedXPackMetricsets := []string{ - "node", - "node_stats", - } - - if !common.MakeStringSet(config.Metricsets...).Equals(common.MakeStringSet(expectedXPackMetricsets...)) { - return errors.Errorf("The %v module with xpack.enabled: true must have metricsets: %v", ModuleName, expectedXPackMetricsets) - } - - return nil + return elastic.NewModule(&base, []string{"node", "node_stats"}, logp.NewLogger(ModuleName)) } // ModuleName is the name of this module. diff --git a/metricbeat/module/logstash/logstash_test.go b/metricbeat/module/logstash/logstash_test.go index 73ec193eed6..63c1f443bd2 100644 --- a/metricbeat/module/logstash/logstash_test.go +++ b/metricbeat/module/logstash/logstash_test.go @@ -15,12 +15,19 @@ // specific language governing permissions and limitations // under the License. -package logstash +package logstash_test import ( "testing" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + mbtest "github.com/elastic/beats/v7/metricbeat/mb/testing" + "github.com/elastic/beats/v7/metricbeat/module/logstash" + + // Make sure metricsets are registered in mb.Registry + _ "github.com/elastic/beats/v7/metricbeat/module/logstash/node" + _ "github.com/elastic/beats/v7/metricbeat/module/logstash/node_stats" ) func TestGetVertexClusterUUID(t *testing.T) { @@ -53,7 +60,26 @@ func TestGetVertexClusterUUID(t *testing.T) { for name, test := range tests { t.Run(name, func(t *testing.T) { - assert.Equal(t, test.expectedClusterUUID, GetVertexClusterUUID(test.vertex, test.overrideClusterUUID)) + require.Equal(t, test.expectedClusterUUID, logstash.GetVertexClusterUUID(test.vertex, test.overrideClusterUUID)) }) } } + +func TestXPackEnabledMetricSets(t *testing.T) { + config := map[string]interface{}{ + "module": logstash.ModuleName, + "hosts": []string{"foobar:9600"}, + "xpack.enabled": true, + } + + metricSets := mbtest.NewReportingMetricSetV2Errors(t, config) + require.Len(t, metricSets, 2) + for _, ms := range metricSets { + name := ms.Name() + switch name { + case "node", "node_stats": + default: + t.Errorf("unexpected metricset name = %v", name) + } + } +} diff --git a/metricbeat/modules.d/beat-xpack.yml.disabled b/metricbeat/modules.d/beat-xpack.yml.disabled index ed7ecc00df6..0d254a465a1 100644 --- a/metricbeat/modules.d/beat-xpack.yml.disabled +++ b/metricbeat/modules.d/beat-xpack.yml.disabled @@ -2,12 +2,9 @@ # Docs: https://www.elastic.co/guide/en/beats/metricbeat/master/metricbeat-module-beat.html - module: beat - metricsets: - - stats - - state + xpack.enabled: true period: 10s hosts: ["http://localhost:5066"] #username: "user" #password: "secret" - xpack.enabled: true diff --git a/metricbeat/modules.d/elasticsearch-xpack.yml.disabled b/metricbeat/modules.d/elasticsearch-xpack.yml.disabled index ed428acb1e3..c7f57b84f54 100644 --- a/metricbeat/modules.d/elasticsearch-xpack.yml.disabled +++ b/metricbeat/modules.d/elasticsearch-xpack.yml.disabled @@ -2,19 +2,9 @@ # Docs: https://www.elastic.co/guide/en/beats/metricbeat/master/metricbeat-module-elasticsearch.html - module: elasticsearch - metricsets: - - ccr - - cluster_stats - - enrich - - index - - index_recovery - - index_summary - - ml_job - - node_stats - - shard + xpack.enabled: true period: 10s hosts: ["http://localhost:9200"] #username: "user" #password: "secret" - xpack.enabled: true diff --git a/metricbeat/modules.d/kibana-xpack.yml.disabled b/metricbeat/modules.d/kibana-xpack.yml.disabled index 84675eeb340..dd6b4d939a2 100644 --- a/metricbeat/modules.d/kibana-xpack.yml.disabled +++ b/metricbeat/modules.d/kibana-xpack.yml.disabled @@ -2,11 +2,9 @@ # Docs: https://www.elastic.co/guide/en/beats/metricbeat/master/metricbeat-module-kibana.html - module: kibana - metricsets: - - stats + xpack.enabled: true period: 10s hosts: ["localhost:5601"] #basepath: "" #username: "user" #password: "secret" - xpack.enabled: true diff --git a/metricbeat/modules.d/logstash-xpack.yml.disabled b/metricbeat/modules.d/logstash-xpack.yml.disabled index 5166f7b9c75..db78289f2a8 100644 --- a/metricbeat/modules.d/logstash-xpack.yml.disabled +++ b/metricbeat/modules.d/logstash-xpack.yml.disabled @@ -2,11 +2,8 @@ # Docs: https://www.elastic.co/guide/en/beats/metricbeat/master/metricbeat-module-logstash.html - module: logstash - metricsets: - - node - - node_stats + xpack.enabled: true period: 10s hosts: ["localhost:9600"] #username: "user" #password: "secret" - xpack.enabled: true