forked from elastic/beats
-
Notifications
You must be signed in to change notification settings - Fork 0
/
registry.go
166 lines (136 loc) · 5.41 KB
/
registry.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
package mb
import (
"fmt"
"sort"
"strings"
"github.com/elastic/beats/libbeat/logp"
)
const initialSize = 20 // initialSize specifies the initial size of the Register.
// Registry is the singleton Register instance where all ModuleFactory's and
// MetricSetFactory's should be registered.
var Registry = NewRegister()
// DefaultModuleFactory returns the given BaseModule and never returns an error.
// If a MetricSets are registered without an associated ModuleFactory, then
// the DefaultModuleFactory will be used to instantiate a Module.
var DefaultModuleFactory = func(base BaseModule) (Module, error) {
return &base, nil
}
// ModuleFactory accepts a BaseModule and returns a Module. If there was an
// error creating the Module then an error will be returned.
type ModuleFactory func(base BaseModule) (Module, error)
// MetricSetFactory accepts a BaseMetricSet and returns a MetricSet. If there
// was an error creating the MetricSet then an error will be returned. The
// returned MetricSet must also implement either EventFetcher or EventsFetcher
// (but not both).
type MetricSetFactory func(base BaseMetricSet) (MetricSet, error)
// HostParser is a function that parses a host value from the configuration
// and returns a HostData object. The module is provided in case additional
// configuration values are required to parse and build the HostData object.
// An error should be returned if the host or configuration is invalid.
type HostParser func(module Module, host string) (HostData, error)
type metricSetFactoryInfo struct {
name string
factory MetricSetFactory
hostParser HostParser
}
// Register contains the factory functions for creating new Modules and new
// MetricSets.
type Register struct {
// A map of module name to ModuleFactory.
modules map[string]ModuleFactory
// A map of module name to nested map of MetricSet name to metricSetFactoryInfo.
metricSets map[string]map[string]metricSetFactoryInfo
}
// NewRegister creates and returns a new Register.
func NewRegister() *Register {
return &Register{
modules: make(map[string]ModuleFactory, initialSize),
metricSets: make(map[string]map[string]metricSetFactoryInfo, initialSize),
}
}
// AddModule registers a new ModuleFactory. An error is returned if the
// 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 {
if name == "" {
return fmt.Errorf("module name is required")
}
name = strings.ToLower(name)
_, exists := r.modules[name]
if exists {
return fmt.Errorf("module '%s' is already registered", name)
}
if factory == nil {
return fmt.Errorf("module '%s' cannot be registered with a nil factory", name)
}
r.modules[name] = factory
logp.Info("Module registered: %s", name)
return nil
}
// AddMetricSet registers a new MetricSetFactory. Optionally it accepts a single
// HostParser function for parsing the 'host' configuration data. An error is
// 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 {
if module == "" {
return fmt.Errorf("module name is required")
}
if name == "" {
return fmt.Errorf("metricset name is required")
}
module = strings.ToLower(module)
name = strings.ToLower(name)
if metricsets, ok := r.metricSets[module]; !ok {
r.metricSets[module] = map[string]metricSetFactoryInfo{}
} else if _, exists := metricsets[name]; exists {
return fmt.Errorf("metricset '%s/%s' is already registered", module, name)
}
if factory == nil {
return fmt.Errorf("metricset '%s/%s' cannot be registered with a nil factory", module, name)
}
var hp HostParser
if len(hostParser) > 0 {
hp = hostParser[0]
}
r.metricSets[module][name] = metricSetFactoryInfo{name: name, factory: factory, hostParser: hp}
logp.Info("MetricSet registered: %s/%s", module, name)
return nil
}
// 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 {
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) {
module = strings.ToLower(module)
name = strings.ToLower(name)
modules, exists := r.metricSets[module]
if !exists {
return nil, nil, fmt.Errorf("metricset '%s/%s' is not registered, module not found", module, name)
}
info, exists := modules[name]
if !exists {
return nil, nil, fmt.Errorf("metricset '%s/%s' is not registered, metricset not found", module, name)
}
return info.factory, info.hostParser, nil
}
// String return a string representation of the registered ModuleFactory's and
// MetricSetFactory's.
func (r Register) String() string {
var modules []string
for module := range r.modules {
modules = append(modules, module)
}
sort.Strings(modules)
var metricSets []string
for module, m := range r.metricSets {
for name := range m {
metricSets = append(metricSets, fmt.Sprintf("%s/%s", module, name))
}
}
sort.Strings(metricSets)
return fmt.Sprintf("Register [ModuleFactory:[%s], MetricSetFactory:[%s]]",
strings.Join(modules, ", "), strings.Join(metricSets, ", "))
}