@cryptotaxi247 / netdata-1 / commits / 65cd61cc9

dns_query_time plugin: added

Ilya committed Mar 26, 2017 at 03:51 UTC 65cd61cc91763c1d95c2c2d2701c1f7be49a3a4c
1 file changed +129
python.d/dns_query_time.chart.py new
+129
@@ -0,0 +1,129 @@
1 +try:
2 + from time import monotonic as time
3 +except ImportError:
4 + from time import time
5 +try:
6 + import dns.message, dns.query, dns.name
7 + DNS_PYTHON = True
8 +except ImportError:
9 + DNS_PYTHON = False
10 +try:
11 + from queue import Queue
12 +except ImportError:
13 + from Queue import Queue
14 +from random import choice
15 +from threading import Thread
16 +from socket import gethostbyname, gaierror
17 +from base import SimpleService
18 +
19 +
20 +# default module values (can be overridden per job in `config`)
21 +update_every = 5
22 +priority = 60000
23 +retries = 60
24 +
25 +
26 +class Service(SimpleService):
27 + def __init__(self, configuration=None, name=None):
28 + SimpleService.__init__(self, configuration=configuration, name=name)
29 + self.order = list()
30 + self.definitions = dict()
31 + self.timeout = self.configuration.get('response_timeout', 4)
32 + self.aggregate = self.configuration.get('aggregate', True)
33 + self.domains = self.configuration.get('domains')
34 + self.server_list = self.configuration.get('dns_servers')
35 +
36 + def check(self):
37 + if not DNS_PYTHON:
38 + self.error('\'python-dnspython\' package is needed to use dns_query_time.chart.py')
39 + return False
40 +
41 + self.timeout = self.timeout if isinstance(self.timeout, int) else 4
42 + self.update_every = self.timeout + 1 if self.update_every <= self.timeout else self.update_every
43 +
44 + if not all([self.domains, self.server_list,
45 + isinstance(self.server_list, str), isinstance(self.domains, str)]):
46 + self.error('server_list and domain_list can\'t be empty')
47 + return False
48 + else:
49 + self.domains, self.server_list = self.domains.split(), self.server_list.split()
50 +
51 + for ns in self.server_list:
52 + if not check_ns(ns):
53 + self.info('Bad NS: %s' % ns)
54 + self.server_list.remove(ns)
55 + if not self.server_list:
56 + return False
57 +
58 + data = self._get_data(timeout=1)
59 +
60 + down_servers = [s[2:] for s in data if data[s] == -100]
61 + if down_servers:
62 + self.info('Removed due to non response %s' % down_servers)
63 + self.server_list = [s for s in self.server_list if s not in down_servers]
64 + if self.server_list:
65 + self._data_from_check = data
66 + self.order, self.definitions = create_charts(aggregate=self.aggregate, server_list=self.server_list)
67 + self.info(str({'domains': len(self.domains), 'servers': self.server_list}))
68 + return True
69 + else:
70 + return False
71 +
72 + def _get_data(self, timeout=None):
73 + return dns_request(self.server_list, timeout or self.timeout, self.domains)
74 +
75 +
76 +def dns_request(server_list, timeout, domains):
77 + threads = list()
78 + que = Queue()
79 + result = dict()
80 +
81 + def dns_req(ns, t, q):
82 + domain = dns.name.from_text(choice(domains))
83 + request = dns.message.make_query(domain, dns.rdatatype.A)
84 +
85 + try:
86 + dns_start = time()
87 + dns.query.udp(request, ns, timeout=t)
88 + dns_end = time()
89 + query_time = round((dns_end - dns_start) * 1000)
90 + q.put({''.join(['ns', ns]): query_time})
91 + except dns.exception.Timeout:
92 + q.put({''.join(['ns', ns]): -100})
93 +
94 + for server in server_list:
95 + th = Thread(target=dns_req, args=(server, timeout, que))
96 + th.start()
97 + threads.append(th)
98 +
99 + for th in threads:
100 + th.join()
101 + result.update(que.get())
102 +
103 + return result
104 +
105 +
106 +def check_ns(ns):
107 + try:
108 + return gethostbyname(ns)
109 + except gaierror:
110 + return False
111 +
112 +
113 +def create_charts(aggregate, server_list):
114 + if aggregate:
115 + order = ['dns_group']
116 + definitions = {'dns_group': {'options': [None, "DNS Response Time", "ms", 'name servers',
117 + 'resp.time', 'line'], 'lines': []}}
118 + for ns in server_list:
119 + definitions['dns_group']['lines'].append([''.join(['ns', ns]), ns, 'absolute'])
120 +
121 + return order, definitions
122 + else:
123 + order = [''.join(['dns_', ns]) for ns in server_list]
124 + definitions = dict()
125 + for ns in server_list:
126 + definitions[''.join(['dns_', ns])] = {'options': [None, "DNS Response Time", "ms", ns,
127 + 'resp.time', 'area'],
128 + 'lines': [[''.join(['ns', ns]), ns, 'absolute']]}
129 + return order, definitions