Skip to content

Commit

Permalink
Fix edge cases if big files are created and truncated.
Browse files Browse the repository at this point in the history
Improve speedup time by doing the intial DNS resolution also in parallel.
  • Loading branch information
hikhvar committed Mar 26, 2024
1 parent 64b4119 commit bafcfc1
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 17 deletions.
56 changes: 39 additions & 17 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"net/http"
"os"
"strings"
"sync"
"time"

"github.com/digineo/go-ping"
Expand Down Expand Up @@ -172,29 +173,38 @@ func startMonitor(cfg *config.Config) (*mon.Monitor, error) {
func upsertTargets(globalTargets *targets, resolver *net.Resolver, cfg *config.Config, monitor *mon.Monitor) error {
oldTargets := globalTargets.Targets()
newTargets := make([]*target, len(cfg.Targets))
var wg sync.WaitGroup
for i, t := range cfg.Targets {
t := &target{
host: t.Addr,
addresses: make([]net.IPAddr, 0),
delay: time.Duration(10*i) * time.Millisecond,
resolver: resolver,
}
newTargets[i] = t

err := t.addOrUpdateMonitor(monitor, targetOpts{
disableIPv4: cfg.Options.DisableIPv4,
disableIPv6: cfg.Options.DisableIPv6,
})
if err != nil {
return fmt.Errorf("failed to setup target: %w", err)
newTarget := globalTargets.Get(t.Addr)
if newTarget == nil {
newTarget = &target{
host: t.Addr,
addresses: make([]net.IPAddr, 0),
delay: time.Duration(10*i) * time.Millisecond,
resolver: resolver,
}
}
}

newTargets[i] = newTarget

wg.Add(1)
go func() {
err := newTarget.addOrUpdateMonitor(monitor, targetOpts{
disableIPv4: cfg.Options.DisableIPv4,
disableIPv6: cfg.Options.DisableIPv6,
})
if err != nil {
log.Errorf("failed to setup target: %w", err)

Check failure on line 197 in main.go

View workflow job for this annotation

GitHub Actions / test (1.22.x, ubuntu-latest)

github.com/sirupsen/logrus.Errorf does not support error-wrapping directive %w
}
wg.Done()
}()
}
wg.Wait()
globalTargets.SetTargets(newTargets)

removed := removedTargets(oldTargets, globalTargets)
for _, removedTarget := range removed {
log.Infof("remove target: %s\n", removedTarget.host)
log.Infof("remove target: %s", removedTarget.host)
removedTarget.removeFromMonitor(monitor)
}
return nil
Expand All @@ -212,12 +222,24 @@ func watchConfig(globalTargets *targets, resolver *net.Resolver, monitor *mon.Mo
}
for {
select {
case <-watcher.Events:
case event := <-watcher.Events:
log.Debugf("Got file inotify event: %s", event)
// If the file is removed, the inotify watcher will lose track of the file. Add it again.
if event.Op == inotify.Remove {
if err = watcher.Add(*configFile); err != nil {
log.Fatalf("failed to renew watch for file: %v", err)
}
}
cfg, err := loadConfig()
if err != nil {
log.Errorf("unable to load config: %v", err)
continue
}
// We get zero targets if the file was truncated. This happens if an automation tool rewrites
// the complete file, instead of alternating only parts of it.
if len(cfg.Targets) == 0 {
continue
}
log.Infof("reloading config file %s", *configFile)
if err := upsertTargets(globalTargets, resolver, cfg, monitor); err != nil {
log.Errorf("failed to reload config: %v", err)
Expand Down
13 changes: 13 additions & 0 deletions target.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ func (t *targets) SetTargets(tar []*target) {
}

func (t *targets) Contains(tar *target) bool {
t.mutex.RLock()
defer t.mutex.RUnlock()
for _, ta := range t.t {
if ta.host == tar.host {
return true
Expand All @@ -45,6 +47,17 @@ func (t *targets) Contains(tar *target) bool {
return false
}

func (t *targets) Get(host string) *target {
t.mutex.RLock()
defer t.mutex.RUnlock()
for _, ta := range t.t {
if ta.host == host {
return ta
}
}
return nil
}

func (t *targets) Targets() []*target {
t.mutex.RLock()
defer t.mutex.RUnlock()
Expand Down

0 comments on commit bafcfc1

Please sign in to comment.