Skip to content

Commit

Permalink
Allow resolver timeout parameter and faster startup times
Browse files Browse the repository at this point in the history
  • Loading branch information
syepes committed Apr 21, 2023
1 parent 9c878c2 commit 05de108
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 56 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@ The file `network_exporter.yml` can be either edited before building the docker
# Main Config
conf:
refresh: 15m
nameserver: 192.168.0.1:53
nameserver: 192.168.0.1:53 # Optional
nameserver_timeout: 250ms # Optional

# Specific Protocol settings
icmp:
Expand Down
38 changes: 25 additions & 13 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package config

import (
"fmt"
"net"
"os"
"regexp"
"strings"
Expand All @@ -11,6 +12,7 @@ import (
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/syepes/network_exporter/pkg/common"

yaml "gopkg.in/yaml.v3"
)

Expand All @@ -27,31 +29,32 @@ type Targets []struct {
}

type HTTPGet struct {
Interval duration `yaml:"interval" json:"interval"`
Timeout duration `yaml:"timeout" json:"timeout"`
Interval duration `yaml:"interval" json:"interval" default:"15s"`
Timeout duration `yaml:"timeout" json:"timeout" default:"14s"`
}

type TCP struct {
Interval duration `yaml:"interval" json:"interval"`
Timeout duration `yaml:"timeout" json:"timeout"`
Interval duration `yaml:"interval" json:"interval" default:"5s"`
Timeout duration `yaml:"timeout" json:"timeout" default:"4s"`
}

type MTR struct {
Interval duration `yaml:"interval" json:"interval"`
Timeout duration `yaml:"timeout" json:"timeout"`
MaxHops int `yaml:"max-hops" json:"max-hops"`
Count int `yaml:"count" json:"count"`
Interval duration `yaml:"interval" json:"interval" default:"5s"`
Timeout duration `yaml:"timeout" json:"timeout" default:"4s"`
MaxHops int `yaml:"max-hops" json:"max-hops" default:"30"`
Count int `yaml:"count" json:"count" default:"10"`
}

type ICMP struct {
Interval duration `yaml:"interval" json:"interval"`
Timeout duration `yaml:"timeout" json:"timeout"`
Count int `yaml:"count" json:"count"`
Interval duration `yaml:"interval" json:"interval" default:"5s"`
Timeout duration `yaml:"timeout" json:"timeout" default:"4s"`
Count int `yaml:"count" json:"count" default:"10"`
}

type Conf struct {
Refresh duration `yaml:"refresh" json:"refresh"`
Nameserver string `yaml:"nameserver" json:"nameserver"`
Refresh duration `yaml:"refresh" json:"refresh" default:"0s"`
Nameserver string `yaml:"nameserver" json:"nameserver"`
NameserverTimeout duration `yaml:"nameserver_timeout" json:"nameserver_timeout" default:"250ms"`
}

type Config struct {
Expand All @@ -74,6 +77,12 @@ func (b *extraKV) UnmarshalYAML(unmarshal func(interface{}) error) error {
return unmarshal(&b.Kv)
}

// SafeConfig Safe configuration reload
type Resolver struct {
Resolver *net.Resolver
Timeout time.Duration
}

// SafeConfig Safe configuration reload
type SafeConfig struct {
Cfg *Config
Expand Down Expand Up @@ -169,6 +178,9 @@ func (sc *SafeConfig) ReloadConfig(logger log.Logger, confFile string) (err erro
}

// Config precheck
if c.ICMP.Interval <= 0 || c.MTR.Interval <= 0 || c.TCP.Interval <= 0 || c.HTTPGet.Interval <= 0 {
return fmt.Errorf("intervals (icmp,mtr,tcp,http_get) must be >0")
}
if c.MTR.MaxHops < 0 || c.MTR.MaxHops > 65500 {
return fmt.Errorf("mtr.max-hops must be between 0 and 65500")
}
Expand Down
18 changes: 9 additions & 9 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (
"github.com/syepes/network_exporter/pkg/common"
)

const version string = "1.7.1"
const version string = "1.7.2"

var (
listenAddress = kingpin.Flag("web.listen-address", "The address to listen on for HTTP requests").Default(":9427").String()
Expand Down Expand Up @@ -66,16 +66,16 @@ func main() {
resolver := getResolver()

monitorPING = monitor.NewPing(logger, sc, resolver, icmpID)
monitorPING.AddTargets()
go monitorPING.AddTargets()

monitorMTR = monitor.NewMTR(logger, sc, resolver, icmpID)
monitorMTR.AddTargets()
go monitorMTR.AddTargets()

monitorTCP = monitor.NewTCPPort(logger, sc, resolver)
monitorTCP.AddTargets()
go monitorTCP.AddTargets()

monitorHTTPGet = monitor.NewHTTPGet(logger, sc, resolver)
monitorHTTPGet.AddTargets()
go monitorHTTPGet.AddTargets()

go startConfigRefresh()

Expand Down Expand Up @@ -142,18 +142,18 @@ func startServer() {
level.Error(logger).Log("msg", "Could not start http", "err", http.ListenAndServe(*listenAddress, mux))
}

func getResolver() *net.Resolver {
func getResolver() *config.Resolver {
if sc.Cfg.Conf.Nameserver == "" {
level.Info(logger).Log("msg", "Configured default DNS resolver")
return net.DefaultResolver
return &config.Resolver{Resolver: net.DefaultResolver, Timeout: sc.Cfg.Conf.NameserverTimeout.Duration()}
}

level.Info(logger).Log("msg", "Configured custom DNS resolver")
dialer := func(ctx context.Context, network, address string) (net.Conn, error) {
d := net.Dialer{Timeout: 3 * time.Second}
d := net.Dialer{Timeout: sc.Cfg.Conf.NameserverTimeout.Duration()}
return d.DialContext(ctx, "udp", sc.Cfg.Conf.Nameserver)
}
return &net.Resolver{PreferGo: true, Dial: dialer}
return &config.Resolver{Resolver: &net.Resolver{PreferGo: true, Dial: dialer}, Timeout: sc.Cfg.Conf.NameserverTimeout.Duration()}
}

func expVars(w http.ResponseWriter, r *http.Request) {
Expand Down
5 changes: 2 additions & 3 deletions monitor/monitor_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package monitor

import (
"fmt"
"net"
"net/url"
"sync"
"time"
Expand All @@ -19,15 +18,15 @@ import (
type HTTPGet struct {
logger log.Logger
sc *config.SafeConfig
resolver *net.Resolver
resolver *config.Resolver
interval time.Duration
timeout time.Duration
targets map[string]*target.HTTPGet
mtx sync.RWMutex
}

// NewHTTPGet creates and configures a new Monitoring HTTPGet instance
func NewHTTPGet(logger log.Logger, sc *config.SafeConfig, resolver *net.Resolver) *HTTPGet {
func NewHTTPGet(logger log.Logger, sc *config.SafeConfig, resolver *config.Resolver) *HTTPGet {
if logger == nil {
logger = log.NewNopLogger()
}
Expand Down
10 changes: 5 additions & 5 deletions monitor/monitor_mtr.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package monitor

import (
"context"
"fmt"
"net"
"sync"
"time"

Expand All @@ -18,7 +18,7 @@ import (
type MTR struct {
logger log.Logger
sc *config.SafeConfig
resolver *net.Resolver
resolver *config.Resolver
icmpID *common.IcmpID
interval time.Duration
timeout time.Duration
Expand All @@ -29,7 +29,7 @@ type MTR struct {
}

// NewMTR creates and configures a new Monitoring MTR instance
func NewMTR(logger log.Logger, sc *config.SafeConfig, resolver *net.Resolver, icmpID *common.IcmpID) *MTR {
func NewMTR(logger log.Logger, sc *config.SafeConfig, resolver *config.Resolver, icmpID *common.IcmpID) *MTR {
if logger == nil {
logger = log.NewNopLogger()
}
Expand Down Expand Up @@ -104,7 +104,7 @@ func (p *MTR) AddTargetDelayed(name string, host string, srcAddr string, labels
defer p.mtx.Unlock()

// Resolve hostnames
ipAddrs, err := common.DestAddrs(host, p.resolver)
ipAddrs, err := common.DestAddrs(context.Background(), host, p.resolver.Resolver, p.resolver.Timeout)
if err != nil || len(ipAddrs) == 0 {
return err
}
Expand Down Expand Up @@ -181,7 +181,7 @@ func (p *MTR) CheckActiveTargets() (err error) {
if target.Name != targetName {
continue
}
ipAddrs, err := common.DestAddrs(target.Host, p.resolver)
ipAddrs, err := common.DestAddrs(context.Background(), target.Host, p.resolver.Resolver, p.resolver.Timeout)
if err != nil || len(ipAddrs) == 0 {
return err
}
Expand Down
16 changes: 8 additions & 8 deletions monitor/monitor_ping.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package monitor

import (
"context"
"fmt"
"net"
"sync"
"time"

Expand All @@ -18,7 +18,7 @@ import (
type PING struct {
logger log.Logger
sc *config.SafeConfig
resolver *net.Resolver
resolver *config.Resolver
icmpID *common.IcmpID
interval time.Duration
timeout time.Duration
Expand All @@ -28,7 +28,7 @@ type PING struct {
}

// NewPing creates and configures a new Monitoring ICMP instance
func NewPing(logger log.Logger, sc *config.SafeConfig, resolver *net.Resolver, icmpID *common.IcmpID) *PING {
func NewPing(logger log.Logger, sc *config.SafeConfig, resolver *config.Resolver, icmpID *common.IcmpID) *PING {
if logger == nil {
logger = log.NewNopLogger()
}
Expand Down Expand Up @@ -66,7 +66,7 @@ func (p *PING) AddTargets() {
targetConfigTmp := []string{}
for _, v := range p.sc.Cfg.Targets {
if v.Type == "ICMP" || v.Type == "ICMP+MTR" {
ipAddrs, err := common.DestAddrs(v.Host, p.resolver)
ipAddrs, err := common.DestAddrs(context.Background(), v.Host, p.resolver.Resolver, p.resolver.Timeout)
if err != nil || len(ipAddrs) == 0 {
level.Warn(p.logger).Log("type", "ICMP", "func", "AddTargets", "msg", fmt.Sprintf("Skipping resolve target: %s", v.Host), "err", err)
}
Expand All @@ -82,7 +82,7 @@ func (p *PING) AddTargets() {
for _, targetName := range targetAdd {
for _, target := range p.sc.Cfg.Targets {
if target.Type == "ICMP" || target.Type == "ICMP+MTR" {
ipAddrs, err := common.DestAddrs(target.Host, p.resolver)
ipAddrs, err := common.DestAddrs(context.Background(), target.Host, p.resolver.Resolver, p.resolver.Timeout)
if err != nil || len(ipAddrs) == 0 {
level.Warn(p.logger).Log("type", "ICMP", "func", "AddTargets", "msg", fmt.Sprintf("Skipping resolve target: %s", target.Host), "err", err)
}
Expand Down Expand Up @@ -136,7 +136,7 @@ func (p *PING) DelTargets() {
targetConfigTmp := []string{}
for _, v := range p.sc.Cfg.Targets {
if v.Type == "ICMP" || v.Type == "ICMP+MTR" {
ipAddrs, err := common.DestAddrs(v.Host, p.resolver)
ipAddrs, err := common.DestAddrs(context.Background(), v.Host, p.resolver.Resolver, p.resolver.Timeout)
if err != nil || len(ipAddrs) == 0 {
level.Warn(p.logger).Log("type", "ICMP", "func", "DelTargets", "msg", fmt.Sprintf("Skipping resolve target: %s", v.Host), "err", err)
}
Expand Down Expand Up @@ -191,7 +191,7 @@ func (p *PING) CheckActiveTargets() (err error) {
if target.Name != targetName {
continue
}
ipAddrs, err := common.DestAddrs(target.Host, p.resolver)
ipAddrs, err := common.DestAddrs(context.Background(), target.Host, p.resolver.Resolver, p.resolver.Timeout)
if err != nil || len(ipAddrs) == 0 {
return err
}
Expand All @@ -207,7 +207,7 @@ func (p *PING) CheckActiveTargets() (err error) {

p.RemoveTarget(targetName + " " + targetIp)

ipAddrs, err := common.DestAddrs(target.Host, p.resolver)
ipAddrs, err := common.DestAddrs(context.Background(), target.Host, p.resolver.Resolver, p.resolver.Timeout)
if err != nil || len(ipAddrs) == 0 {
level.Warn(p.logger).Log("type", "ICMP", "func", "CheckActiveTargets", "msg", fmt.Sprintf("Skipping resolve target: %s", target.Host), "err", err)
}
Expand Down
16 changes: 8 additions & 8 deletions monitor/monitor_tcp.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package monitor

import (
"context"
"fmt"
"net"
"strings"
"sync"
"time"
Expand All @@ -19,15 +19,15 @@ import (
type TCPPort struct {
logger log.Logger
sc *config.SafeConfig
resolver *net.Resolver
resolver *config.Resolver
interval time.Duration
timeout time.Duration
targets map[string]*target.TCPPort
mtx sync.RWMutex
}

// NewTCPPort creates and configures a new Monitoring TCP instance
func NewTCPPort(logger log.Logger, sc *config.SafeConfig, resolver *net.Resolver) *TCPPort {
func NewTCPPort(logger log.Logger, sc *config.SafeConfig, resolver *config.Resolver) *TCPPort {
if logger == nil {
logger = log.NewNopLogger()
}
Expand Down Expand Up @@ -68,7 +68,7 @@ func (p *TCPPort) AddTargets() {
level.Warn(p.logger).Log("type", "TCP", "func", "AddTargets", "msg", fmt.Sprintf("Skipping target, could not identify host: %v (%v)", v.Host, v.Name))
continue
}
ipAddrs, err := common.DestAddrs(conn[0], p.resolver)
ipAddrs, err := common.DestAddrs(context.Background(), conn[0], p.resolver.Resolver, p.resolver.Timeout)
if err != nil || len(ipAddrs) == 0 {
level.Warn(p.logger).Log("type", "TCP", "func", "AddTargets", "msg", fmt.Sprintf("Skipping resolve target: %s", v.Host), "err", err)
}
Expand All @@ -89,7 +89,7 @@ func (p *TCPPort) AddTargets() {
level.Warn(p.logger).Log("type", "TCP", "func", "AddTargets", "msg", fmt.Sprintf("Skipping target, could not identify host: %v (%v)", target.Host, target.Name))
continue
}
ipAddrs, err := common.DestAddrs(conn[0], p.resolver)
ipAddrs, err := common.DestAddrs(context.Background(), conn[0], p.resolver.Resolver, p.resolver.Timeout)
if err != nil || len(ipAddrs) == 0 {
level.Warn(p.logger).Log("type", "TCP", "func", "AddTargets", "msg", fmt.Sprintf("Skipping resolve target: %s", target.Name), "err", err)
}
Expand All @@ -102,7 +102,7 @@ func (p *TCPPort) AddTargets() {
level.Warn(p.logger).Log("type", "TCP", "func", "AddTargets", "msg", fmt.Sprintf("Skipping target, could not identify host: %v (%v)", target.Host, target.Name))
continue
}
ipAddrs, err := common.DestAddrs(conn[0], p.resolver)
ipAddrs, err := common.DestAddrs(context.Background(), conn[0], p.resolver.Resolver, p.resolver.Timeout)
if err != nil || len(ipAddrs) == 0 {
level.Warn(p.logger).Log("type", "TCP", "func", "AddTargets", "msg", fmt.Sprintf("Skipping resolve target: %s", target.Host), "err", err)
}
Expand Down Expand Up @@ -158,7 +158,7 @@ func (p *TCPPort) DelTargets() {
level.Warn(p.logger).Log("type", "TCP", "func", "DelTargets", "msg", fmt.Sprintf("Skipping target, could not identify host: %v (%v)", v.Host, v.Name))
continue
}
ipAddrs, err := common.DestAddrs(conn[0], p.resolver)
ipAddrs, err := common.DestAddrs(context.Background(), conn[0], p.resolver.Resolver, p.resolver.Timeout)
if err != nil || len(ipAddrs) == 0 {
level.Warn(p.logger).Log("type", "TCP", "func", "DelTargets", "msg", fmt.Sprintf("Skipping resolve target: %s", v.Host), "err", err)
}
Expand Down Expand Up @@ -213,7 +213,7 @@ func (p *TCPPort) CheckActiveTargets() (err error) {
if target.Name != targetName {
continue
}
ipAddrs, err := common.DestAddrs(strings.Split(target.Host, ":")[0], p.resolver)
ipAddrs, err := common.DestAddrs(context.Background(), strings.Split(target.Host, ":")[0], p.resolver.Resolver, p.resolver.Timeout)
if err != nil || len(ipAddrs) == 0 {
return err
}
Expand Down
14 changes: 13 additions & 1 deletion network_exporter.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# sdsdsd
conf:
refresh: 15m
nameserver: 8.8.8.8:53
# nameserver: 8.8.8.8:53 # Optional
nameserver_timeout: 250ms # Optional

icmp:
interval: 3s
Expand Down Expand Up @@ -29,6 +30,9 @@ targets:
probe:
- hostname1
- hostname2
labels:
dc: home
rack: a1
- name: google-dns1
host: 8.8.8.8
type: ICMP
Expand All @@ -40,4 +44,12 @@ targets:
type: ICMP+MTR
- name: cloudflare-dns-https
host: 1.1.1.1:443
source_ip: 192.168.1.1
type: TCP
- name: download-file-64M
host: http://test-debit.free.fr/65536.rnd
type: HTTPGet
- name: download-file-64M-proxy
host: http://test-debit.free.fr/65536.rnd
type: HTTPGet
proxy: http://localhost:3128
Loading

0 comments on commit 05de108

Please sign in to comment.