feat(go.d/sd/nl): make timeout and interval configurable (#18847)
Ilya Mashchenko committed
Oct 22, 2024 at 18:11 UTC
732b56114527c7e48a6e54a96aeff95970c92e9a
2 files changed
+87
-51
src/go/plugin/go.d/agent/discovery/sd/discoverer/netlisteners/ll.go
new
+62
@@ -0,0 +1,62 @@
1
+// SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+package netlisteners
4
+
5
+import (
6
+ "context"
7
+ "fmt"
8
+ "os"
9
+ "os/exec"
10
+ "path/filepath"
11
+ "time"
12
+
13
+ "github.com/netdata/netdata/go/plugins/pkg/executable"
14
+)
15
+
16
+type localListeners interface {
17
+ discover(ctx context.Context) ([]byte, error)
18
+}
19
+
20
+func newLocalListeners(timeout time.Duration) localListeners {
21
+ dir := os.Getenv("NETDATA_PLUGINS_DIR")
22
+ if dir == "" {
23
+ dir = executable.Directory
24
+ }
25
+ if dir == "" {
26
+ dir, _ = os.Getwd()
27
+ }
28
+
29
+ return &localListenersExec{
30
+ binPath: filepath.Join(dir, "local-listeners"),
31
+ timeout: timeout,
32
+ }
33
+}
34
+
35
+type localListenersExec struct {
36
+ binPath string
37
+ timeout time.Duration
38
+}
39
+
40
+func (e *localListenersExec) discover(ctx context.Context) ([]byte, error) {
41
+ execCtx, cancel := context.WithTimeout(ctx, e.timeout)
42
+ defer cancel()
43
+
44
+ // TCPv4/6 and UPDv4 sockets in LISTEN state
45
+ // https://github.com/netdata/netdata/blob/master/src/collectors/utils/local_listeners.c
46
+ args := []string{
47
+ "no-udp6",
48
+ "no-local",
49
+ "no-inbound",
50
+ "no-outbound",
51
+ "no-namespaces",
52
+ }
53
+
54
+ cmd := exec.CommandContext(execCtx, e.binPath, args...)
55
+
56
+ bs, err := cmd.Output()
57
+ if err != nil {
58
+ return nil, fmt.Errorf("error on executing '%s': %v", cmd, err)
59
+ }
60
+
61
+ return bs, nil
62
+}
src/go/plugin/go.d/agent/discovery/sd/discoverer/netlisteners/netlisteners.go
+25
-51
@@ -10,8 +10,6 @@ import (
10
"fmt"
11
"log/slog"
12
"net"
13
- "os"
14
- "os/exec"
13
"path/filepath"
14
"sort"
15
"strconv"
@@ -19,8 +17,8 @@ import (
17
"time"
18
19
"github.com/netdata/netdata/go/plugins/logger"
22
- "github.com/netdata/netdata/go/plugins/pkg/executable"
20
"github.com/netdata/netdata/go/plugins/plugin/go.d/agent/discovery/sd/model"
21
+ "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/confopt"
22
23
"github.com/ilyam8/hashstructure"
24
)
@@ -30,18 +28,27 @@ var (
28
fullName = fmt.Sprintf("sd:%s", shortName)
29
)
30
31
+type Config struct {
32
+ Source string `yaml:"-"`
33
+ Tags string `yaml:"tags"`
34
+
35
+ Interval *confopt.Duration `yaml:"interval"`
36
+ Timeout confopt.Duration `yaml:"timeout"`
37
+}
38
+
39
func NewDiscoverer(cfg Config) (*Discoverer, error) {
40
tags, err := model.ParseTags(cfg.Tags)
41
if err != nil {
42
return nil, fmt.Errorf("parse tags: %v", err)
43
}
44
39
- dir := os.Getenv("NETDATA_PLUGINS_DIR")
40
- if dir == "" {
41
- dir = executable.Directory
45
+ interval := time.Minute * 2
46
+ if cfg.Interval != nil {
47
+ interval = cfg.Interval.Duration()
48
}
43
- if dir == "" {
44
- dir, _ = os.Getwd()
49
+ timeout := time.Second * 5
50
+ if cfg.Timeout.Duration() != 0 {
51
+ timeout = cfg.Timeout.Duration()
52
}
53
54
d := &Discoverer{
@@ -49,12 +56,10 @@ func NewDiscoverer(cfg Config) (*Discoverer, error) {
56
slog.String("component", "service discovery"),
57
slog.String("discoverer", shortName),
58
),
52
- cfgSource: cfg.Source,
53
- ll: &localListenersExec{
54
- binPath: filepath.Join(dir, "local-listeners"),
55
- timeout: time.Second * 5,
56
- },
57
- interval: time.Minute * 2,
59
+ cfgSource: cfg.Source,
60
+ ll: newLocalListeners(timeout),
61
+ interval: interval,
62
+ timeout: timeout,
63
expiryTime: time.Minute * 10,
64
cache: make(map[uint64]*cacheItem),
65
started: make(chan struct{}),
@@ -65,11 +70,6 @@ func NewDiscoverer(cfg Config) (*Discoverer, error) {
70
return d, nil
71
}
72
68
-type Config struct {
69
- Source string `yaml:"-"`
70
- Tags string `yaml:"tags"`
71
-}
72
-
73
type (
74
Discoverer struct {
75
*logger.Logger
@@ -78,6 +78,7 @@ type (
78
cfgSource string
79
80
interval time.Duration
81
+ timeout time.Duration
82
ll localListeners
83
84
expiryTime time.Duration
@@ -92,9 +93,6 @@ type (
93
lastSeenTime time.Time
94
tgt model.Target
95
}
95
- localListeners interface {
96
- discover(ctx context.Context) ([]byte, error)
97
- }
96
)
97
98
func (d *Discoverer) String() string {
@@ -103,6 +101,7 @@ func (d *Discoverer) String() string {
101
102
func (d *Discoverer) Discover(ctx context.Context, in chan<- []model.TargetGroup) {
103
d.Info("instance is started")
104
+ d.Debugf("used config: interval: %s, timeout: %s, cache expiration time: %s", d.interval, d.timeout, d.expiryTime)
105
defer func() { d.Info("instance is stopped") }()
106
107
close(d.started)
@@ -112,6 +111,10 @@ func (d *Discoverer) Discover(ctx context.Context, in chan<- []model.TargetGroup
111
return
112
}
113
114
+ if d.interval == 0 {
115
+ return
116
+ }
117
+
118
tk := time.NewTicker(d.interval)
119
defer tk.Stop()
120
@@ -295,35 +298,6 @@ func (d *Discoverer) parseLocalListeners(bs []byte) ([]model.Target, error) {
298
return tgts[:n], nil
299
}
300
298
-type localListenersExec struct {
299
- binPath string
300
- timeout time.Duration
301
-}
302
-
303
-func (e *localListenersExec) discover(ctx context.Context) ([]byte, error) {
304
- execCtx, cancel := context.WithTimeout(ctx, e.timeout)
305
- defer cancel()
306
-
307
- // TCPv4/6 and UPDv4 sockets in LISTEN state
308
- // https://github.com/netdata/netdata/blob/master/src/collectors/utils/local_listeners.c
309
- args := []string{
310
- "no-udp6",
311
- "no-local",
312
- "no-inbound",
313
- "no-outbound",
314
- "no-namespaces",
315
- }
316
-
317
- cmd := exec.CommandContext(execCtx, e.binPath, args...)
318
-
319
- bs, err := cmd.Output()
320
- if err != nil {
321
- return nil, fmt.Errorf("error on executing '%s': %v", cmd, err)
322
- }
323
-
324
- return bs, nil
325
-}
326
-
301
func extractComm(cmdLine string) string {
302
if i := strings.IndexByte(cmdLine, ' '); i != -1 {
303
cmdLine = cmdLine[:i]