github.com/netdata/go.d.plugin@v0.58.1/modules/dnsquery/collect.go (about)

     1  // SPDX-License-Identifier: GPL-3.0-or-later
     2  
     3  package dnsquery
     4  
     5  import (
     6  	"math/rand"
     7  	"net"
     8  	"strconv"
     9  	"sync"
    10  	"time"
    11  
    12  	"github.com/miekg/dns"
    13  )
    14  
    15  func (d *DNSQuery) collect() (map[string]int64, error) {
    16  	if d.dnsClient == nil {
    17  		d.dnsClient = d.newDNSClient(d.Network, d.Timeout.Duration)
    18  	}
    19  
    20  	mx := make(map[string]int64)
    21  	domain := randomDomain(d.Domains)
    22  	d.Debugf("current domain : %s", domain)
    23  
    24  	var wg sync.WaitGroup
    25  	var mux sync.RWMutex
    26  	for _, srv := range d.Servers {
    27  		for rtypeName, rtype := range d.recordTypes {
    28  			wg.Add(1)
    29  			go func(srv, rtypeName string, rtype uint16, wg *sync.WaitGroup) {
    30  				defer wg.Done()
    31  
    32  				msg := new(dns.Msg)
    33  				msg.SetQuestion(dns.Fqdn(domain), rtype)
    34  				address := net.JoinHostPort(srv, strconv.Itoa(d.Port))
    35  
    36  				resp, rtt, err := d.dnsClient.Exchange(msg, address)
    37  
    38  				mux.Lock()
    39  				defer mux.Unlock()
    40  
    41  				px := "server_" + srv + "_record_" + rtypeName + "_"
    42  
    43  				mx[px+"query_status_success"] = 0
    44  				mx[px+"query_status_network_error"] = 0
    45  				mx[px+"query_status_dns_error"] = 0
    46  
    47  				if err != nil {
    48  					d.Debugf("error on querying %s after %s query for %s : %s", srv, rtypeName, domain, err)
    49  					mx[px+"query_status_network_error"] = 1
    50  					return
    51  				}
    52  
    53  				if resp != nil && resp.Rcode != dns.RcodeSuccess {
    54  					d.Debugf("invalid answer from %s after %s query for %s (rcode %d)", srv, rtypeName, domain, resp.Rcode)
    55  					mx[px+"query_status_dns_error"] = 1
    56  				} else {
    57  					mx[px+"query_status_success"] = 1
    58  				}
    59  				mx["server_"+srv+"_record_"+rtypeName+"_query_time"] = rtt.Nanoseconds()
    60  
    61  			}(srv, rtypeName, rtype, &wg)
    62  		}
    63  	}
    64  	wg.Wait()
    65  
    66  	return mx, nil
    67  }
    68  
    69  func randomDomain(domains []string) string {
    70  	src := rand.NewSource(time.Now().UnixNano())
    71  	r := rand.New(src)
    72  	return domains[r.Intn(len(domains))]
    73  }