@cryptotaxi247 / netdata-1 / commits / 9e7295087

improve(go.d/sd/pipeline): add `services` config (#21269)

Ilya Mashchenko committed Nov 6, 2025 at 15:29 UTC 9e729508770c4bbe7c221bae882611938c9834f2
10 files changed +1573 -1037
src/go/plugin/go.d/agent/discovery/sd/pipeline/compose.go
+1 -33
@@ -4,15 +4,12 @@ package pipeline
4
5 import (
6 "bytes"
7 - "errors"
7 "fmt"
8 "text/template"
9
10 "github.com/netdata/netdata/go/plugins/logger"
11 "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/confgroup"
12 "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/discovery/sd/model"
14 -
15 - "gopkg.in/yaml.v2"
13 )
14
15 func newConfigComposer(cfg []ComposeRuleConfig) (*configComposer, error) {
@@ -71,7 +68,7 @@ func (c *configComposer) compose(tgt model.Target) []confgroup.Config {
68 continue
69 }
70
74 - cfgs, err := c.parseTemplateData(c.buf.Bytes())
71 + cfgs, err := parseConfigTemplateData(c.buf.Bytes())
72 if err != nil {
73 c.Warningf("failed to parse template data: %v", err)
74 continue
@@ -87,35 +84,6 @@ func (c *configComposer) compose(tgt model.Target) []confgroup.Config {
84 return configs
85 }
86
90 -func (c *configComposer) parseTemplateData(bs []byte) ([]confgroup.Config, error) {
91 - var data any
92 - if err := yaml.Unmarshal(bs, &data); err != nil {
93 - return nil, err
94 - }
95 -
96 - type (
97 - single = map[any]any
98 - multi = []any
99 - )
100 -
101 - switch data.(type) {
102 - case single:
103 - var cfg confgroup.Config
104 - if err := yaml.Unmarshal(bs, &cfg); err != nil {
105 - return nil, err
106 - }
107 - return []confgroup.Config{cfg}, nil
108 - case multi:
109 - var cfgs []confgroup.Config
110 - if err := yaml.Unmarshal(bs, &cfgs); err != nil {
111 - return nil, err
112 - }
113 - return cfgs, nil
114 - default:
115 - return nil, errors.New("unknown config format")
116 - }
117 -}
118 -
87 func newComposeRules(cfg []ComposeRuleConfig) ([]*composeRule, error) {
88 var rules []*composeRule
89
src/go/plugin/go.d/agent/discovery/sd/pipeline/config.go
+96 -8
@@ -5,21 +5,29 @@ package pipeline
5 import (
6 "errors"
7 "fmt"
8 + "strings"
9
10 "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/confgroup"
11 "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/discovery/sd/discoverer/dockersd"
12 "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/discovery/sd/discoverer/k8ssd"
13 "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/discovery/sd/discoverer/netlistensd"
14 "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/discovery/sd/discoverer/snmpsd"
15 + "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/discovery/sd/model"
16 )
17
18 type Config struct {
19 Source string `yaml:"-"`
20 ConfigDefaults confgroup.Registry `yaml:"-"`
21
20 - Disabled bool `yaml:"disabled"`
21 - Name string `yaml:"name"`
22 - Discover []DiscoveryConfig `yaml:"discover"`
22 + Disabled bool `yaml:"disabled"`
23 + Name string `yaml:"name"`
24 +
25 + Discover []DiscoveryConfig `yaml:"discover"`
26 +
27 + // New single-step format:
28 + Services []ServiceRuleConfig `yaml:"services"`
29 +
30 + // Legacy two-step:
31 Classify []ClassifyRuleConfig `yaml:"classify"`
32 Compose []ComposeRuleConfig `yaml:"compose"`
33 }
@@ -32,6 +40,12 @@ type DiscoveryConfig struct {
40 SNMP snmpsd.Config `yaml:"snmp"`
41 }
42
43 +type ServiceRuleConfig struct {
44 + ID string `yaml:"id"` // mandatory (for logging/diagnostics)
45 + Match string `yaml:"match"` // mandatory
46 + ConfigTemplate string `yaml:"config_template"` // optional (drop if empty)
47 +}
48 +
49 type ClassifyRuleConfig struct {
50 Name string `yaml:"name"`
51 Selector string `yaml:"selector"` // mandatory
@@ -58,11 +72,20 @@ func validateConfig(cfg Config) error {
72 if err := validateDiscoveryConfig(cfg.Discover); err != nil {
73 return fmt.Errorf("discover config: %v", err)
74 }
61 - if err := validateClassifyConfig(cfg.Classify); err != nil {
62 - return fmt.Errorf("classify rules: %v", err)
63 - }
64 - if err := validateComposeConfig(cfg.Compose); err != nil {
65 - return fmt.Errorf("compose rules: %v", err)
75 +
76 + switch {
77 + case len(cfg.Services) > 0:
78 + if err := validateServicesConfig(cfg.Services); err != nil {
79 + return fmt.Errorf("services rules: %v", err)
80 + }
81 + default:
82 + // Legacy path
83 + if err := validateClassifyConfig(cfg.Classify); err != nil {
84 + return fmt.Errorf("classify rules: %v", err)
85 + }
86 + if err := validateComposeConfig(cfg.Compose); err != nil {
87 + return fmt.Errorf("compose rules: %v", err)
88 + }
89 }
90 return nil
91 }
@@ -81,6 +104,23 @@ func validateDiscoveryConfig(config []DiscoveryConfig) error {
104 return nil
105 }
106
107 +func validateServicesConfig(rules []ServiceRuleConfig) error {
108 + if len(rules) == 0 {
109 + return errors.New("empty config, need at least 1 service rule")
110 + }
111 + for i, r := range rules {
112 + i++
113 + if r.ID == "" {
114 + return fmt.Errorf("'service[%d]->id' not set", i)
115 + }
116 + if r.Match == "" {
117 + return fmt.Errorf("'service[%s][%d]->match' not set", r.ID, i)
118 + }
119 + // config_template is optional
120 + }
121 + return nil
122 +}
123 +
124 func validateClassifyConfig(rules []ClassifyRuleConfig) error {
125 if len(rules) == 0 {
126 return errors.New("empty config, need least 1 rule")
@@ -136,3 +176,51 @@ func validateComposeConfig(rules []ComposeRuleConfig) error {
176 }
177 return nil
178 }
179 +
180 +func ConvertOldToServices(cls []ClassifyRuleConfig, cmp []ComposeRuleConfig) ([]ServiceRuleConfig, error) {
181 + var out []ServiceRuleConfig
182 +
183 + // Build quick lookups for tag -> list of match exprs that add this tag.
184 + tagToExprs := map[string][]string{}
185 + for _, r := range cls {
186 + for _, m := range r.Match {
187 + // split tags line into tokens:
188 + tags, _ := model.ParseTags(m.Tags) // reuse existing parser if accessible
189 + for tag := range tags {
190 + if strings.HasPrefix(tag, "-") { // ignore deletions
191 + continue
192 + }
193 + tagToExprs[tag] = append(tagToExprs[tag], m.Expr)
194 + }
195 + }
196 + // also include rule-level tags
197 + rtags, _ := model.ParseTags(r.Tags)
198 + for tag := range rtags {
199 + if strings.HasPrefix(tag, "-") {
200 + continue
201 + }
202 + // no expr here; this is too generic to build a service rule from.
203 + }
204 + }
205 +
206 + // For each compose rule config entry, create services for its selector tags.
207 + for _, r := range cmp {
208 + for _, c := range r.Config {
209 + sel := strings.TrimSpace(c.Selector)
210 + exprs := tagToExprs[sel]
211 + for i, expr := range exprs {
212 + id := sel
213 + if i > 0 {
214 + id = fmt.Sprintf("%s_%d", sel, i+1)
215 + }
216 + out = append(out, ServiceRuleConfig{
217 + ID: id,
218 + Match: expr,
219 + ConfigTemplate: c.Template,
220 + })
221 + }
222 + }
223 + }
224 +
225 + return out, nil
226 +}
src/go/plugin/go.d/agent/discovery/sd/pipeline/pipeline.go
+50 -15
@@ -24,30 +24,41 @@ func New(cfg Config) (*Pipeline, error) {
24 return nil, err
25 }
26
27 - clr, err := newTargetClassificator(cfg.Classify)
28 - if err != nil {
29 - return nil, fmt.Errorf("classify rules: %v", err)
30 - }
31 -
32 - cmr, err := newConfigComposer(cfg.Compose)
33 - if err != nil {
34 - return nil, fmt.Errorf("compose rules: %v", err)
35 - }
36 -
27 p := &Pipeline{
28 Logger: logger.New().With(
29 slog.String("component", "service discovery"),
30 slog.String("pipeline", cfg.Name),
31 ),
32 configDefaults: cfg.ConfigDefaults,
43 - clr: clr,
44 - cmr: cmr,
33 accum: newAccumulator(),
34 discoverers: make([]model.Discoverer, 0),
35 configs: make(map[string]map[uint64][]confgroup.Config),
36 }
37 +
38 p.accum.Logger = p.Logger
39
40 + if len(cfg.Services) > 0 {
41 + svr, err := newServiceEngine(cfg.Services)
42 + if err != nil {
43 + return nil, fmt.Errorf("services rules: %v", err)
44 + }
45 + p.svr = svr
46 + svr.Logger = p.Logger
47 + } else {
48 + // Legacy path
49 + clr, err := newTargetClassificator(cfg.Classify)
50 + if err != nil {
51 + return nil, fmt.Errorf("classify rules: %v", err)
52 + }
53 + cmr, err := newConfigComposer(cfg.Compose)
54 + if err != nil {
55 + return nil, fmt.Errorf("compose rules: %v", err)
56 + }
57 + p.clr, p.cmr = clr, cmr
58 + clr.Logger = p.Logger
59 + cmr.Logger = p.Logger
60 + }
61 +
62 if err := p.registerDiscoverers(cfg); err != nil {
63 return nil, err
64 }
@@ -62,9 +73,15 @@ type (
73 configDefaults confgroup.Registry
74 discoverers []model.Discoverer
75 accum *accumulator
65 - clr classificator
66 - cmr composer
67 - configs map[string]map[uint64][]confgroup.Config // [targetSource][targetHash]
76 +
77 + configs map[string]map[uint64][]confgroup.Config // [targetSource][targetHash]
78 +
79 + // new
80 + svr composer
81 +
82 + // legacy
83 + clr classificator
84 + cmr composer
85 }
86 classificator interface {
87 classify(model.Target) model.Tags
@@ -201,6 +218,23 @@ func (p *Pipeline) processGroup(tgg model.TargetGroup) *confgroup.Group {
218
219 targetsCache[hash] = nil
220
221 + if p.svr != nil {
222 + if cfgs := p.svr.compose(tgt); len(cfgs) > 0 {
223 + targetsCache[hash] = cfgs
224 + changed = true
225 + for _, cfg := range cfgs {
226 + cfg.SetProvider(tgg.Provider())
227 + cfg.SetSource(tgg.Source())
228 + cfg.SetSourceType(confgroup.TypeDiscovered)
229 + if def, ok := p.configDefaults.Lookup(cfg.Module()); ok {
230 + cfg.ApplyDefaults(def)
231 + }
232 + }
233 + }
234 + continue
235 + }
236 +
237 + // Legacy:
238 if tags := p.clr.classify(tgt); len(tags) > 0 {
239 tgt.Tags().Merge(tags)
240
@@ -218,6 +252,7 @@ func (p *Pipeline) processGroup(tgg model.TargetGroup) *confgroup.Group {
252 }
253 }
254 }
255 +
256 }
257
258 for hash := range targetsCache {
src/go/plugin/go.d/agent/discovery/sd/pipeline/pipeline_test.go
+209
@@ -94,6 +94,18 @@ compose:
94 template: |
95 name: {{ .Name }}-foobar2
96 `
97 +
98 + const servicesConfig = `
99 +services:
100 + - id: "svc-foobar1"
101 + match: '{{ glob .Name "mock*1*" }}'
102 + config_template: |
103 + name: {{ .Name }}-foobar1
104 + - id: "svc-foobar2"
105 + match: '{{ glob .Name "mock*2*" }}'
106 + config_template: |
107 + name: {{ .Name }}-foobar2
108 +`
109 tests := map[string]discoverySim{
110 "new group with no targets": {
111 config: config,
@@ -186,6 +198,21 @@ compose:
198 prepareDiscoveredGroup("mock11-foobar1", "mock22-foobar2"),
199 },
200 },
201 + "services-only: new group with targets": {
202 + config: servicesConfig,
203 + discoverers: []model.Discoverer{
204 + newMockDiscoverer("rule1",
205 + newMockTargetGroup("test", "mock1", "mock2"),
206 + ),
207 + },
208 + useServices: true, // tell the simulator to wire svr-only
209 + wantClassifyCalls: 0, // no classify in services mode
210 + wantComposeCalls: 2, // compose called per target (2 targets)
211 + wantConfGroups: []*confgroup.Group{
212 + // same expected configs as the legacy "new group with targets"
213 + prepareDiscoveredGroup("mock1-foobar1", "mock2-foobar2"),
214 + },
215 + },
216 }
217
218 for name, sim := range tests {
@@ -301,3 +328,185 @@ func mustCalcHash(obj any) uint64 {
328 }
329 return hash
330 }
331 +
332 +func TestConvertOldToServices(t *testing.T) {
333 + type inYAML struct {
334 + Classify string
335 + Compose string
336 + }
337 +
338 + tests := map[string]struct {
339 + in inYAML
340 + want []ServiceRuleConfig
341 + }{
342 + "basic 1:1 mapping": {
343 + in: inYAML{
344 + Classify: `
345 +- name: "Applications"
346 + selector: "unknown"
347 + tags: "-unknown app"
348 + match:
349 + - tags: "activemq"
350 + expr: '{{ and (eq .Port "8161") (eq .Comm "activemq") }}'
351 +`,
352 + Compose: `
353 +- name: "Applications"
354 + selector: "app"
355 + config:
356 + - selector: "activemq"
357 + template: |
358 + module: activemq
359 + name: local
360 + url: http://{{.Address}}
361 + webadmin: admin
362 +`,
363 + },
364 + want: []ServiceRuleConfig{
365 + {
366 + ID: "activemq",
367 + Match: `{{ and (eq .Port "8161") (eq .Comm "activemq") }}`,
368 + ConfigTemplate: "module: activemq\nname: local\nurl: http://{{.Address}}\nwebadmin: admin\n",
369 + },
370 + },
371 + },
372 +
373 + "multiple classify exprs for same tag -> multiple service rules": {
374 + in: inYAML{
375 + Classify: `
376 +- name: "Databases"
377 + selector: "unknown"
378 + match:
379 + - tags: "redis"
380 + expr: '{{ eq .Port "6379" }}'
381 + - tags: "redis"
382 + expr: '{{ and (eq .Comm "redis-server") (eq .Address "127.0.0.1") }}'
383 +`,
384 + Compose: `
385 +- name: "Databases"
386 + selector: "app"
387 + config:
388 + - selector: "redis"
389 + template: |
390 + module: redis
391 + name: {{ .Name }}
392 +`,
393 + },
394 + // NOTE: Order should follow classify expr encounter order:
395 + // 1) Port-based, 2) Comm+Address-based. IDs redis, redis_2 accordingly.
396 + want: []ServiceRuleConfig{
397 + {
398 + ID: "redis",
399 + Match: `{{ eq .Port "6379" }}`,
400 + ConfigTemplate: "module: redis\nname: {{ .Name }}\n",
401 + },
402 + {
403 + ID: "redis_2",
404 + Match: `{{ and (eq .Comm "redis-server") (eq .Address "127.0.0.1") }}`,
405 + ConfigTemplate: "module: redis\nname: {{ .Name }}\n",
406 + },
407 + },
408 + },
409 +
410 + "ignore deletions and rule-level tags without expr": {
411 + in: inYAML{
412 + Classify: `
413 +- name: "NoExpr"
414 + selector: "unknown"
415 + tags: "nginx" # rule-level tag: no expr -> cannot produce a service rule
416 + match: []
417 +- name: "Deletions"
418 + selector: "unknown"
419 + match:
420 + - tags: "-nginx" # deletion: ignore
421 + expr: '{{ eq .Port "80" }}' # has expr but tag is a deletion, ignore
422 +`,
423 + Compose: `
424 +- name: "Web"
425 + selector: "app"
426 + config:
427 + - selector: "nginx"
428 + template: |
429 + module: nginx
430 + name: web
431 +`,
432 + },
433 + want: nil, // nothing to map
434 + },
435 +
436 + "compose selector without classify producer -> empty": {
437 + in: inYAML{
438 + Classify: `
439 +- name: "App"
440 + selector: "unknown"
441 + match:
442 + - tags: "foo"
443 + expr: '{{ eq .Port "1234" }}'
444 +`,
445 + Compose: `
446 +- name: "App"
447 + selector: "app"
448 + config:
449 + - selector: "bar"
450 + template: |
451 + module: bar
452 +`,
453 + },
454 + want: nil,
455 + },
456 +
457 + "multiple compose selectors map to different classify tags": {
458 + in: inYAML{
459 + Classify: `
460 +- name: "Mixed"
461 + selector: "unknown"
462 + match:
463 + - tags: "kafka"
464 + expr: '{{ eq .Port "9092" }}'
465 + - tags: "zookeeper"
466 + expr: '{{ eq .Port "2181" }}'
467 +`,
468 + Compose: `
469 +- name: "Stream"
470 + selector: "app"
471 + config:
472 + - selector: "zookeeper"
473 + template: |
474 + module: zookeeper
475 + name: zk
476 + - selector: "kafka"
477 + template: |
478 + module: kafka
479 + name: broker
480 +`,
481 + },
482 + // Order follows compose config order; for each selector, classify exprs order is preserved.
483 + want: []ServiceRuleConfig{
484 + {
485 + ID: "zookeeper",
486 + Match: `{{ eq .Port "2181" }}`,
487 + ConfigTemplate: "module: zookeeper\nname: zk\n",
488 + },
489 + {
490 + ID: "kafka",
491 + Match: `{{ eq .Port "9092" }}`,
492 + ConfigTemplate: "module: kafka\nname: broker\n",
493 + },
494 + },
495 + },
496 + }
497 +
498 + for name, tc := range tests {
499 + t.Run(name, func(t *testing.T) {
500 + var cls []ClassifyRuleConfig
501 + var cmp []ComposeRuleConfig
502 +
503 + require.NoError(t, yaml.Unmarshal([]byte(tc.in.Classify), &cls), "classify YAML")
504 + require.NoError(t, yaml.Unmarshal([]byte(tc.in.Compose), &cmp), "compose YAML")
505 +
506 + got, err := ConvertOldToServices(cls, cmp)
507 + require.NoError(t, err)
508 +
509 + assert.Equal(t, tc.want, got)
510 + })
511 + }
512 +}
src/go/plugin/go.d/agent/discovery/sd/pipeline/services.go new
+137
@@ -0,0 +1,137 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +package pipeline
4 +
5 +import (
6 + "bytes"
7 + "errors"
8 + "fmt"
9 + "strings"
10 + "text/template"
11 +
12 + "github.com/netdata/netdata/go/plugins/logger"
13 + "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/confgroup"
14 + "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/discovery/sd/model"
15 +
16 + "gopkg.in/yaml.v2"
17 +)
18 +
19 +func newServiceEngine(cfg []ServiceRuleConfig) (*serviceEngine, error) {
20 + rules, err := newServiceRules(cfg)
21 + if err != nil {
22 + return nil, err
23 + }
24 + return &serviceEngine{rules: rules}, nil
25 +}
26 +
27 +type serviceEngine struct {
28 + *logger.Logger
29 + rules []*serviceRule
30 + buf bytes.Buffer
31 +}
32 +
33 +type serviceRule struct {
34 + id string
35 + match *template.Template
36 + tmpl *template.Template // optional
37 +}
38 +
39 +func newServiceRules(cfg []ServiceRuleConfig) ([]*serviceRule, error) {
40 + fmap := newFuncMap()
41 + var rules []*serviceRule
42 +
43 + for i, rc := range cfg {
44 + i++
45 +
46 + m, err := parseTemplate(rc.Match, fmap)
47 + if err != nil {
48 + return nil, fmt.Errorf("service '%s'[%d]: match: %v", rc.ID, i, err)
49 + }
50 +
51 + var tmpl *template.Template
52 + if strings.TrimSpace(rc.ConfigTemplate) != "" {
53 + tmpl, err = parseTemplate(rc.ConfigTemplate, fmap)
54 + if err != nil {
55 + return nil, fmt.Errorf("service '%s'[%d]: config_template: %v", rc.ID, i, err)
56 + }
57 + }
58 +
59 + rules = append(rules, &serviceRule{
60 + id: rc.ID, match: m, tmpl: tmpl,
61 + })
62 + }
63 + return rules, nil
64 +}
65 +
66 +func (s *serviceEngine) compose(tgt model.Target) []confgroup.Config {
67 + var out []confgroup.Config
68 +
69 + for i, r := range s.rules {
70 + s.buf.Reset()
71 +
72 + if err := r.match.Execute(&s.buf, tgt); err != nil {
73 + s.Warningf("failed to execute services[%d]->match on target '%s'", i+1, tgt.TUID())
74 + continue
75 + }
76 + if strings.TrimSpace(s.buf.String()) != "true" {
77 + continue
78 + }
79 +
80 + // No config_template => drop
81 + if r.tmpl == nil {
82 + break
83 + }
84 +
85 + s.buf.Reset()
86 + if err := r.tmpl.Execute(&s.buf, tgt); err != nil {
87 + s.Warningf("failed to execute services[%d]->config_template on target '%s': %v", i+1, tgt.TUID(), err)
88 + continue
89 + }
90 + if s.buf.Len() == 0 {
91 + continue
92 + }
93 +
94 + cfgs, err := parseConfigTemplateData(s.buf.Bytes())
95 + if err != nil {
96 + s.Warningf("failed to parse services[%d] template data: %v", i+1, err)
97 + continue
98 + }
99 +
100 + out = append(out, cfgs...)
101 + }
102 +
103 + if len(out) > 0 {
104 + s.Debugf("created %d config(s) for target '%s'", len(out), tgt.TUID())
105 + }
106 +
107 + return out
108 +}
109 +
110 +func parseConfigTemplateData(bs []byte) ([]confgroup.Config, error) {
111 + var data any
112 + if err := yaml.Unmarshal(bs, &data); err != nil {
113 + return nil, err
114 + }
115 +
116 + type (
117 + single = map[any]any
118 + multi = []any
119 + )
120 +
121 + switch data.(type) {
122 + case single:
123 + var cfg confgroup.Config
124 + if err := yaml.Unmarshal(bs, &cfg); err != nil {
125 + return nil, err
126 + }
127 + return []confgroup.Config{cfg}, nil
128 + case multi:
129 + var cfgs []confgroup.Config
130 + if err := yaml.Unmarshal(bs, &cfgs); err != nil {
131 + return nil, err
132 + }
133 + return cfgs, nil
134 + default:
135 + return nil, errors.New("unknown config format")
136 + }
137 +}
src/go/plugin/go.d/agent/discovery/sd/pipeline/services_test.go new
+121
@@ -0,0 +1,121 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +package pipeline
4 +
5 +import (
6 + "testing"
7 +
8 + "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/confgroup"
9 + "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/discovery/sd/model"
10 +
11 + "github.com/stretchr/testify/assert"
12 + "github.com/stretchr/testify/require"
13 + "gopkg.in/yaml.v2"
14 +)
15 +
16 +func TestServiceEngine_compose(t *testing.T) {
17 + // Config A:
18 + // - rule1: matches exactly Name == "mock1" and yields 1 config
19 + // - rule2: matches Name == "mock2" or "mock3" and yields 2 configs (YAML list)
20 + // - drop1: matches Name == "dropme" but has no config_template => hard drop (break)
21 + // - rule3: another rule matching Name == "mock3" to validate multi-rule aggregation
22 + configA := `
23 +- id: "rule1"
24 + match: '{{ eq .Name "mock1" }}'
25 + config_template: |
26 + name: {{ .Name }}-1
27 +- id: "rule2"
28 + match: '{{ or (eq .Name "mock2") (eq .Name "mock3") }}'
29 + config_template: |
30 + - name: {{ .Name }}-2
31 + - name: {{ .Name }}-3
32 +- id: "drop1"
33 + match: '{{ eq .Name "dropme" }}'
34 +- id: "rule3"
35 + match: '{{ eq .Name "mock3" }}'
36 + config_template: |
37 + - name: {{ .Name }}-4
38 +`
39 +
40 + // Config B:
41 + // - drop3: matches Name == "mock3" with no template => hard drop (break)
42 + // - rule2/rule3 exist but must NOT be evaluated if drop3 matches
43 + configB := `
44 +- id: "rule1"
45 + match: '{{ eq .Name "mock1" }}'
46 + config_template: |
47 + name: {{ .Name }}-1
48 +- id: "drop3"
49 + match: '{{ eq .Name "mock3" }}'
50 +- id: "rule2"
51 + match: '{{ or (eq .Name "mock2") (eq .Name "mock3") }}'
52 + config_template: |
53 + - name: {{ .Name }}-2
54 + - name: {{ .Name }}-3
55 +- id: "rule3"
56 + match: '{{ eq .Name "mock3" }}'
57 + config_template: |
58 + - name: {{ .Name }}-4
59 +`
60 +
61 + type tc struct {
62 + configYAML string
63 + target model.Target
64 + wantConfigs []confgroup.Config
65 + }
66 +
67 + tests := map[string]tc{
68 + "no rules match": {
69 + configYAML: configA,
70 + target: newMockTarget("nothing"),
71 + wantConfigs: nil,
72 + },
73 + "drop rule hit (no config_template)": {
74 + configYAML: configA,
75 + target: newMockTarget("dropme"),
76 + wantConfigs: nil,
77 + },
78 + "one rule -> one config": {
79 + configYAML: configA,
80 + target: newMockTarget("mock1"),
81 + wantConfigs: []confgroup.Config{
82 + {"name": "mock1-1"},
83 + },
84 + },
85 + "one rule -> two configs (YAML list)": {
86 + configYAML: configA,
87 + target: newMockTarget("mock2"),
88 + wantConfigs: []confgroup.Config{
89 + {"name": "mock2-2"},
90 + {"name": "mock2-3"},
91 + },
92 + },
93 + "multiple rules aggregated (no drop before)": {
94 + configYAML: configA,
95 + target: newMockTarget("mock3"),
96 + wantConfigs: []confgroup.Config{
97 + {"name": "mock3-2"},
98 + {"name": "mock3-3"},
99 + {"name": "mock3-4"},
100 + },
101 + },
102 + "hard drop stops further evaluation": {
103 + configYAML: configB,
104 + target: newMockTarget("mock3"),
105 + wantConfigs: nil, // drop3 matches first => break => rule2/rule3 ignored
106 + },
107 + }
108 +
109 + for name, test := range tests {
110 + t.Run(name, func(t *testing.T) {
111 + var cfg []ServiceRuleConfig
112 + err := yaml.Unmarshal([]byte(test.configYAML), &cfg)
113 + require.NoErrorf(t, err, "yaml unmarshalling of services config")
114 +
115 + svr, err := newServiceEngine(cfg)
116 + require.NoErrorf(t, err, "service engine creation")
117 +
118 + assert.Equal(t, test.wantConfigs, svr.compose(test.target))
119 + })
120 + }
121 +}
src/go/plugin/go.d/agent/discovery/sd/pipeline/sim_test.go
+39 -13
@@ -23,6 +23,9 @@ type discoverySim struct {
23 wantClassifyCalls int
24 wantComposeCalls int
25 wantConfGroups []*confgroup.Group
26 +
27 + // New: when true (or when cfg.Services is non-empty), run with services engine only.
28 + useServices bool
29 }
30
31 func (sim discoverySim) run(t *testing.T) {
@@ -32,15 +35,6 @@ func (sim discoverySim) run(t *testing.T) {
35 err := yaml.Unmarshal([]byte(sim.config), &cfg)
36 require.Nilf(t, err, "cfg unmarshal")
37
35 - clr, err := newTargetClassificator(cfg.Classify)
36 - require.Nil(t, err, "newTargetClassificator")
37 -
38 - cmr, err := newConfigComposer(cfg.Compose)
39 - require.Nil(t, err, "newConfigComposer")
40 -
41 - mockClr := &mockClassificator{clr: clr}
42 - mockCmr := &mockComposer{cmr: cmr}
43 -
38 accum := newAccumulator()
39 accum.sendEvery = time.Second * 2
40
@@ -48,12 +42,44 @@ func (sim discoverySim) run(t *testing.T) {
42 Logger: logger.New(),
43 discoverers: sim.discoverers,
44 accum: accum,
51 - clr: mockClr,
52 - cmr: mockCmr,
45 configs: make(map[string]map[uint64][]confgroup.Config),
46 }
55 -
47 pl.accum.Logger = pl.Logger
48 +
49 + // Prefer services when either explicitly requested or present in config.
50 + if sim.useServices || len(cfg.Services) > 0 {
51 + // --- services-only path ---
52 + svr, err := newServiceEngine(cfg.Services)
53 + require.Nil(t, err, "newServiceEngine")
54 +
55 + mockSvr := &mockComposer{cmr: svr} // reuse mock to count compose()
56 + pl.svr = mockSvr // set services engine
57 + svr.Logger = pl.Logger
58 +
59 + groups := sim.collectGroups(t, pl)
60 + sortConfigGroups(groups)
61 + sortConfigGroups(sim.wantConfGroups)
62 +
63 + assert.Equal(t, sim.wantConfGroups, groups)
64 + // When services is used, classify is not called.
65 + assert.Equalf(t, 0, sim.wantClassifyCalls, "classify calls should be zero in services mode")
66 + assert.Equalf(t, sim.wantComposeCalls, mockSvr.calls, "compose (services) calls")
67 + return
68 + }
69 +
70 + // --- legacy path ---
71 + clr, err := newTargetClassificator(cfg.Classify)
72 + require.Nil(t, err, "newTargetClassificator")
73 +
74 + cmr, err := newConfigComposer(cfg.Compose)
75 + require.Nil(t, err, "newConfigComposer")
76 +
77 + mockClr := &mockClassificator{clr: clr}
78 + mockCmr := &mockComposer{cmr: cmr}
79 +
80 + pl.clr = mockClr
81 + pl.cmr = mockCmr
82 +
83 clr.Logger = pl.Logger
84 cmr.Logger = pl.Logger
85
@@ -109,7 +135,7 @@ func (m *mockClassificator) classify(tgt model.Target) model.Tags {
135
136 type mockComposer struct {
137 calls int
112 - cmr *configComposer
138 + cmr composer
139 }
140
141 func (m *mockComposer) compose(tgt model.Target) []confgroup.Config {
src/go/plugin/go.d/config/go.d/sd/docker.conf
+290 -306
@@ -8,309 +8,293 @@ discover:
8 tags: "unknown"
9 address: "unix:///var/run/docker.sock"
10
11 -classify:
12 - - name: "Skip"
13 - selector: "unknown"
14 - tags: "skip"
15 - match:
16 - - tags: "skip"
17 - expr: |
18 - {{ $netNOK := eq .NetworkMode "host" -}}
19 - {{ $protoNOK := not (eq .PortProtocol "tcp") -}}
20 - {{ $portNOK := empty .PrivatePort -}}
21 - {{ $addrNOK := or (empty .IPAddress) (glob .PublicPortIP "*:*") -}}
22 - {{ or $netNOK $protoNOK $portNOK $addrNOK }}
23 - - name: "Applications"
24 - selector: "!skip unknown"
25 - tags: "-unknown app"
26 - match:
27 - - tags: "apache"
28 - expr: '{{ match "sp" .Image "httpd httpd:* */apache */apache:* */apache2 */apache2:*" }}'
29 - - tags: "beanstalk"
30 - expr: '{{ match "sp" .Image "*/beanstalkd */beanstalkd:*" }}'
31 - - tags: "boinc"
32 - expr: '{{ match "sp" .Image "boinc/client boinc/client:* */boinc */boinc:*" }}'
33 - - tags: "cockroachdb"
34 - expr: '{{ match "sp" .Image "cockroachdb/cockroach cockroachdb/cockroach:*" }}'
35 - - tags: "consul"
36 - expr: '{{ match "sp" .Image "consul consul:* */consul */consul:*" }}'
37 - - tags: "coredns"
38 - expr: '{{ match "sp" .Image "*/coredns */coredns:*" }}'
39 - - tags: "couchbase"
40 - expr: '{{ or (eq .PrivatePort "8091") (match "sp" .Image "couchbase couchbase:*") }}'
41 - - tags: "couchdb"
42 - expr: '{{ or (eq .PrivatePort "5984") (match "sp" .Image "couchdb couchdb:*") }}'
43 - - tags: "dovecot"
44 - expr: '{{ or (eq .PrivatePort "24242") (match "sp" .Image "*/dovecot */dovecot:*") }}'
45 - - tags: "elasticsearch"
46 - expr: '{{ or (eq .PrivatePort "9200") (match "sp" .Image "elasticsearch elasticsearch:* */elasticsearch */elasticsearch:* */opensearch */opensearch:*") }}'
47 - - tags: "gearman"
48 - expr: '{{ and (eq .PrivatePort "4730") (match "sp" .Image "*/gearmand */gearmand:*") }}'
49 - - tags: "ipfs"
50 - expr: '{{ and (eq .PrivatePort "5001") (match "sp" .Image "ipfs/kubo ipfs/kubo:*") }}'
51 - - tags: "lighttpd"
52 - expr: '{{ match "sp" .Image "*/lighttpd */lighttpd:*" }}'
53 - - tags: "maxscale"
54 - expr: '{{ or (eq .PrivatePort "8989") (match "sp" .Image "mariadb/maxscale mariadb/maxscale:*") }}'
55 - - tags: "memcached"
56 - expr: '{{ or (eq .PrivatePort "11211") (match "sp" .Image "memcached memcached:* */memcached */memcached:*") }}'
57 - - tags: "mongodb"
58 - expr: '{{ or (eq .PrivatePort "27017") (match "sp" .Image "mongo mongo:* */mongodb */mongodb:* */mongodb-community-server */mongodb-community-server:*") }}'
59 - - tags: "mysql"
60 - expr: '{{ or (eq .PrivatePort "3306") (match "sp" .Image "mysql mysql:* */mysql */mysql:* mariadb mariadb:* */mariadb */mariadb:* percona percona:* */percona-mysql */percona-mysql:*") }}'
61 - - tags: "nats"
62 - expr: '{{ and (eq .PrivatePort "8222") (match "sp" .Image "nats nats:*") }}'
63 - - tags: "nginx"
64 - expr: '{{ match "sp" .Image "nginx nginx:*" }}'
65 - - tags: "nginxunit"
66 - expr: '{{ match "sp" .Image "nginx/unit nginx/unit:*" }}'
67 - - tags: "oracledb"
68 - expr: '{{ and (eq .PrivatePort "1521" "2484") (match "sp" .Image "oracle/database oracle/database:*") }}'
69 - - tags: "pgbouncer"
70 - expr: '{{ or (eq .PrivatePort "6432") (match "sp" .Image "*/pgbouncer */pgbouncer:*") }}'
71 - - tags: "pika"
72 - expr: '{{ match "sp" .Image "pikadb/pika pikadb/pika:*" }}'
73 - - tags: "postgres"
74 - expr: '{{ or (eq .PrivatePort "5432") (match "sp" .Image "postgres postgres:* */postgres */postgres:* */postgresql */postgresql:*") }}'
75 - - tags: "proxysql"
76 - expr: '{{ or (eq .PrivatePort "6032") (match "sp" .Image "*/proxysql */proxysql:*") }}'
77 - - tags: "puppet"
78 - expr: '{{ or (eq .PrivatePort "8140") (match "sp" .Image "puppet/puppetserver puppet/puppetserver:*") }}'
79 - - tags: "rabbitmq"
80 - expr: '{{ or (eq .PrivatePort "15672") (match "sp" .Image "rabbitmq rabbitmq:* */rabbitmq */rabbitmq:*") }}'
81 - - tags: "redis"
82 - expr: '{{ or (eq .PrivatePort "6379") (match "sp" .Image "redis redis:* */redis */redis:*") }}'
83 - - tags: "rethinkdb"
84 - expr: '{{ and (eq .PrivatePort "28015") (match "sp" .Image "rethinkdb rethinkdb:* */rethinkdb */rethinkdb:*") }}'
85 - - tags: "squid"
86 - expr: '{{ match "sp" .Image "*/squid */squid:*" }}'
87 - - tags: "tengine"
88 - expr: '{{ match "sp" .Image "*/tengine */tengine:*" }}'
89 - - tags: "tor"
90 - expr: '{{ and (eq .PrivatePort "9051") (match "sp" .Image "*/tor */tor:*") }}'
91 - - tags: "tomcat"
92 - expr: '{{ match "sp" .Image "tomcat tomcat:* */tomcat */tomcat:*" }}'
93 - - tags: "typesense"
94 - expr: '{{ match "sp" .Image "typesense/typesense typesense/typesense:*" }}'
95 - - tags: "varnish"
96 - expr: '{{ match "sp" .Image "varnish varnish:*" }}'
97 - - tags: "vernemq"
98 - expr: '{{ match "sp" .Image "*/vernemq */vernemq:*" }}'
99 - - tags: "zookeeper"
100 - expr: '{{ or (eq .PrivatePort "2181") (match "sp" .Image "*/zookeeper */zookeeper:*") }}'
101 -compose:
102 - - name: "Applications"
103 - selector: "app"
104 - config:
105 - - selector: "apache"
106 - template: |
107 - module: apache
108 - name: docker_{{.Name}}
109 - url: http://{{.Address}}/server-status?auto
110 - - selector: "beanstalk"
111 - template: |
112 - module: beanstalk
113 - name: docker_{{.Name}}
114 - address: {{.Address}}
115 - - selector: "boinc"
116 - template: |
117 - module: boinc
118 - name: docker_{{.Name}}
119 - address: {{.Address}}
120 - - selector: "cockroachdb"
121 - template: |
122 - module: cockroachdb
123 - name: docker_{{.Name}}
124 - url: http://{{.Address}}/_status/vars
125 - - selector: "consul"
126 - template: |
127 - module: consul
128 - name: docker_{{.Name}}
129 - url: http://{{.Address}}
130 - - selector: "coredns"
131 - template: |
132 - module: coredns
133 - name: docker_{{.Name}}
134 - url: http://{{.Address}}/metrics
135 - - selector: "coredns"
136 - template: |
137 - module: coredns
138 - name: docker_{{.Name}}
139 - url: http://{{.Address}}/metrics
140 - - selector: "couchbase"
141 - template: |
142 - module: couchbase
143 - name: docker_{{.Name}}
144 - url: http://{{.Address}}
145 - - selector: "couchdb"
146 - template: |
147 - module: couchdb
148 - name: docker_{{.Name}}
149 - url: http://{{.Address}}
150 - - selector: "dovecot"
151 - template: |
152 - module: dovecot
153 - name: docker_{{.Name}}
154 - address: {{.Address}}
155 - - selector: "elasticsearch"
156 - template: |
157 - module: elasticsearch
158 - name: docker_{{.Name}}
159 - {{ if glob .Image "*elastic*" -}}
160 - url: http://{{.Address}}
161 - {{ else -}}
162 - url: https://{{.Address}}
163 - tls_skip_verify: yes
164 - username: admin
165 - password: admin
166 - {{ end -}}
167 - - selector: "gearman"
168 - template: |
169 - module: gearman
170 - name: docker_{{.Name}}
171 - address: {{.Address}}
172 - - selector: "ipfs"
173 - template: |
174 - module: ipfs
175 - name: docker_{{.Name}}
176 - url: http://{{.Address}}
177 - - selector: "lighttpd"
178 - template: |
179 - module: lighttpd
180 - name: docker_{{.Name}}
181 - url: http://{{.Address}}/server-status?auto
182 - - selector: "maxscale"
183 - template: |
184 - module: maxscale
185 - name: docker_{{.Name}}
186 - url: http://{{.Address}}
187 - - selector: "memcached"
188 - template: |
189 - module: memcached
190 - name: docker_{{.Name}}
191 - address: {{.Address}}
192 - - selector: "mongodb"
193 - template: |
194 - module: mongodb
195 - name: docker_{{.Name}}
196 - uri: mongodb://{{.Address}}
197 - - selector: "mysql"
198 - template: |
199 - module: mysql
200 - name: docker_{{.Name}}
201 - dsn: netdata@tcp({{.Address}})/
202 - - selector: "nats"
203 - template: |
204 - - module: nats
205 - name: docker_{{.Name}}
206 - url: http://{{.Address}}
207 - - selector: "nginx"
208 - template: |
209 - - module: nginx
210 - name: docker_{{.Name}}
211 - url: http://{{.Address}}/stub_status
212 - - module: nginx
213 - name: docker_{{.Name}}
214 - url: http://{{.Address}}/basic_status
215 - - module: nginx
216 - name: docker_{{.Name}}
217 - url: http://{{.Address}}/nginx_status
218 - - module: nginx
219 - name: docker_{{.Name}}
220 - url: http://{{.Address}}/status
221 - - selector: "nginxunit"
222 - template: |
223 - - module: nginxunit
224 - name: docker_{{.Name}}
225 - url: http://{{.Address}}
226 - - selector: "oracledb"
227 - template: |
228 - module: oracledb
229 - name: docker_{{.Name}}
230 - {{ if eq .PrivatePort "1521" -}}
231 - dsn: 'oracle://username:password@{{.Address}}/XE'
232 - {{ else -}}
233 - dsn: 'oracle://username:password@{{.Address}}/XE?ssl=true&ssl verify=false'
234 - {{ end -}}
235 - - selector: "pgbouncer"
236 - template: |
237 - module: pgbouncer
238 - name: docker_{{.Name}}
239 - dsn: postgres://netdata:postgres@{{.Address}}/pgbouncer
240 - - selector: "pika"
241 - template: |
242 - module: pika
243 - name: docker_{{.Name}}
244 - address: redis://@{{.Address}}
245 - - selector: "rethinkdb"
246 - template: |
247 - module: rethinkdb
248 - name: docker_{{.Name}}
249 - address: {{.Address}}
250 - - selector: "postgres"
251 - template: |
252 - module: postgres
253 - name: docker_{{.Name}}
254 - dsn: postgres://netdata:postgres@{{.Address}}/postgres
255 - - selector: "proxysql"
256 - template: |
257 - module: proxysql
258 - name: docker_{{.Name}}
259 - dsn: stats:stats@tcp({{.Address}})/
260 - - selector: "puppet"
261 - template: |
262 - module: puppet
263 - name: docker_{{.Name}}
264 - url: https://{{.Address}}
265 - tls_skip_verify: yes
266 - - selector: "rabbitmq"
267 - template: |
268 - module: rabbitmq
269 - name: docker_{{.Name}}
270 - url: http://{{.Address}}
271 - - selector: "redis"
272 - template: |
273 - module: redis
274 - name: docker_{{.Name}}
275 - address: redis://@{{.Address}}
276 - - selector: "squid"
277 - template: |
278 - module: squid
279 - name: docker_{{.Name}}
280 - url: http://{{.Address}}
281 - - selector: "tengine"
282 - template: |
283 - module: tengine
284 - name: docker_{{.Name}}
285 - url: http://{{.Address}}/us
286 - - selector: "tomcat"
287 - template: |
288 - module: tomcat
289 - name: docker_{{.Name}}
290 - url: http://{{.Address}}
291 - - selector: "typesense"
292 - template: |
293 - module: typesense
294 - name: docker_{{.Name}}
295 - url: http://{{.Address}}
296 - api_key: {{ trimPrefix "--api-key=" (regexFind "--api-key=[^ ]+" .Command) -}}
297 - - selector: "tor"
298 - template: |
299 - module: tor
300 - name: docker_{{.Name}}
301 - address: {{.Address}}
302 - - selector: "varnish"
303 - template: |
304 - module: varnish
305 - name: docker_{{.Name}}
306 - docker_container: {{.Name}}
307 - - selector: "vernemq"
308 - template: |
309 - module: vernemq
310 - name: docker_{{.Name}}
311 - url: http://{{.Address}}/metrics
312 - - selector: "zookeeper"
313 - template: |
314 - module: zookeeper
315 - name: docker_{{.Name}}
316 - address: {{.Address}}
11 +services:
12 + - id: "skip"
13 + match: |
14 + {{ $netNOK := eq .NetworkMode "host" -}}
15 + {{ $protoNOK := not (eq .PortProtocol "tcp") -}}
16 + {{ $portNOK := empty .PrivatePort -}}
17 + {{ $addrNOK := or (empty .IPAddress) (glob .PublicPortIP "*:*") -}}
18 + {{ or $netNOK $protoNOK $portNOK $addrNOK }}
19 +
20 + - id: "apache"
21 + match: '{{ match "sp" .Image "httpd httpd:* */apache */apache:* */apache2 */apache2:*" }}'
22 + config_template: |
23 + module: apache
24 + name: docker_{{.Name}}
25 + url: http://{{.Address}}/server-status?auto
26 +
27 + - id: "beanstalk"
28 + match: '{{ match "sp" .Image "*/beanstalkd */beanstalkd:*" }}'
29 + config_template: |
30 + module: beanstalk
31 + name: docker_{{.Name}}
32 + address: {{.Address}}
33 +
34 + - id: "boinc"
35 + match: '{{ match "sp" .Image "boinc/client boinc/client:* */boinc */boinc:*" }}'
36 + config_template: |
37 + module: boinc
38 + name: docker_{{.Name}}
39 + address: {{.Address}}
40 +
41 + - id: "cockroachdb"
42 + match: '{{ match "sp" .Image "cockroachdb/cockroach cockroachdb/cockroach:*" }}'
43 + config_template: |
44 + module: cockroachdb
45 + name: docker_{{.Name}}
46 + url: http://{{.Address}}/_status/vars
47 +
48 + - id: "consul"
49 + match: '{{ match "sp" .Image "consul consul:* */consul */consul:*" }}'
50 + config_template: |
51 + module: consul
52 + name: docker_{{.Name}}
53 + url: http://{{.Address}}
54 +
55 + - id: "coredns"
56 + match: '{{ match "sp" .Image "*/coredns */coredns:*" }}'
57 + config_template: |
58 + module: coredns
59 + name: docker_{{.Name}}
60 + url: http://{{.Address}}/metrics
61 +
62 + - id: "couchbase"
63 + match: '{{ or (eq .PrivatePort "8091") (match "sp" .Image "couchbase couchbase:*") }}'
64 + config_template: |
65 + module: couchbase
66 + name: docker_{{.Name}}
67 + url: http://{{.Address}}
68 +
69 + - id: "couchdb"
70 + match: '{{ or (eq .PrivatePort "5984") (match "sp" .Image "couchdb couchdb:*") }}'
71 + config_template: |
72 + module: couchdb
73 + name: docker_{{.Name}}
74 + url: http://{{.Address}}
75 +
76 + - id: "dovecot"
77 + match: '{{ or (eq .PrivatePort "24242") (match "sp" .Image "*/dovecot */dovecot:*") }}'
78 + config_template: |
79 + module: dovecot
80 + name: docker_{{.Name}}
81 + address: {{.Address}}
82 +
83 + - id: "elasticsearch"
84 + match: '{{ or (eq .PrivatePort "9200") (match "sp" .Image "elasticsearch elasticsearch:* */elasticsearch */elasticsearch:* */opensearch */opensearch:*") }}'
85 + config_template: |
86 + module: elasticsearch
87 + name: docker_{{.Name}}
88 + {{ if glob .Image "*elastic*" -}}
89 + url: http://{{.Address}}
90 + {{ else -}}
91 + url: https://{{.Address}}
92 + tls_skip_verify: yes
93 + username: admin
94 + password: admin
95 + {{ end -}}
96 +
97 + - id: "gearman"
98 + match: '{{ and (eq .PrivatePort "4730") (match "sp" .Image "*/gearmand */gearmand:*") }}'
99 + config_template: |
100 + module: gearman
101 + name: docker_{{.Name}}
102 + address: {{.Address}}
103 +
104 + - id: "ipfs"
105 + match: '{{ and (eq .PrivatePort "5001") (match "sp" .Image "ipfs/kubo ipfs/kubo:*") }}'
106 + config_template: |
107 + module: ipfs
108 + name: docker_{{.Name}}
109 + url: http://{{.Address}}
110 +
111 + - id: "lighttpd"
112 + match: '{{ match "sp" .Image "*/lighttpd */lighttpd:*" }}'
113 + config_template: |
114 + module: lighttpd
115 + name: docker_{{.Name}}
116 + url: http://{{.Address}}/server-status?auto
117 +
118 + - id: "maxscale"
119 + match: '{{ or (eq .PrivatePort "8989") (match "sp" .Image "mariadb/maxscale mariadb/maxscale:*") }}'
120 + config_template: |
121 + module: maxscale
122 + name: docker_{{.Name}}
123 + url: http://{{.Address}}
124 +
125 + - id: "memcached"
126 + match: '{{ or (eq .PrivatePort "11211") (match "sp" .Image "memcached memcached:* */memcached */memcached:*") }}'
127 + config_template: |
128 + module: memcached
129 + name: docker_{{.Name}}
130 + address: {{.Address}}
131 +
132 + - id: "mongodb"
133 + match: '{{ or (eq .PrivatePort "27017") (match "sp" .Image "mongo mongo:* */mongodb */mongodb:* */mongodb-community-server */mongodb-community-server:*") }}'
134 + config_template: |
135 + module: mongodb
136 + name: docker_{{.Name}}
137 + uri: mongodb://{{.Address}}
138 +
139 + - id: "mysql"
140 + match: '{{ or (eq .PrivatePort "3306") (match "sp" .Image "mysql mysql:* */mysql */mysql:* mariadb mariadb:* */mariadb */mariadb:* percona percona:* */percona-mysql */percona-mysql:*") }}'
141 + config_template: |
142 + module: mysql
143 + name: docker_{{.Name}}
144 + dsn: netdata@tcp({{.Address}})/
145 +
146 + - id: "nats"
147 + match: '{{ and (eq .PrivatePort "8222") (match "sp" .Image "nats nats:*") }}'
148 + config_template: |
149 + - module: nats
150 + name: docker_{{.Name}}
151 + url: http://{{.Address}}
152 +
153 + - id: "nginx"
154 + match: '{{ match "sp" .Image "nginx nginx:*" }}'
155 + config_template: |
156 + - module: nginx
157 + name: docker_{{.Name}}
158 + url: http://{{.Address}}/stub_status
159 + - module: nginx
160 + name: docker_{{.Name}}
161 + url: http://{{.Address}}/basic_status
162 + - module: nginx
163 + name: docker_{{.Name}}
164 + url: http://{{.Address}}/nginx_status
165 + - module: nginx
166 + name: docker_{{.Name}}
167 + url: http://{{.Address}}/status
168 +
169 + - id: "nginxunit"
170 + match: '{{ match "sp" .Image "nginx/unit nginx/unit:*" }}'
171 + config_template: |
172 + - module: nginxunit
173 + name: docker_{{.Name}}
174 + url: http://{{.Address}}
175 +
176 + - id: "oracledb"
177 + match: '{{ and (eq .PrivatePort "1521" "2484") (match "sp" .Image "oracle/database oracle/database:*") }}'
178 + config_template: |
179 + module: oracledb
180 + name: docker_{{.Name}}
181 + {{ if eq .PrivatePort "1521" -}}
182 + dsn: 'oracle://username:password@{{.Address}}/XE'
183 + {{ else -}}
184 + dsn: 'oracle://username:password@{{.Address}}/XE?ssl=true&ssl verify=false'
185 + {{ end -}}
186 +
187 + - id: "pgbouncer"
188 + match: '{{ or (eq .PrivatePort "6432") (match "sp" .Image "*/pgbouncer */pgbouncer:*") }}'
189 + config_template: |
190 + module: pgbouncer
191 + name: docker_{{.Name}}
192 + dsn: postgres://netdata:postgres@{{.Address}}/pgbouncer
193 +
194 + - id: "pika"
195 + match: '{{ match "sp" .Image "pikadb/pika pikadb/pika:*" }}'
196 + config_template: |
197 + module: pika
198 + name: docker_{{.Name}}
199 + address: redis://@{{.Address}}
200 +
201 + - id: "postgres"
202 + match: '{{ or (eq .PrivatePort "5432") (match "sp" .Image "postgres postgres:* */postgres */postgres:* */postgresql */postgresql:*") }}'
203 + config_template: |
204 + module: postgres
205 + name: docker_{{.Name}}
206 + dsn: postgres://netdata:postgres@{{.Address}}/postgres
207 +
208 + - id: "proxysql"
209 + match: '{{ or (eq .PrivatePort "6032") (match "sp" .Image "*/proxysql */proxysql:*") }}'
210 + config_template: |
211 + module: proxysql
212 + name: docker_{{.Name}}
213 + dsn: stats:stats@tcp({{.Address}})/
214 +
215 + - id: "puppet"
216 + match: '{{ or (eq .PrivatePort "8140") (match "sp" .Image "puppet/puppetserver puppet/puppetserver:*") }}'
217 + config_template: |
218 + module: puppet
219 + name: docker_{{.Name}}
220 + url: https://{{.Address}}
221 + tls_skip_verify: yes
222 +
223 + - id: "rabbitmq"
224 + match: '{{ or (eq .PrivatePort "15672") (match "sp" .Image "rabbitmq rabbitmq:* */rabbitmq */rabbitmq:*") }}'
225 + config_template: |
226 + module: rabbitmq
227 + name: docker_{{.Name}}
228 + url: http://{{.Address}}
229 +
230 + - id: "redis"
231 + match: '{{ or (eq .PrivatePort "6379") (match "sp" .Image "redis redis:* */redis */redis:*") }}'
232 + config_template: |
233 + module: redis
234 + name: docker_{{.Name}}
235 + address: redis://@{{.Address}}
236 +
237 + - id: "rethinkdb"
238 + match: '{{ and (eq .PrivatePort "28015") (match "sp" .Image "rethinkdb rethinkdb:* */rethinkdb */rethinkdb:*") }}'
239 + config_template: |
240 + module: rethinkdb
241 + name: docker_{{.Name}}
242 + address: {{.Address}}
243 +
244 + - id: "squid"
245 + match: '{{ match "sp" .Image "*/squid */squid:*" }}'
246 + config_template: |
247 + module: squid
248 + name: docker_{{.Name}}
249 + url: http://{{.Address}}
250 +
251 + - id: "tengine"
252 + match: '{{ match "sp" .Image "*/tengine */tengine:*" }}'
253 + config_template: |
254 + module: tengine
255 + name: docker_{{.Name}}
256 + url: http://{{.Address}}/us
257 +
258 + - id: "tor"
259 + match: '{{ and (eq .PrivatePort "9051") (match "sp" .Image "*/tor */tor:*") }}'
260 + config_template: |
261 + module: tor
262 + name: docker_{{.Name}}
263 + address: {{.Address}}
264 +
265 + - id: "tomcat"
266 + match: '{{ match "sp" .Image "tomcat tomcat:* */tomcat */tomcat:*" }}'
267 + config_template: |
268 + module: tomcat
269 + name: docker_{{.Name}}
270 + url: http://{{.Address}}
271 +
272 + - id: "typesense"
273 + match: '{{ match "sp" .Image "typesense/typesense typesense/typesense:*" }}'
274 + config_template: |
275 + module: typesense
276 + name: docker_{{.Name}}
277 + url: http://{{.Address}}
278 + api_key: {{ trimPrefix "--api-key=" (regexFind "--api-key=[^ ]+" .Command) -}}
279 +
280 + - id: "varnish"
281 + match: '{{ match "sp" .Image "varnish varnish:*" }}'
282 + config_template: |
283 + module: varnish
284 + name: docker_{{.Name}}
285 + docker_container: {{.Name}}
286 +
287 + - id: "vernemq"
288 + match: '{{ match "sp" .Image "*/vernemq */vernemq:*" }}'
289 + config_template: |
290 + module: vernemq
291 + name: docker_{{.Name}}
292 + url: http://{{.Address}}/metrics
293 +
294 + - id: "zookeeper"
295 + match: '{{ or (eq .PrivatePort "2181") (match "sp" .Image "*/zookeeper */zookeeper:*") }}'
296 + config_template: |
297 + module: zookeeper
298 + name: docker_{{.Name}}
299 + address: {{.Address}}
300 +
src/go/plugin/go.d/config/go.d/sd/net_listeners.conf
+605 -627
@@ -7,630 +7,608 @@ discover:
7 net_listeners:
8 tags: "unknown"
9
10 -classify:
11 - - name: "Applications"
12 - selector: "unknown"
13 - tags: "-unknown app"
14 - match:
15 - - tags: "activemq"
16 - expr: '{{ and (eq .Port "8161") (eq .Comm "activemq") }}'
17 - - tags: "apache"
18 - expr: '{{ and (eq .Port "80" "8080") (eq .Comm "apache" "apache2" "httpd") }}'
19 - - tags: "apcupsd"
20 - expr: '{{ or (eq .Port "3551") (eq .Comm "apcupsd") }}'
21 - - tags: "beanstalk"
22 - expr: '{{ or (eq .Port "11300") (eq .Comm "beanstalkd") }}'
23 - - tags: "boinc"
24 - expr: '{{ and (eq .Port "31416") (eq .Comm "boinc") }}'
25 - - tags: "bind"
26 - expr: '{{ and (eq .Port "8653") (eq .Comm "bind" "named") }}'
27 - - tags: "cassandra"
28 - expr: '{{ and (eq .Port "7072") (glob .Cmdline "*cassandra*") }}'
29 - - tags: "ceph"
30 - expr: '{{ and (eq .Port "8443") (eq .Comm "ceph-mgr") }}'
31 - - tags: "chrony"
32 - expr: '{{ and (eq .Port "323") (eq .Comm "chronyd") }}'
33 - - tags: "clickhouse"
34 - expr: '{{ and (eq .Port "8123") (eq .Comm "clickhouse-server") }}'
35 - - tags: "cockroachdb"
36 - expr: '{{ and (eq .Port "8080") (eq .Comm "cockroach") }}'
37 - - tags: "consul"
38 - expr: '{{ and (eq .Port "8500") (eq .Comm "consul") }}'
39 - - tags: "coredns"
40 - expr: '{{ and (eq .Port "9153") (eq .Comm "coredns") }}'
41 - - tags: "couchbase"
42 - expr: '{{ or (eq .Port "8091") (glob .Cmdline "*couchbase*") }}'
43 - - tags: "couchdb"
44 - expr: '{{ or (eq .Port "5984") (glob .Cmdline "*couchdb*") }}'
45 - - tags: "dnsdist"
46 - expr: '{{ and (eq .Port "8083") (eq .Comm "dnsdist") }}'
47 - - tags: "dnsmasq"
48 - expr: '{{ and (eq .Protocol "UDP") (eq .Port "53") (eq .Comm "dnsmasq") }}'
49 - - tags: "docker_engine"
50 - expr: '{{ and (eq .Port "9323") (eq .Comm "dockerd") }}'
51 - - tags: "dovecot"
52 - expr: '{{ and (eq .Port "24242") (eq .Comm "dovecot") }}'
53 - - tags: "elasticsearch"
54 - expr: '{{ or (eq .Port "9200") (glob .Cmdline "*elasticsearch*" "*opensearch*") }}'
55 - - tags: "envoy"
56 - expr: '{{ and (eq .Port "9901") (eq .Comm "envoy") }}'
57 - - tags: "fluentd"
58 - expr: '{{ and (eq .Port "24220") (glob .Cmdline "*fluentd*") }}'
59 - - tags: "freeradius"
60 - expr: '{{ and (eq .Port "18121") (eq .Comm "freeradius") }}'
61 - - tags: "gearman"
62 - expr: '{{ or (eq .Port "4730") (eq .Comm "gearmand") }}'
63 - - tags: "geth"
64 - expr: '{{ and (eq .Port "6060") (eq .Comm "geth") }}'
65 - - tags: "haproxy"
66 - expr: '{{ and (eq .Port "8404") (eq .Comm "haproxy") }}'
67 - - tags: "hddtemp"
68 - expr: '{{ and (eq .Port "7634") (eq .Comm "hddtemp") }}'
69 - - tags: "hdfs_namenode"
70 - expr: '{{ and (eq .Port "9870") (eq .Comm "hadoop") }}'
71 - - tags: "hdfs_datanode"
72 - expr: '{{ and (eq .Port "9864") (eq .Comm "hadoop") }}'
73 - - tags: "icecast"
74 - expr: '{{ and (eq .Port "8000") (eq .Comm "icecast") }}'
75 - - tags: "ipfs"
76 - expr: '{{ and (eq .Port "5001") (eq .Comm "ipfs") }}'
77 - - tags: "kubelet"
78 - expr: '{{ and (eq .Port "10250" "10255") (eq .Comm "kubelet") }}'
79 - - tags: "kubeproxy"
80 - expr: '{{ and (eq .Port "10249") (eq .Comm "kube-proxy") }}'
81 - - tags: "lighttpd"
82 - expr: '{{ and (eq .Port "80" "8080") (eq .Comm "lighttpd") }}'
83 - - tags: "logstash"
84 - expr: '{{ and (eq .Port "9600") (glob .Cmdline "*logstash*") }}'
85 - - tags: "maxscale"
86 - expr: '{{ or (eq .Port "8989") (eq .Comm "maxscale") }}'
87 - - tags: "memcached"
88 - expr: '{{ or (eq .Port "11211") (eq .Comm "memcached") }}'
89 - - tags: "mongodb"
90 - expr: '{{ or (eq .Port "27017") (eq .Comm "mongod") }}'
91 - - tags: "monit"
92 - expr: '{{ or (eq .Port "2812") (eq .Comm "monit") }}'
93 - - tags: "mysql"
94 - expr: '{{ or (eq .Port "3306") (eq .Comm "mysqld" "mariadbd") }}'
95 - - tags: "nats"
96 - expr: '{{ and (eq .Port "8222") (eq .Comm "nats-server") }}'
97 - - tags: "nginx"
98 - expr: '{{ and (eq .Port "80" "8080") (eq .Comm "nginx") }}'
99 - - tags: "nginxunit"
100 - expr: '{{ and (eq .Port "8000") (eq .Comm "unit") }}'
101 - - tags: "ntpd"
102 - expr: '{{ or (eq .Port "123") (eq .Comm "ntpd") }}'
103 - - tags: "openldap"
104 - expr: '{{ eq .Comm "slapd" }}'
105 - - tags: "openvpn"
106 - expr: '{{ and (eq .Port "7505") (eq .Comm "openvpn") }}'
107 - - tags: "oracledb"
108 - expr: '{{ and (eq .Port "1521" "2484") (eq .Comm "tnslsnr") }}'
109 - - tags: "pgbouncer"
110 - expr: '{{ or (eq .Port "6432") (eq .Comm "pgbouncer") }}'
111 - - tags: "pihole"
112 - expr: '{{ and (eq .Port "80") (eq .Comm "pihole-FTL") }}'
113 - - tags: "pika"
114 - expr: '{{ and (eq .Port "9221") (eq .Comm "pika") }}'
115 - - tags: "postgres"
116 - expr: '{{ or (eq .Port "5432") (eq .Comm "postgres") }}'
117 - - tags: "powerdns"
118 - expr: '{{ and (eq .Port "8081") (eq .Comm "pdns_server") }}'
119 - - tags: "powerdns_recursor"
120 - expr: '{{ and (eq .Port "8081") (eq .Comm "pdns_recursor") }}'
121 - - tags: "proxysql"
122 - expr: '{{ or (eq .Port "6032") (eq .Comm "proxysql") }}'
123 - - tags: "puppet"
124 - expr: '{{ or (eq .Port "8140") (glob .Cmdline "*puppet-server*") }}'
125 - - tags: "rabbitmq"
126 - expr: '{{ or (eq .Port "15672") (glob .Cmdline "*rabbitmq*") }}'
127 - - tags: "redis"
128 - expr: '{{ or (eq .Port "6379") (eq .Comm "redis-server") }}'
129 - - tags: "rethinkdb"
130 - expr: '{{ and (eq .Port "28015") (eq .Comm "rethinkdb") }}'
131 - - tags: "riak"
132 - expr: '{{ and (eq .Port "8098") (glob .Cmdline "*riak*") }}'
133 - - tags: "rspamd"
134 - expr: '{{ and (eq .Port "11334") (eq .Comm "rspamd") }}'
135 - - tags: "squid"
136 - expr: '{{ and (eq .Port "3128") (eq .Comm "squid") }}'
137 - - tags: "spigotmc"
138 - expr: '{{ and (eq .Port "25575") (glob .Cmdline "*spigot*") }}'
139 - - tags: "supervisord"
140 - expr: '{{ and (eq .Port "9001") (eq .Comm "supervisord") }}'
141 - - tags: "tomcat"
142 - expr: '{{ and (eq .Port "8080") (glob .Cmdline "*tomcat*") }}'
143 - - tags: "tor"
144 - expr: '{{ and (eq .Port "9051") (eq .Comm "tor") }}'
145 - - tags: "traefik"
146 - expr: '{{ and (eq .Port "80" "8080") (eq .Comm "traefik") }}'
147 - - tags: "typesense"
148 - expr: '{{ and (eq .Port "8108") (eq .Comm "typesense-server") }}'
149 - - tags: "unbound"
150 - expr: '{{ and (eq .Port "8953") (eq .Comm "unbound") }}'
151 - - tags: "upsd"
152 - expr: '{{ or (eq .Port "3493") (eq .Comm "upsd") }}'
153 - - tags: "uwsgi"
154 - expr: '{{ and (eq .Port "1717") (eq .Comm "uwsgi") }}'
155 - - tags: "vernemq"
156 - expr: '{{ and (eq .Port "8888") (glob .Cmdline "*vernemq*") }}'
157 - - tags: "yugabytedb"
158 - expr: '{{ and (eq .Port "7000" "9000" "12000" "13000") (or (glob .Cmdline "*YSQL*") (eq .Comm "yb-master" "yb-tserver")) }}'
159 - - tags: "zookeeper"
160 - expr: '{{ or (eq .Port "2181" "2182") (glob .Cmdline "*zookeeper*") }}'
161 - - name: "Prometheus exporters"
162 - selector: "unknown"
163 - tags: "-unknown exporter"
164 - match:
165 - - tags: "exporter"
166 - expr: '{{ or (and (not (empty (promPort .Port))) (not (eq .Comm "docker-proxy"))) (glob .Comm "*exporter*") }}'
167 -compose:
168 - - name: "Applications"
169 - selector: "app"
170 - config:
171 - - selector: "activemq"
172 - template: |
173 - module: activemq
174 - name: local
175 - url: http://{{.Address}}
176 - webadmin: admin
177 - - selector: "apache"
178 - template: |
179 - module: apache
180 - name: local
181 - url: http://{{.Address}}/server-status?auto
182 - - selector: "apcupsd"
183 - template: |
184 - module: apcupsd
185 - name: local_{{.Port}}
186 - address: {{.Address}}
187 - - selector: "beanstalk"
188 - template: |
189 - module: beanstalk
190 - name: local
191 - address: {{.Address}}
192 - - selector: "bind"
193 - template: |
194 - module: bind
195 - name: local
196 - url: http://{{.Address}}/json/v1
197 - - selector: "boinc"
198 - template: |
199 - module: boinc
200 - name: local
201 - address: {{.Address}}
202 - - selector: "cassandra"
203 - template: |
204 - module: cassandra
205 - name: local
206 - url: http://{{.Address}}/metrics
207 - - selector: "ceph"
208 - template: |
209 - module: ceph
210 - name: local
211 - url: https://{{.Address}}
212 - - selector: "chrony"
213 - template: |
214 - module: chrony
215 - name: local
216 - address: {{.Address}}
217 - - selector: "clickhouse"
218 - template: |
219 - module: clickhouse
220 - name: local
221 - url: http://{{.Address}}
222 - - selector: "cockroachdb"
223 - template: |
224 - module: cockroachdb
225 - name: local
226 - url: http://{{.Address}}/_status/vars
227 - - selector: "consul"
228 - template: |
229 - module: consul
230 - name: local
231 - url: http://{{.Address}}
232 - - selector: "coredns"
233 - template: |
234 - module: coredns
235 - name: local
236 - url: http://{{.Address}}/metrics
237 - - selector: "couchbase"
238 - template: |
239 - module: couchbase
240 - name: local
241 - url: http://{{.Address}}
242 - - selector: "couchdb"
243 - template: |
244 - module: couchdb
245 - name: local
246 - url: http://{{.Address}}
247 - node: '_local'
248 - - selector: "dnsdist"
249 - template: |
250 - module: dnsdist
251 - name: local
252 - url: http://{{.Address}}
253 - headers:
254 - X-API-Key: 'dnsdist-api-key'
255 - - selector: "dnsmasq"
256 - template: |
257 - module: dnsmasq
258 - name: local
259 - protocol: udp
260 - address: {{.Address}}
261 - - selector: "docker_engine"
262 - template: |
263 - module: docker_engine
264 - name: local
265 - url: http://{{.Address}}/metrics
266 - - selector: "dovecot"
267 - template: |
268 - module: dovecot
269 - name: local
270 - address: {{.Address}}
271 - - selector: "elasticsearch"
272 - template: |
273 - module: elasticsearch
274 - name: local
275 - {{ if glob .Cmdline "*elastic*" -}}
276 - url: http://{{.Address}}
277 - {{ else -}}
278 - url: https://{{.Address}}
279 - tls_skip_verify: yes
280 - username: admin
281 - password: admin
282 - {{ end -}}
283 - - selector: "envoy"
284 - template: |
285 - module: envoy
286 - name: local
287 - url: http://{{.Address}}/stats/prometheus
288 - - selector: "envoy"
289 - template: |
290 - module: envoy
291 - name: local
292 - url: http://{{.Address}}/stats/prometheus
293 - - selector: "fluentd"
294 - template: |
295 - module: fluentd
296 - name: local
297 - url: http://{{.Address}}
298 - - selector: "freeradius"
299 - template: |
300 - module: freeradius
301 - name: local
302 - address: {{.IPAddress}}
303 - port: {{.Port}}
304 - secret: adminsecret
305 - - selector: "gearman"
306 - template: |
307 - module: gearman
308 - name: local
309 - address: {{.Address}}
310 - - selector: "geth"
311 - template: |
312 - module: geth
313 - name: local
314 - url: http://{{.Address}}/debug/metrics/prometheus
315 - - selector: "haproxy"
316 - template: |
317 - module: haproxy
318 - name: local
319 - url: http://{{.Address}}/metrics
320 - - selector: "hddtemp"
321 - template: |
322 - module: hddtemp
323 - name: local
324 - address: {{.Address}}
325 - - selector: "hdfs_namenode"
326 - template: |
327 - module: hdfs
328 - name: namenode_local
329 - url: http://{{.Address}}/jmx
330 - - selector: "hdfs_datanode"
331 - template: |
332 - module: hdfs
333 - name: datanode_local
334 - url: http://{{.Address}}/jmx
335 - - selector: "icecast"
336 - template: |
337 - module: icecast
338 - name: local
339 - url: http://{{.Address}}
340 - - selector: "ipfs"
341 - template: |
342 - module: ipfs
343 - name: local
344 - url: http://{{.Address}}
345 - - selector: "kubelet"
346 - template: |
347 - module: k8s_kubelet
348 - name: local
349 - {{- if eq .Port "10255" }}
350 - url: http://{{.Address}}/metrics
351 - {{- else }}
352 - url: https://{{.Address}}/metrics
353 - tls_skip_verify: yes
354 - {{- end }}
355 - - selector: "kubeproxy"
356 - template: |
357 - module: k8s_kubeproxy
358 - name: local
359 - url: http://{{.Address}}/metrics
360 - - selector: "lighttpd"
361 - template: |
362 - module: lighttpd
363 - name: local
364 - url: http://{{.Address}}/server-status?auto
365 - - selector: "logstash"
366 - template: |
367 - module: logstash
368 - name: local
369 - url: http://{{.Address}}
370 - - selector: "maxscale"
371 - template: |
372 - module: maxscale
373 - name: local
374 - url: http://{{.Address}}
375 - - selector: "memcached"
376 - template: |
377 - module: memcached
378 - name: local
379 - address: {{.Address}}
380 - - selector: "mongodb"
381 - template: |
382 - module: mongodb
383 - name: local
384 - uri: mongodb://{{.Address}}
385 - - selector: "monit"
386 - template: |
387 - module: monit
388 - name: local
389 - url: http://{{.Address}}
390 - username: admin
391 - password: monit
392 - - selector: "mysql"
393 - template: |
394 - - module: mysql
395 - name: local
396 - dsn: netdata@unix(/var/run/mysqld/mysqld.sock)/
397 - - module: mysql
398 - name: local
399 - dsn: netdata@tcp({{.Address}})/
400 - - selector: "nats"
401 - template: |
402 - - module: nats
403 - name: local
404 - url: http://{{.Address}}
405 - - selector: "nginx"
406 - template: |
407 - - module: nginx
408 - name: local
409 - url: http://{{.Address}}/stub_status
410 - - module: nginx
411 - name: local
412 - url: http://{{.Address}}/basic_status
413 - - module: nginx
414 - name: local
415 - url: http://{{.Address}}/nginx_status
416 - - module: nginx
417 - name: local
418 - url: http://{{.Address}}/status
419 - - selector: "nginxunit"
420 - template: |
421 - - module: nginxunit
422 - name: local
423 - url: http://{{.Address}}
424 - - selector: "ntpd"
425 - template: |
426 - module: ntpd
427 - name: local
428 - address: {{.Address}}
429 - collect_peers: no
430 - - selector: "openldap"
431 - template: |
432 - module: openldap
433 - name: local
434 - url: ldap://{{.Address}}
435 - - selector: "openvpn"
436 - template: |
437 - module: openvpn
438 - name: local
439 - address: {{.Address}}
440 - - selector: "oracledb"
441 - template: |
442 - module: oracledb
443 - name: local
444 - {{ if eq .Port "1521" -}}
445 - dsn: 'oracle://username:password@{{.Address}}/XE'
446 - {{ else -}}
447 - dsn: 'oracle://username:password@{{.Address}}/XE?ssl=true&ssl verify=false'
448 - {{ end -}}
449 - - selector: "pgbouncer"
450 - template: |
451 - module: pgbouncer
452 - name: local
453 - dsn: postgres://netdata:postgres@{{.Address}}/pgbouncer
454 - - selector: "pihole"
455 - template: |
456 - module: pihole
457 - name: local
458 - url: http://{{.Address}}
459 - - selector: "pika"
460 - template: |
461 - module: pika
462 - name: local
463 - address: redis://@{{.IPAddress}}:{{.Port}}
464 - - selector: "rethinkdb"
465 - template: |
466 - module: rethinkdb
467 - name: local
468 - address: {{.Address}}
469 - - selector: "riak"
470 - template: |
471 - module: riakkv
472 - name: local
473 - url: http://{{.Address}}/stats
474 - - selector: "rspamd"
475 - template: |
476 - module: rspamd
477 - name: local
478 - url: http://{{.Address}}
479 - - selector: "postgres"
480 - template: |
481 - - module: postgres
482 - name: local
483 - dsn: 'host=/var/run/postgresql dbname=postgres user=postgres'
484 - - module: postgres
485 - name: local
486 - dsn: 'host=/var/run/postgresql dbname=postgres user=netdata'
487 - - module: postgres
488 - name: local
489 - dsn: postgresql://netdata@{{.Address}}/postgres
490 - - selector: "powerdns"
491 - template: |
492 - module: powerdns
493 - name: local
494 - url: http://{{.Address}}
495 - headers:
496 - X-API-KEY: secret
497 - - selector: "powerdns_recursor"
498 - template: |
499 - module: powerdns_recursor
500 - name: local
501 - url: http://{{.Address}}
502 - headers:
503 - X-API-KEY: secret
504 - - selector: "proxysql"
505 - template: |
506 - module: proxysql
507 - name: local
508 - dsn: stats:stats@tcp({{.Address}})/
509 - - selector: "puppet"
510 - template: |
511 - module: puppet
512 - name: local
513 - url: https://{{.Address}}
514 - tls_skip_verify: yes
515 - - selector: "rabbitmq"
516 - template: |
517 - module: rabbitmq
518 - name: local
519 - url: http://{{.Address}}
520 - username: guest
521 - password: guest
522 - collect_queues_metrics: no
523 - - selector: "redis"
524 - template: |
525 - module: redis
526 - name: local
527 - address: redis://@{{.Address}}
528 - - selector: "squid"
529 - template: |
530 - module: squid
531 - name: local
532 - url: http://{{.Address}}
533 - - selector: "spigotmc"
534 - template: |
535 - module: spigotmc
536 - name: local
537 - address: {{.Address}}
538 - - selector: "supervisord"
539 - template: |
540 - module: supervisord
541 - name: local
542 - url: http://{{.Address}}/RPC2
543 - - selector: "traefik"
544 - template: |
545 - module: traefik
546 - name: local
547 - url: http://{{.Address}}/metrics
548 - - selector: "typesense"
549 - template: |
550 - module: typesense
551 - name: local
552 - url: http://{{.Address}}
553 - api_key: {{ trimPrefix "--api-key=" (regexFind "--api-key=[^ ]+" .Cmdline) -}}
554 - - selector: "tomcat"
555 - template: |
556 - module: tomcat
557 - name: local
558 - url: http://{{.Address}}
559 - - selector: "tor"
560 - template: |
561 - module: tor
562 - name: local
563 - address: {{.Address}}
564 - - selector: "unbound"
565 - template: |
566 - module: unbound
567 - name: local
568 - address: {{.Address}}
569 - - selector: "upsd"
570 - template: |
571 - module: upsd
572 - name: local
573 - address: {{.Address}}
574 - - selector: "uwsgi"
575 - template: |
576 - module: uwsgi
577 - name: local
578 - address: {{.Address}}
579 - - selector: "vernemq"
580 - template: |
581 - module: vernemq
582 - name: local
583 - url: http://{{.Address}}/metrics
584 - - selector: "yugabytedb"
585 - template: |
586 - - module: yugabytedb
587 - {{ if eq .Port "7000" -}}
588 - name: local_master
589 - {{ else if eq .Port "9000" -}}
590 - name: local_tserver
591 - {{ else if eq .Port "12000" -}}
592 - name: local_ycql
593 - {{ else if eq .Port "13000" -}}
594 - name: local_ysql
595 - {{ else -}}
596 - name: local
597 - {{ end }}
598 - url: http://{{.Address}}/prometheus-metrics
599 - - selector: "zookeeper"
600 - template: |
601 - module: zookeeper
602 - name: local
603 - address: {{.Address}}
604 -
605 - - name: "Prometheus exporters generic"
606 - selector: "exporter"
607 - config:
608 - - selector: "exporter"
609 - template: |
610 - {{ $name := promPort .Port -}}
611 - {{ if empty $name -}}
612 - {{ $name = printf "%s_%s" .Comm .Port -}}
613 - {{ end -}}
614 - module: prometheus
615 - name: {{$name}}_local
616 - url: http://{{.Address}}/metrics
617 - {{ if eq $name "caddy" -}}
618 - expected_prefix: 'caddy_'
619 - {{ else if eq $name "openethereum" -}}
620 - expected_prefix: 'blockchaincache_'
621 - {{ else if eq $name "crowdsec" -}}
622 - expected_prefix: 'cs_'
623 - {{ else if eq $name "netbox" -}}
624 - expected_prefix: 'django_'
625 - {{ else if eq $name "traefik" -}}
626 - expected_prefix: 'traefik_'
627 - {{ else if eq $name "pushgateway" -}}
628 - expected_prefix: 'pushgateway_'
629 - selector:
630 - allow:
631 - - pushgateway_*
632 - {{ else if eq $name "wireguard_exporter" -}}
633 - expected_prefix: 'wireguard_exporter'
634 - {{ else if eq $name "clickhouse" -}}
635 - max_time_series: 3000
636 - {{ end -}}
10 +services:
11 + - id: "activemq"
12 + match: '{{ and (eq .Port "8161") (eq .Comm "activemq") }}'
13 + config_template: |
14 + module: activemq
15 + name: local
16 + url: http://{{.Address}}
17 + webadmin: admin
18 +
19 + - id: "apache"
20 + match: '{{ and (eq .Port "80" "8080") (eq .Comm "apache" "apache2" "httpd") }}'
21 + config_template: |
22 + module: apache
23 + name: local
24 + url: http://{{.Address}}/server-status?auto
25 +
26 + - id: "apcupsd"
27 + match: '{{ or (eq .Port "3551") (eq .Comm "apcupsd") }}'
28 + config_template: |
29 + module: apcupsd
30 + name: local_{{.Port}}
31 + address: {{.Address}}
32 +
33 + - id: "beanstalk"
34 + match: '{{ or (eq .Port "11300") (eq .Comm "beanstalkd") }}'
35 + config_template: |
36 + module: beanstalk
37 + name: local
38 + address: {{.Address}}
39 +
40 + - id: "bind"
41 + match: '{{ and (eq .Port "8653") (eq .Comm "bind" "named") }}'
42 + config_template: |
43 + module: bind
44 + name: local
45 + url: http://{{.Address}}/json/v1
46 +
47 + - id: "boinc"
48 + match: '{{ and (eq .Port "31416") (eq .Comm "boinc") }}'
49 + config_template: |
50 + module: boinc
51 + name: local
52 + address: {{.Address}}
53 +
54 + - id: "cassandra"
55 + match: '{{ and (eq .Port "7072") (glob .Cmdline "*cassandra*") }}'
56 + config_template: |
57 + module: cassandra
58 + name: local
59 + url: http://{{.Address}}/metrics
60 +
61 + - id: "ceph"
62 + match: '{{ and (eq .Port "8443") (eq .Comm "ceph-mgr") }}'
63 + config_template: |
64 + module: ceph
65 + name: local
66 + url: https://{{.Address}}
67 +
68 + - id: "chrony"
69 + match: '{{ and (eq .Port "323") (eq .Comm "chronyd") }}'
70 + config_template: |
71 + module: chrony
72 + name: local
73 + address: {{.Address}}
74 +
75 + - id: "clickhouse"
76 + match: '{{ and (eq .Port "8123") (eq .Comm "clickhouse-server") }}'
77 + config_template: |
78 + module: clickhouse
79 + name: local
80 + url: http://{{.Address}}
81 +
82 + - id: "cockroachdb"
83 + match: '{{ and (eq .Port "8080") (eq .Comm "cockroach") }}'
84 + config_template: |
85 + module: cockroachdb
86 + name: local
87 + url: http://{{.Address}}/_status/vars
88 +
89 + - id: "consul"
90 + match: '{{ and (eq .Port "8500") (eq .Comm "consul") }}'
91 + config_template: |
92 + module: consul
93 + name: local
94 + url: http://{{.Address}}
95 +
96 + - id: "coredns"
97 + match: '{{ and (eq .Port "9153") (eq .Comm "coredns") }}'
98 + config_template: |
99 + module: coredns
100 + name: local
101 + url: http://{{.Address}}/metrics
102 +
103 + - id: "couchbase"
104 + match: '{{ or (eq .Port "8091") (glob .Cmdline "*couchbase*") }}'
105 + config_template: |
106 + module: couchbase
107 + name: local
108 + url: http://{{.Address}}
109 +
110 + - id: "couchdb"
111 + match: '{{ or (eq .Port "5984") (glob .Cmdline "*couchdb*") }}'
112 + config_template: |
113 + module: couchdb
114 + name: local
115 + url: http://{{.Address}}
116 + node: '_local'
117 +
118 + - id: "dnsdist"
119 + match: '{{ and (eq .Port "8083") (eq .Comm "dnsdist") }}'
120 + config_template: |
121 + module: dnsdist
122 + name: local
123 + url: http://{{.Address}}
124 + headers:
125 + X-API-Key: 'dnsdist-api-key'
126 +
127 + - id: "dnsmasq"
128 + match: '{{ and (eq .Protocol "UDP") (eq .Port "53") (eq .Comm "dnsmasq") }}'
129 + config_template: |
130 + module: dnsmasq
131 + name: local
132 + protocol: udp
133 + address: {{.Address}}
134 +
135 + - id: "docker_engine"
136 + match: '{{ and (eq .Port "9323") (eq .Comm "dockerd") }}'
137 + config_template: |
138 + module: docker_engine
139 + name: local
140 + url: http://{{.Address}}/metrics
141 +
142 + - id: "dovecot"
143 + match: '{{ and (eq .Port "24242") (eq .Comm "dovecot") }}'
144 + config_template: |
145 + module: dovecot
146 + name: local
147 + address: {{.Address}}
148 +
149 + - id: "elasticsearch"
150 + match: '{{ or (eq .Port "9200") (glob .Cmdline "*elasticsearch*" "*opensearch*") }}'
151 + config_template: |
152 + module: elasticsearch
153 + name: local
154 + {{ if glob .Cmdline "*elastic*" -}}
155 + url: http://{{.Address}}
156 + {{ else -}}
157 + url: https://{{.Address}}
158 + tls_skip_verify: yes
159 + username: admin
160 + password: admin
161 + {{ end -}}
162 +
163 + - id: "envoy"
164 + match: '{{ and (eq .Port "9901") (eq .Comm "envoy") }}'
165 + config_template: |
166 + module: envoy
167 + name: local
168 + url: http://{{.Address}}/stats/prometheus
169 +
170 + - id: "fluentd"
171 + match: '{{ and (eq .Port "24220") (glob .Cmdline "*fluentd*") }}'
172 + config_template: |
173 + module: fluentd
174 + name: local
175 + url: http://{{.Address}}
176 +
177 + - id: "freeradius"
178 + match: '{{ and (eq .Port "18121") (eq .Comm "freeradius") }}'
179 + config_template: |
180 + module: freeradius
181 + name: local
182 + address: {{.IPAddress}}
183 + port: {{.Port}}
184 + secret: adminsecret
185 +
186 + - id: "gearman"
187 + match: '{{ or (eq .Port "4730") (eq .Comm "gearmand") }}'
188 + config_template: |
189 + module: gearman
190 + name: local
191 + address: {{.Address}}
192 +
193 + - id: "geth"
194 + match: '{{ and (eq .Port "6060") (eq .Comm "geth") }}'
195 + config_template: |
196 + module: geth
197 + name: local
198 + url: http://{{.Address}}/debug/metrics/prometheus
199 +
200 + - id: "haproxy"
201 + match: '{{ and (eq .Port "8404") (eq .Comm "haproxy") }}'
202 + config_template: |
203 + module: haproxy
204 + name: local
205 + url: http://{{.Address}}/metrics
206 +
207 + - id: "hddtemp"
208 + match: '{{ and (eq .Port "7634") (eq .Comm "hddtemp") }}'
209 + config_template: |
210 + module: hddtemp
211 + name: local
212 + address: {{.Address}}
213 +
214 + - id: "hdfs_namenode"
215 + match: '{{ and (eq .Port "9870") (eq .Comm "hadoop") }}'
216 + config_template: |
217 + module: hdfs
218 + name: namenode_local
219 + url: http://{{.Address}}/jmx
220 +
221 + - id: "hdfs_datanode"
222 + match: '{{ and (eq .Port "9864") (eq .Comm "hadoop") }}'
223 + config_template: |
224 + module: hdfs
225 + name: datanode_local
226 + url: http://{{.Address}}/jmx
227 +
228 + - id: "icecast"
229 + match: '{{ and (eq .Port "8000") (eq .Comm "icecast") }}'
230 + config_template: |
231 + module: icecast
232 + name: local
233 + url: http://{{.Address}}
234 +
235 + - id: "ipfs"
236 + match: '{{ and (eq .Port "5001") (eq .Comm "ipfs") }}'
237 + config_template: |
238 + module: ipfs
239 + name: local
240 + url: http://{{.Address}}
241 +
242 + - id: "kubelet"
243 + match: '{{ and (eq .Port "10250" "10255") (eq .Comm "kubelet") }}'
244 + config_template: |
245 + module: k8s_kubelet
246 + name: local
247 + {{- if eq .Port "10255" }}
248 + url: http://{{.Address}}/metrics
249 + {{- else }}
250 + url: https://{{.Address}}/metrics
251 + tls_skip_verify: yes
252 + {{- end }}
253 +
254 + - id: "kubeproxy"
255 + match: '{{ and (eq .Port "10249") (eq .Comm "kube-proxy") }}'
256 + config_template: |
257 + module: k8s_kubeproxy
258 + name: local
259 + url: http://{{.Address}}/metrics
260 +
261 + - id: "lighttpd"
262 + match: '{{ and (eq .Port "80" "8080") (eq .Comm "lighttpd") }}'
263 + config_template: |
264 + module: lighttpd
265 + name: local
266 + url: http://{{.Address}}/server-status?auto
267 +
268 + - id: "logstash"
269 + match: '{{ and (eq .Port "9600") (glob .Cmdline "*logstash*") }}'
270 + config_template: |
271 + module: logstash
272 + name: local
273 + url: http://{{.Address}}
274 +
275 + - id: "maxscale"
276 + match: '{{ or (eq .Port "8989") (eq .Comm "maxscale") }}'
277 + config_template: |
278 + module: maxscale
279 + name: local
280 + url: http://{{.Address}}
281 +
282 + - id: "memcached"
283 + match: '{{ or (eq .Port "11211") (eq .Comm "memcached") }}'
284 + config_template: |
285 + module: memcached
286 + name: local
287 + address: {{.Address}}
288 +
289 + - id: "mongodb"
290 + match: '{{ or (eq .Port "27017") (eq .Comm "mongod") }}'
291 + config_template: |
292 + module: mongodb
293 + name: local
294 + uri: mongodb://{{.Address}}
295 +
296 + - id: "monit"
297 + match: '{{ or (eq .Port "2812") (eq .Comm "monit") }}'
298 + config_template: |
299 + module: monit
300 + name: local
301 + url: http://{{.Address}}
302 + username: admin
303 + password: monit
304 +
305 + - id: "mysql"
306 + match: '{{ or (eq .Port "3306") (eq .Comm "mysqld" "mariadbd") }}'
307 + config_template: |
308 + - module: mysql
309 + name: local
310 + dsn: netdata@unix(/var/run/mysqld/mysqld.sock)/
311 + - module: mysql
312 + name: local
313 + dsn: netdata@tcp({{.Address}})/
314 +
315 + - id: "nats"
316 + match: '{{ and (eq .Port "8222") (eq .Comm "nats-server") }}'
317 + config_template: |
318 + - module: nats
319 + name: local
320 + url: http://{{.Address}}
321 +
322 + - id: "nginx"
323 + match: '{{ and (eq .Port "80" "8080") (eq .Comm "nginx") }}'
324 + config_template: |
325 + - module: nginx
326 + name: local
327 + url: http://{{.Address}}/stub_status
328 + - module: nginx
329 + name: local
330 + url: http://{{.Address}}/basic_status
331 + - module: nginx
332 + name: local
333 + url: http://{{.Address}}/nginx_status
334 + - module: nginx
335 + name: local
336 + url: http://{{.Address}}/status
337 +
338 + - id: "nginxunit"
339 + match: '{{ and (eq .Port "8000") (eq .Comm "unit") }}'
340 + config_template: |
341 + - module: nginxunit
342 + name: local
343 + url: http://{{.Address}}
344 +
345 + - id: "ntpd"
346 + match: '{{ or (eq .Port "123") (eq .Comm "ntpd") }}'
347 + config_template: |
348 + module: ntpd
349 + name: local
350 + address: {{.Address}}
351 + collect_peers: no
352 +
353 + - id: "openldap"
354 + match: '{{ eq .Comm "slapd" }}'
355 + config_template: |
356 + module: openldap
357 + name: local
358 + url: ldap://{{.Address}}
359 +
360 + - id: "openvpn"
361 + match: '{{ and (eq .Port "7505") (eq .Comm "openvpn") }}'
362 + config_template: |
363 + module: openvpn
364 + name: local
365 + address: {{.Address}}
366 +
367 + - id: "oracledb"
368 + match: '{{ and (eq .Port "1521" "2484") (eq .Comm "tnslsnr") }}'
369 + config_template: |
370 + module: oracledb
371 + name: local
372 + {{ if eq .Port "1521" -}}
373 + dsn: 'oracle://username:password@{{.Address}}/XE'
374 + {{ else -}}
375 + dsn: 'oracle://username:password@{{.Address}}/XE?ssl=true&ssl verify=false'
376 + {{ end -}}
377 +
378 + - id: "pgbouncer"
379 + match: '{{ or (eq .Port "6432") (eq .Comm "pgbouncer") }}'
380 + config_template: |
381 + module: pgbouncer
382 + name: local
383 + dsn: postgres://netdata:postgres@{{.Address}}/pgbouncer
384 +
385 + - id: "pihole"
386 + match: '{{ and (eq .Port "80") (eq .Comm "pihole-FTL") }}'
387 + config_template: |
388 + module: pihole
389 + name: local
390 + url: http://{{.Address}}
391 +
392 + - id: "pika"
393 + match: '{{ and (eq .Port "9221") (eq .Comm "pika") }}'
394 + config_template: |
395 + module: pika
396 + name: local
397 + address: redis://@{{.IPAddress}}:{{.Port}}
398 +
399 + - id: "postgres"
400 + match: '{{ or (eq .Port "5432") (eq .Comm "postgres") }}'
401 + config_template: |
402 + - module: postgres
403 + name: local
404 + dsn: 'host=/var/run/postgresql dbname=postgres user=postgres'
405 + - module: postgres
406 + name: local
407 + dsn: 'host=/var/run/postgresql dbname=postgres user=netdata'
408 + - module: postgres
409 + name: local
410 + dsn: postgresql://netdata@{{.Address}}/postgres
411 +
412 + - id: "powerdns"
413 + match: '{{ and (eq .Port "8081") (eq .Comm "pdns_server") }}'
414 + config_template: |
415 + module: powerdns
416 + name: local
417 + url: http://{{.Address}}
418 + headers:
419 + X-API-KEY: secret
420 +
421 + - id: "powerdns_recursor"
422 + match: '{{ and (eq .Port "8081") (eq .Comm "pdns_recursor") }}'
423 + config_template: |
424 + module: powerdns_recursor
425 + name: local
426 + url: http://{{.Address}}
427 + headers:
428 + X-API-KEY: secret
429 +
430 + - id: "proxysql"
431 + match: '{{ or (eq .Port "6032") (eq .Comm "proxysql") }}'
432 + config_template: |
433 + module: proxysql
434 + name: local
435 + dsn: stats:stats@tcp({{.Address}})/
436 +
437 + - id: "puppet"
438 + match: '{{ or (eq .Port "8140") (glob .Cmdline "*puppet-server*") }}'
439 + config_template: |
440 + module: puppet
441 + name: local
442 + url: https://{{.Address}}
443 + tls_skip_verify: yes
444 +
445 + - id: "rabbitmq"
446 + match: '{{ or (eq .Port "15672") (glob .Cmdline "*rabbitmq*") }}'
447 + config_template: |
448 + module: rabbitmq
449 + name: local
450 + url: http://{{.Address}}
451 + username: guest
452 + password: guest
453 + collect_queues_metrics: no
454 +
455 + - id: "redis"
456 + match: '{{ or (eq .Port "6379") (eq .Comm "redis-server") }}'
457 + config_template: |
458 + module: redis
459 + name: local
460 + address: redis://@{{.Address}}
461 +
462 + - id: "rethinkdb"
463 + match: '{{ and (eq .Port "28015") (eq .Comm "rethinkdb") }}'
464 + config_template: |
465 + module: rethinkdb
466 + name: local
467 + address: {{.Address}}
468 +
469 + - id: "riak"
470 + match: '{{ and (eq .Port "8098") (glob .Cmdline "*riak*") }}'
471 + config_template: |
472 + module: riakkv
473 + name: local
474 + url: http://{{.Address}}/stats
475 +
476 + - id: "rspamd"
477 + match: '{{ and (eq .Port "11334") (eq .Comm "rspamd") }}'
478 + config_template: |
479 + module: rspamd
480 + name: local
481 + url: http://{{.Address}}
482 +
483 + - id: "squid"
484 + match: '{{ and (eq .Port "3128") (eq .Comm "squid") }}'
485 + config_template: |
486 + module: squid
487 + name: local
488 + url: http://{{.Address}}
489 +
490 + - id: "spigotmc"
491 + match: '{{ and (eq .Port "25575") (glob .Cmdline "*spigot*") }}'
492 + config_template: |
493 + module: spigotmc
494 + name: local
495 + address: {{.Address}}
496 +
497 + - id: "supervisord"
498 + match: '{{ and (eq .Port "9001") (eq .Comm "supervisord") }}'
499 + config_template: |
500 + module: supervisord
501 + name: local
502 + url: http://{{.Address}}/RPC2
503 +
504 + - id: "tomcat"
505 + match: '{{ and (eq .Port "8080") (glob .Cmdline "*tomcat*") }}'
506 + config_template: |
507 + module: tomcat
508 + name: local
509 + url: http://{{.Address}}
510 +
511 + - id: "tor"
512 + match: '{{ and (eq .Port "9051") (eq .Comm "tor") }}'
513 + config_template: |
514 + module: tor
515 + name: local
516 + address: {{.Address}}
517 +
518 + - id: "traefik"
519 + match: '{{ and (eq .Port "80" "8080") (eq .Comm "traefik") }}'
520 + config_template: |
521 + module: traefik
522 + name: local
523 + url: http://{{.Address}}/metrics
524 +
525 + - id: "typesense"
526 + match: '{{ and (eq .Port "8108") (eq .Comm "typesense-server") }}'
527 + config_template: |
528 + module: typesense
529 + name: local
530 + url: http://{{.Address}}
531 + api_key: {{ trimPrefix "--api-key=" (regexFind "--api-key=[^ ]+" .Cmdline) -}}
532 +
533 + - id: "unbound"
534 + match: '{{ and (eq .Port "8953") (eq .Comm "unbound") }}'
535 + config_template: |
536 + module: unbound
537 + name: local
538 + address: {{.Address}}
539 +
540 + - id: "upsd"
541 + match: '{{ or (eq .Port "3493") (eq .Comm "upsd") }}'
542 + config_template: |
543 + module: upsd
544 + name: local
545 + address: {{.Address}}
546 +
547 + - id: "uwsgi"
548 + match: '{{ and (eq .Port "1717") (eq .Comm "uwsgi") }}'
549 + config_template: |
550 + module: uwsgi
551 + name: local
552 + address: {{.Address}}
553 +
554 + - id: "vernemq"
555 + match: '{{ and (eq .Port "8888") (glob .Cmdline "*vernemq*") }}'
556 + config_template: |
557 + module: vernemq
558 + name: local
559 + url: http://{{.Address}}/metrics
560 +
561 + - id: "yugabytedb"
562 + match: '{{ and (eq .Port "7000" "9000" "12000" "13000") (or (glob .Cmdline "*YSQL*") (eq .Comm "yb-master" "yb-tserver")) }}'
563 + config_template: |
564 + - module: yugabytedb
565 + {{ if eq .Port "7000" -}}
566 + name: local_master
567 + {{ else if eq .Port "9000" -}}
568 + name: local_tserver
569 + {{ else if eq .Port "12000" -}}
570 + name: local_ycql
571 + {{ else if eq .Port "13000" -}}
572 + name: local_ysql
573 + {{ else -}}
574 + name: local
575 + {{ end }}
576 + url: http://{{.Address}}/prometheus-metrics
577 +
578 + - id: "zookeeper"
579 + match: '{{ or (eq .Port "2181" "2182") (glob .Cmdline "*zookeeper*") }}'
580 + config_template: |
581 + module: zookeeper
582 + name: local
583 + address: {{.Address}}
584 +
585 + - id: "exporter"
586 + match: '{{ or (and (not (empty (promPort .Port))) (not (eq .Comm "docker-proxy"))) (glob .Comm "*exporter*") }}'
587 + config_template: |
588 + {{ $name := promPort .Port -}}
589 + {{ if empty $name -}}
590 + {{ $name = printf "%s_%s" .Comm .Port -}}
591 + {{ end -}}
592 + module: prometheus
593 + name: {{$name}}_local
594 + url: http://{{.Address}}/metrics
595 + {{ if eq $name "caddy" -}}
596 + expected_prefix: 'caddy_'
597 + {{ else if eq $name "openethereum" -}}
598 + expected_prefix: 'blockchaincache_'
599 + {{ else if eq $name "crowdsec" -}}
600 + expected_prefix: 'cs_'
601 + {{ else if eq $name "netbox" -}}
602 + expected_prefix: 'django_'
603 + {{ else if eq $name "traefik" -}}
604 + expected_prefix: 'traefik_'
605 + {{ else if eq $name "pushgateway" -}}
606 + expected_prefix: 'pushgateway_'
607 + selector:
608 + allow:
609 + - pushgateway_*
610 + {{ else if eq $name "wireguard_exporter" -}}
611 + expected_prefix: 'wireguard_exporter'
612 + {{ else if eq $name "clickhouse" -}}
613 + max_time_series: 3000
614 + {{ end -}}
src/go/plugin/go.d/config/go.d/sd/snmp.conf
+25 -35
@@ -58,38 +58,28 @@ discover:
58 ## Credential is the name of a credential from the Credentials list
59 credential: "public-v2c"
60
61 -classify:
62 - - name: "SNMP Devices"
63 - selector: "*"
64 - tags: "snmp"
65 - match:
66 - - tags: "snmp"
67 - expr: '{{ true }}'
68 -
69 -compose:
70 - - name: "SNMP Devices"
71 - selector: "snmp"
72 - config:
73 - - selector: "snmp"
74 - template: |
75 - module: snmp
76 - update_every: 5
77 - {{- if .SysInfo.Name }}
78 - name: {{ .SysInfo.Name }}-ip-{{ .IPAddress }}
79 - {{- else }}
80 - name: ip-{{ .IPAddress }}
81 - {{- end }}
82 - hostname: {{ .IPAddress }}
83 - options:
84 - version: {{ .Credential.Version }}
85 - {{- if eq .Credential.Version "1" "2" }}
86 - community: {{ .Credential.Community }}
87 - {{- else }}
88 - user:
89 - name: {{ .Credential.UserName }}
90 - level: {{ .Credential.SecurityLevel }}
91 - auth_proto: {{ .Credential.AuthProtocol }}
92 - auth_key: {{ .Credential.AuthPassphrase }}
93 - priv_proto: {{ .Credential.PrivacyProtocol }}
94 - priv_key: {{ .Credential.PrivacyPassphrase }}
95 - {{- end }}
61 +services:
62 + - id: "snmp"
63 + match: '{{ true }}'
64 + config_template: |
65 + module: snmp
66 + update_every: 5
67 + {{- if .SysInfo.Name }}
68 + name: {{ .SysInfo.Name }}-ip-{{ .IPAddress }}
69 + {{- else }}
70 + name: ip-{{ .IPAddress }}
71 + {{- end }}
72 + hostname: {{ .IPAddress }}
73 + options:
74 + version: {{ .Credential.Version }}
75 + {{- if eq .Credential.Version "1" "2" }}
76 + community: {{ .Credential.Community }}
77 + {{- else }}
78 + user:
79 + name: {{ .Credential.UserName }}
80 + level: {{ .Credential.SecurityLevel }}
81 + auth_proto: {{ .Credential.AuthProtocol }}
82 + auth_key: {{ .Credential.AuthPassphrase }}
83 + priv_proto: {{ .Credential.PrivacyProtocol }}
84 + priv_key: {{ .Credential.PrivacyPassphrase }}
85 + {{- end }}