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

[7.x] Allow auto-configuration of Metricbeat stack modules for stack monitoring (#17609) #17772

Merged
merged 1 commit into from
Apr 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d
- 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]
- Add more detailed error messages, system tests and small refactoring to the service metricset in windows. {pull}17725[17725]
- Move the perfmon metricset to GA. {issue}16608[16608] {pull}17879[17879]
- Stack Monitoring modules now auto-configure required metricsets when `xpack.enabled: true` is set. {issue}16471[[16471] {pull}17609[17609]

*Packetbeat*

Expand Down
16 changes: 10 additions & 6 deletions metricbeat/docs/modules/beat.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
20 changes: 10 additions & 10 deletions metricbeat/docs/modules/elasticsearch.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
17 changes: 10 additions & 7 deletions metricbeat/docs/modules/kibana.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
14 changes: 10 additions & 4 deletions metricbeat/docs/modules/logstash.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
41 changes: 41 additions & 0 deletions metricbeat/helper/elastic/elastic.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
}
88 changes: 87 additions & 1 deletion metricbeat/helper/elastic/elastic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
}
36 changes: 36 additions & 0 deletions metricbeat/mb/mb.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down
Loading