github.com/netdata/go.d.plugin@v0.58.1/modules/ping/prober.go (about) 1 // SPDX-License-Identifier: GPL-3.0-or-later 2 3 package ping 4 5 import ( 6 "errors" 7 "fmt" 8 "net" 9 "time" 10 11 "github.com/netdata/go.d.plugin/logger" 12 13 probing "github.com/prometheus-community/pro-bing" 14 ) 15 16 func newPingProber(conf pingProberConfig, log *logger.Logger) prober { 17 var source string 18 if conf.iface != "" { 19 if addr, err := getInterfaceIPAddress(conf.iface); err != nil { 20 log.Warningf("error getting interface '%s' IP address: %v", conf.iface, err) 21 } else { 22 log.Infof("interface '%s' IP address '%s', will use it as the source", conf.iface, addr) 23 source = addr 24 } 25 } 26 27 return &pingProber{ 28 network: conf.network, 29 privileged: conf.privileged, 30 packets: conf.packets, 31 source: source, 32 interval: conf.interval, 33 deadline: conf.deadline, 34 Logger: log, 35 } 36 } 37 38 type pingProberConfig struct { 39 network string 40 privileged bool 41 packets int 42 iface string 43 interval time.Duration 44 deadline time.Duration 45 } 46 47 type pingProber struct { 48 *logger.Logger 49 50 network string 51 privileged bool 52 packets int 53 source string 54 interval time.Duration 55 deadline time.Duration 56 } 57 58 func (p *pingProber) ping(host string) (*probing.Statistics, error) { 59 pr := probing.New(host) 60 61 pr.SetNetwork(p.network) 62 63 if err := pr.Resolve(); err != nil { 64 return nil, fmt.Errorf("DNS lookup '%s' : %v", host, err) 65 } 66 67 pr.Source = p.source 68 pr.RecordRtts = false 69 pr.Interval = p.interval 70 pr.Count = p.packets 71 pr.Timeout = p.deadline 72 pr.SetPrivileged(p.privileged) 73 pr.SetLogger(nil) 74 75 if err := pr.Run(); err != nil { 76 return nil, fmt.Errorf("pinging host '%s' (ip %s): %v", pr.Addr(), pr.IPAddr(), err) 77 } 78 79 stats := pr.Statistics() 80 81 p.Debugf("ping stats for host '%s' (ip '%s'): %+v", pr.Addr(), pr.IPAddr(), stats) 82 83 return stats, nil 84 } 85 86 func getInterfaceIPAddress(ifaceName string) (ipaddr string, err error) { 87 iface, err := net.InterfaceByName(ifaceName) 88 if err != nil { 89 return "", err 90 } 91 92 addresses, err := iface.Addrs() 93 if err != nil { 94 return "", err 95 } 96 97 // FIXME: add IPv6 support 98 var v4Addr string 99 for _, addr := range addresses { 100 if ipnet, ok := addr.(*net.IPNet); ok && ipnet.IP.To4() != nil { 101 v4Addr = ipnet.IP.To4().String() 102 break 103 } 104 } 105 106 if v4Addr == "" { 107 return "", errors.New("ipv4 addresses not found") 108 } 109 110 return v4Addr, nil 111 }