@cryptotaxi247 / netdata-1 / commits / a3e54253a

improvement(go.d/sd/snmp): support device cache ttl 0 (#19756)

* improvement(go.d/sd/snmp): support device cache ttl 0 * update config options description

Ilya Mashchenko committed Mar 3, 2025 at 20:59 UTC a3e54253a18c99ba79caa6a579c64ef2a75e24fb
3 files changed +18 -11
src/go/plugin/go.d/agent/discovery/sd/discoverer/snmpsd/discoverer.go
+14 -11
@@ -6,7 +6,6 @@ import (
6 "context"
7 "fmt"
8 "log/slog"
9 - "sync/atomic"
9 "time"
10
11 "github.com/gohugoio/hashstructure"
@@ -55,7 +54,7 @@ func NewDiscoverer(cfg Config) (*Discoverer, error) {
54 status: newDiscoveryStatus(),
55 }
56
58 - if cfg.RescanInterval > 0 {
57 + if cfg.RescanInterval >= 0 {
58 d.rescanInterval = cfg.RescanInterval.Duration()
59 }
60 if cfg.Timeout > 0 {
@@ -64,7 +63,7 @@ func NewDiscoverer(cfg Config) (*Discoverer, error) {
63 if cfg.ParallelScansPerNetwork > 0 {
64 d.parallelScansPerNetwork = cfg.ParallelScansPerNetwork
65 }
67 - if cfg.DeviceCacheTTL > 0 {
66 + if cfg.DeviceCacheTTL >= 0 {
67 d.deviceCacheTTL = cfg.DeviceCacheTTL.Duration()
68 }
69
@@ -90,7 +89,6 @@ type (
89
90 firstDiscovery bool
91 status *discoveryStatus
93 - statusUpdated atomic.Bool
92 }
93 subnet struct {
94 str string
@@ -148,7 +146,7 @@ func (d *Discoverer) discoverNetworks(ctx context.Context, in chan<- []model.Tar
146 d.status.LastDiscoveryTime = now
147 }
148
151 - if d.statusUpdated.Swap(false) || d.status.ConfigHash != d.cfgHash {
149 + if d.status.updated.Swap(false) || d.status.ConfigHash != d.cfgHash {
150 d.status.ConfigHash = d.cfgHash
151 filepersister.Save(statusFileName(), d.status)
152 }
@@ -199,11 +197,16 @@ func (d *Discoverer) probeIPAddress(ctx context.Context, sub subnet, ip string,
197 dev := d.status.get(sub, ip)
198
199 // Use the cached device if available and not expired
202 - if dev != nil && now.Before(dev.DiscoverTime.Add(d.deviceCacheTTL)) {
200 + if dev != nil && (d.deviceCacheTTL == 0 || now.Before(dev.DiscoverTime.Add(d.deviceCacheTTL))) {
201 if d.firstDiscovery {
204 - untilProbe := dev.DiscoverTime.Add(d.deviceCacheTTL).Sub(now).Round(time.Second)
205 - d.Infof("device '%s': found in cache (sysName: '%s', network: '%s', next probe in %s)",
206 - ip, dev.SysInfo.Name, subKey(sub), untilProbe)
202 + if d.deviceCacheTTL == 0 {
203 + d.Infof("device '%s': found in cache (sysName: '%s', network: '%s', cache never expires)",
204 + ip, dev.SysInfo.Name, subKey(sub))
205 + } else {
206 + untilProbe := dev.DiscoverTime.Add(d.deviceCacheTTL).Sub(now).Round(time.Second)
207 + d.Infof("device '%s': found in cache (sysName: '%s', network: '%s', next probe in %s)",
208 + ip, dev.SysInfo.Name, subKey(sub), untilProbe)
209 + }
210 }
211 tg := newTarget(ip, sub.credential, dev.SysInfo)
212 tgg.addTarget(tg)
@@ -221,13 +224,13 @@ func (d *Discoverer) probeIPAddress(ctx context.Context, sub subnet, ip string,
224 ip, dev.SysInfo.Name, subKey(sub), err)
225 }
226 d.status.del(sub, ip)
224 - d.statusUpdated.Store(dev != nil)
227 + d.status.updated.Store(dev != nil)
228 return
229 }
230
231 d.Infof("device '%s': successfully discovered (sysName: '%s', network: '%s')", ip, si.Name, subKey(sub))
232 d.status.put(sub, ip, &discoveredDevice{DiscoverTime: now, SysInfo: *si})
230 - d.statusUpdated.Store(true)
233 + d.status.updated.Store(true)
234 tg := newTarget(ip, sub.credential, *si)
235 tgg.addTarget(tg)
236 }
src/go/plugin/go.d/agent/discovery/sd/discoverer/snmpsd/status.go
+2
@@ -8,6 +8,7 @@ import (
8 "os"
9 "path/filepath"
10 "sync"
11 + "sync/atomic"
12 "time"
13 )
14
@@ -50,6 +51,7 @@ func newDiscoveryStatus() *discoveryStatus {
51
52 type (
53 discoveryStatus struct {
54 + updated atomic.Bool
55 mux sync.RWMutex
56 Networks map[string]map[string]*discoveredDevice `json:"networks"`
57 LastDiscoveryTime time.Time `json:"last_discovery_time"`
src/go/plugin/go.d/config/go.d/sd/snmp.conf
+2
@@ -12,12 +12,14 @@ discover:
12 - discoverer: snmp
13 snmp:
14 ## how often to scan the networks for devices (default: 30m)
15 + ## Set to 0 to perform a single discovery scan and exit
16 #rescan_interval: "30m"
17
18 ## the maximum time to wait for SNMP device responses (default: 1s)
19 #timeout: "1s"
20
21 ## How long to trust cached discovery results before requiring a new probe (default: 12h)
22 + ## Set to 0 to never expire cached results (devices will never be re-probed once discovered)
23 #device_cache_ttl: "12h"
24
25 ## how many IPs to scan concurrently within each subnet (default: 32)