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

Adding query APIs for metricsets and modules from metricbeat registry #4102

Merged
merged 2 commits into from Apr 25, 2017
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.asciidoc
Expand Up @@ -144,6 +144,7 @@ https://github.com/elastic/beats/compare/v5.1.1...master[Check the HEAD diff]
- Add new MetricSet interfaces for developers (`Closer`, `ReportingFetcher`, and `PushMetricSet`). {pull}3908[3908]
- Add kubelet module {pull}3916[3916]
- Add dropwizard module {pull}4022[4022]
- Adding query APIs for metricsets and modules from metricbeat registry {pull}4102[4102]

*Packetbeat*
- Add `fields` and `fields_under_root` to packetbeat protocols configurations. {pull}3518[3518]
Expand Down
53 changes: 51 additions & 2 deletions metricbeat/mb/registry.go
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"sort"
"strings"
"sync"

"github.com/elastic/beats/libbeat/logp"
)
Expand Down Expand Up @@ -44,8 +45,10 @@ type metricSetFactoryInfo struct {
}

// Register contains the factory functions for creating new Modules and new
// MetricSets.
// MetricSets. Registers are thread safe for concurrent usage.
type Register struct {
// Lock to control concurrent read/writes
lock sync.RWMutex
// A map of module name to ModuleFactory.
modules map[string]ModuleFactory
// A map of module name to nested map of MetricSet name to metricSetFactoryInfo.
Expand All @@ -64,6 +67,9 @@ func NewRegister() *Register {
// name is empty, factory is nil, or if a factory has already been registered
// under the name.
func (r *Register) AddModule(name string, factory ModuleFactory) error {
r.lock.Lock()
defer r.lock.Unlock()

if name == "" {
return fmt.Errorf("module name is required")
}
Expand All @@ -89,6 +95,9 @@ func (r *Register) AddModule(name string, factory ModuleFactory) error {
// returned if any parameter is empty or nil or if a factory has already been
// registered under the name.
func (r *Register) AddMetricSet(module string, name string, factory MetricSetFactory, hostParser ...HostParser) error {
r.lock.Lock()
defer r.lock.Unlock()

if module == "" {
return fmt.Errorf("module name is required")
}
Expand Down Expand Up @@ -122,12 +131,18 @@ func (r *Register) AddMetricSet(module string, name string, factory MetricSetFac
// moduleFactory returns the registered ModuleFactory associated with the
// given name. It returns nil if no ModuleFactory is registered.
func (r *Register) moduleFactory(name string) ModuleFactory {
r.lock.RLock()
defer r.lock.RUnlock()

return r.modules[strings.ToLower(name)]
}

// metricSetFactory returns the registered MetricSetFactory associated with the
// given name. It returns an error if no MetricSetFactory is registered.
func (r *Register) metricSetFactory(module, name string) (MetricSetFactory, HostParser, error) {
r.lock.RLock()
defer r.lock.RUnlock()

module = strings.ToLower(module)
name = strings.ToLower(name)

Expand All @@ -144,9 +159,43 @@ func (r *Register) metricSetFactory(module, name string) (MetricSetFactory, Host
return info.factory, info.hostParser, nil
}

//Modules returns the list of module names that are registered
func (r *Register) Modules() []string {
r.lock.RLock()
defer r.lock.RUnlock()

modules := make([]string, 0, len(r.modules))
for module := range r.modules {
modules = append(modules, module)
}

return modules
}

//MetricSets returns the list of metricsets registered for a given module
func (r *Register) MetricSets(module string) []string {
r.lock.RLock()
defer r.lock.RUnlock()

var metricsets []string

sets, ok := r.metricSets[module]
if ok {
metricsets = make([]string, 0, len(sets))
for name := range sets {
metricsets = append(metricsets, name)
}
}

return metricsets
}

// String return a string representation of the registered ModuleFactory's and
// MetricSetFactory's.
func (r Register) String() string {
func (r *Register) String() string {
r.lock.RLock()
defer r.lock.RUnlock()

var modules []string
for module := range r.modules {
modules = append(modules, module)
Expand Down
24 changes: 24 additions & 0 deletions metricbeat/mb/registry_test.go
Expand Up @@ -150,3 +150,27 @@ func TestMetricSetFactory(t *testing.T) {
assert.NotNil(t, hp) // Can't compare functions in Go so just check for non-nil.
})
}

func TestMetricSetQuery(t *testing.T) {
registry := NewRegister()
err := registry.AddMetricSet(moduleName, metricSetName, fakeMetricSetFactory)
if err != nil {
t.Fatal(err)
}

metricsets := registry.MetricSets(moduleName)
assert.Equal(t, len(metricsets), 1)
assert.Equal(t, metricsets[0], metricSetName)

metricsets = registry.MetricSets("foo")
assert.Equal(t, len(metricsets), 0)
}

func TestModuleQuery(t *testing.T) {
registry := NewRegister()
registry.modules[moduleName] = fakeModuleFactory

modules := registry.Modules()
assert.Equal(t, len(modules), 1)
assert.Equal(t, modules[0], moduleName)
}