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

Use default metricsets in hints based autodiscover #6634

Merged
merged 3 commits into from
Mar 26, 2018
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
8 changes: 6 additions & 2 deletions metricbeat/autodiscover/builder/hints/config.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package hints

import "github.com/elastic/beats/metricbeat/mb"

type config struct {
Key string `config:"key"`
Key string `config:"key"`
Registry *mb.Register
}

func defaultConfig() config {
return config{
Key: "metrics",
Key: "metrics",
Registry: mb.Registry,
}
}
18 changes: 10 additions & 8 deletions metricbeat/autodiscover/builder/hints/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ const (
)

type metricHints struct {
Key string
Key string
Registry *mb.Register
}

// NewMetricHints builds a new metrics builder based on hints
Expand All @@ -46,7 +47,7 @@ func NewMetricHints(cfg *common.Config) (autodiscover.Builder, error) {
return nil, fmt.Errorf("unable to unpack hints config due to error: %v", err)
}

return &metricHints{config.Key}, nil
return &metricHints{config.Key, config.Registry}, nil
}

// Create configs based on hints passed from providers
Expand Down Expand Up @@ -113,17 +114,18 @@ func (m *metricHints) getModule(hints common.MapStr) string {

func (m *metricHints) getMetricSets(hints common.MapStr, module string) []string {
var msets []string
var err error
msets = builder.GetHintAsList(hints, m.Key, metricsets)

if len(msets) == 0 {
// Special handling for prometheus as most use cases rely on exporters/instrumentation.
// Prometheus stats can be explicitly configured if need be.
if module == "prometheus" {
msets = []string{"collector"}
} else {
msets = mb.Registry.MetricSets(module)
// If no metricset list is given, take module defaults
// fallback to all metricsets if module has no defaults
msets, err = m.Registry.DefaultMetricSets(module)
if err != nil || len(msets) == 0 {
msets = m.Registry.MetricSets(module)
}
}

return msets
}

Expand Down
95 changes: 66 additions & 29 deletions metricbeat/autodiscover/builder/hints/metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,18 @@ import (

"github.com/elastic/beats/libbeat/common"
"github.com/elastic/beats/libbeat/common/bus"
"github.com/elastic/beats/metricbeat/mb"
)

func TestGenerateHints(t *testing.T) {
tests := []struct {
event bus.Event
len int
result common.MapStr
message string
event bus.Event
len int
result common.MapStr
}{
// Empty event hints should return empty config
{
message: "Empty event hints should return empty config",
event: bus.Event{
"host": "1.2.3.4",
"kubernetes": common.MapStr{
Expand All @@ -35,98 +37,116 @@ func TestGenerateHints(t *testing.T) {
len: 0,
result: common.MapStr{},
},
// Hints without host should return nothing
{
message: "Hints without host should return nothing",
event: bus.Event{
"hints": common.MapStr{
"metrics": common.MapStr{
"module": "prometheus",
"module": "mockmodule",
},
},
},
len: 0,
result: common.MapStr{},
},
// Only module hint should return empty config
{
message: "Only module hint should return all metricsets",
event: bus.Event{
"host": "1.2.3.4",
"hints": common.MapStr{
"metrics": common.MapStr{
"module": "prometheus",
"module": "mockmodule",
},
},
},
len: 1,
result: common.MapStr{
"module": "prometheus",
"metricsets": []interface{}{"collector"},
"module": "mockmodule",
"metricsets": []interface{}{"one", "two"},
"timeout": "3s",
"period": "1m",
"enabled": true,
},
},
// Only module, namespace hint should return empty config
{
message: "metricsets hint works",
event: bus.Event{
"host": "1.2.3.4",
"hints": common.MapStr{
"metrics": common.MapStr{
"module": "prometheus",
"namespace": "test",
"module": "mockmodule",
"metricsets": "one",
},
},
},
len: 1,
result: common.MapStr{
"module": "prometheus",
"namespace": "test",
"metricsets": []interface{}{"collector"},
"module": "mockmodule",
"metricsets": []interface{}{"one"},
"timeout": "3s",
"period": "1m",
"enabled": true,
},
},
{
message: "Only module, it should return defaults",
event: bus.Event{
"host": "1.2.3.4",
"hints": common.MapStr{
"metrics": common.MapStr{
"module": "mockmoduledefaults",
},
},
},
len: 1,
result: common.MapStr{
"module": "mockmoduledefaults",
"metricsets": []interface{}{"default"},
"timeout": "3s",
"period": "1m",
"enabled": true,
},
},
// Module, namespace, host hint should return valid config without port should not return hosts
{
message: "Module, namespace, host hint should return valid config without port should not return hosts",
event: bus.Event{
"host": "1.2.3.4",
"hints": common.MapStr{
"metrics": common.MapStr{
"module": "prometheus",
"module": "mockmoduledefaults",
"namespace": "test",
"hosts": "${data.host}:9090",
},
},
},
len: 1,
result: common.MapStr{
"module": "prometheus",
"module": "mockmoduledefaults",
"namespace": "test",
"metricsets": []interface{}{"collector"},
"metricsets": []interface{}{"default"},
"timeout": "3s",
"period": "1m",
"enabled": true,
},
},
// Module, namespace, host hint should return valid config
{
message: "Module, namespace, host hint should return valid config",
event: bus.Event{
"host": "1.2.3.4",
"port": int64(9090),
"port": 9090,
"hints": common.MapStr{
"metrics": common.MapStr{
"module": "prometheus",
"module": "mockmoduledefaults",
"namespace": "test",
"hosts": "${data.host}:9090",
},
},
},
len: 1,
result: common.MapStr{
"module": "prometheus",
"module": "mockmoduledefaults",
"namespace": "test",
"metricsets": []interface{}{"collector"},
"metricsets": []interface{}{"default"},
"hosts": []interface{}{"1.2.3.4:9090"},
"timeout": "3s",
"period": "1m",
Expand All @@ -135,21 +155,38 @@ func TestGenerateHints(t *testing.T) {
},
}
for _, test := range tests {
cfg := defaultConfig()
mockRegister := mb.NewRegister()
mockRegister.MustAddMetricSet("mockmodule", "one", NewMockMetricSet, mb.DefaultMetricSet())
mockRegister.MustAddMetricSet("mockmodule", "two", NewMockMetricSet, mb.DefaultMetricSet())
mockRegister.MustAddMetricSet("mockmoduledefaults", "default", NewMockMetricSet, mb.DefaultMetricSet())
mockRegister.MustAddMetricSet("mockmoduledefaults", "other", NewMockMetricSet)

m := metricHints{
Key: cfg.Key,
Key: defaultConfig().Key,
Registry: mockRegister,
}
cfgs := m.CreateConfig(test.event)
assert.Equal(t, len(cfgs), test.len)

if test.len != 0 {
config := common.MapStr{}
err := cfgs[0].Unpack(&config)
assert.Nil(t, err)
assert.Nil(t, err, test.message)

assert.Equal(t, config, test.result)
assert.Equal(t, config, test.result, test.message)
}

}
}

type MockMetricSet struct {
mb.BaseMetricSet
}

func NewMockMetricSet(base mb.BaseMetricSet) (mb.MetricSet, error) {
return &MockMetricSet{}, nil
}

func (ms *MockMetricSet) Fetch(report mb.Reporter) {

}
6 changes: 4 additions & 2 deletions metricbeat/docs/autodiscover-hints.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ annotations:

The above annotations are used to spin up a Prometheus collector metricset and it polls the
parent container on port `9090` at a 1 minute interval and the container named `sidecar` on
port `8080` every 10 minutes. Hints can also be provided for the following module configuration
parameters:
port `8080` every 10 minutes. If no metricsets parameter is given, Metricbeat will use default
metricsets of the module, or all metricsets if there is no default list.

Hints can also be provided for the following module configuration parameters:

["source","yaml",subs="attributes"]
-------------------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion metricbeat/mb/builders.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ func newBaseMetricSets(r *Register, m Module) ([]BaseMetricSet, error) {
metricSetNames := m.Config().MetricSets
if len(metricSetNames) == 0 {
var err error
metricSetNames, err = r.defaultMetricSets(m.Name())
metricSetNames, err = r.DefaultMetricSets(m.Name())
if err != nil {
return nil, errors.Errorf("no metricsets configured for module '%s'", m.Name())
}
Expand Down
4 changes: 2 additions & 2 deletions metricbeat/mb/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,10 +217,10 @@ func (r *Register) metricSetRegistration(module, name string) (MetricSetRegistra
return registration, nil
}

// defaultMetricSets returns the names of the default MetricSets for a module.
// DefaultMetricSets returns the names of the default MetricSets for a module.
// An error is returned if no default MetricSet is declared or the module does
// not exist.
func (r *Register) defaultMetricSets(module string) ([]string, error) {
func (r *Register) DefaultMetricSets(module string) ([]string, error) {
r.lock.RLock()
defer r.lock.RUnlock()

Expand Down
2 changes: 1 addition & 1 deletion metricbeat/mb/registry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ func TestDefaultMetricSet(t *testing.T) {
t.Fatal(err)
}

names, err := registry.defaultMetricSets(moduleName)
names, err := registry.DefaultMetricSets(moduleName)
if err != nil {
t.Fatal(err)
}
Expand Down