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)