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