Multiple fixes:
* Improved readability regarding cahrt information generation. * Updated chart ordering to make it consistent between global and per-thread charts. * Updated dimension and family names to not have spaces and use all lowercase. * Changed to using a local copy of STAT_MAP to allow things to work with multiple jobs correctly.
Austin S. Hemmelgarn committed
Jun 7, 2018 at 11:20 UTC
d2e64e6dc0a91d8b2e695a99a3ac842cd87db4ae
1 file changed
+91
-78
python.d/unbound.chart.py
+91
-78
@@ -12,36 +12,36 @@ from bases.loaders import YamlOrderedLoader
12
13
PRECISION = 1000
14
15
-ORDER = ['queries', 'reqlist', 'recursion']
15
+ORDER = ['queries', 'recursion', 'reqlist']
16
17
CHARTS = {
18
'queries': {
19
'options': [None, 'Queries Processed', 'queries', 'Unbound', 'unbound.queries', 'line'],
20
'lines': [
21
- ['ratelimit', 'Ratelimited', 'absolute', 1, 1],
22
- ['cachemiss', 'Cache Miss', 'absolute', 1, 1],
23
- ['cachehit', 'Cache Hit', 'absolute', 1, 1],
24
- ['expired', 'Expired', 'absolute', 1, 1],
25
- ['prefetch', 'Prefetched', 'absolute', 1, 1],
26
- ['recursive', 'Recursive', 'absolute', 1, 1]
21
+ ['ratelimit', 'ratelimited', 'absolute', 1, 1],
22
+ ['cachemiss', 'cache_miss', 'absolute', 1, 1],
23
+ ['cachehit', 'cache_hit', 'absolute', 1, 1],
24
+ ['expired', 'expired', 'absolute', 1, 1],
25
+ ['prefetch', 'prefetched', 'absolute', 1, 1],
26
+ ['recursive', 'recursive', 'absolute', 1, 1]
27
]
28
},
29
- 'reqlist': {
30
- 'options': [None, 'Request List', 'items', 'Unbound', 'unbound.reqlist', 'line'],
29
+ 'recursion': {
30
+ 'options': [None, 'Recursion Timings', 'seconds', 'Unbound', 'unbound.recursion', 'line'],
31
'lines': [
32
- ['reqlist_avg', 'Average Size', 'absolute', 1, 1],
33
- ['reqlist_max', 'Maximum Size', 'absolute', 1, 1],
34
- ['reqlist_overwritten', 'Overwritten Requests', 'absolute', 1, 1],
35
- ['reqlist_exceeded', 'Overruns', 'absolute', 1, 1],
36
- ['reqlist_current', 'Current Size', 'absolute', 1, 1],
37
- ['reqlist_user', 'User Requests', 'absolute', 1, 1]
32
+ ['recursive_avg', 'average', 'absolute', 1, PRECISION],
33
+ ['recursive_med', 'median', 'absolute', 1, PRECISION]
34
]
35
},
40
- 'recursion': {
41
- 'options': [None, 'Recursion Timings', 'seconds', 'Unbound', 'unbound.recursion', 'line'],
36
+ 'reqlist': {
37
+ 'options': [None, 'Request List', 'items', 'Unbound', 'unbound.reqlist', 'line'],
38
'lines': [
43
- ['recursive_avg', 'Average', 'absolute', 1, PRECISION],
44
- ['recursive_med', 'Median', 'absolute', 1, PRECISION]
39
+ ['reqlist_avg', 'average_size', 'absolute', 1, 1],
40
+ ['reqlist_max', 'maximum_size', 'absolute', 1, 1],
41
+ ['reqlist_overwritten', 'overwritten_requests', 'absolute', 1, 1],
42
+ ['reqlist_exceeded', 'overruns', 'absolute', 1, 1],
43
+ ['reqlist_current', 'current_size', 'absolute', 1, 1],
44
+ ['reqlist_user', 'user_requests', 'absolute', 1, 1]
45
]
46
}
47
}
@@ -53,12 +53,12 @@ EXTENDED_CHARTS = {
53
'cache': {
54
'options': [None, 'Cache Sizes', 'items', 'Unbound', 'unbound.cache', 'stacked'],
55
'lines': [
56
- ['cache_message', 'Message Cache', 'absolute', 1, 1],
57
- ['cache_rrset', 'RRSet Cache', 'absolute', 1, 1],
58
- ['cache_infra', 'Infra Cache', 'absolute', 1, 1],
59
- ['cache_key', 'DNSSEC Key Cache', 'absolute', 1, 1],
60
- ['cache_dnscss', 'DNSCrypt Shared Secret Cache', 'absolute', 1, 1],
61
- ['cache_dnscn', 'DNSCrypt Nonce Cache', 'absolute', 1, 1]
56
+ ['cache_message', 'message_cache', 'absolute', 1, 1],
57
+ ['cache_rrset', 'rrset_cache', 'absolute', 1, 1],
58
+ ['cache_infra', 'infra_cache', 'absolute', 1, 1],
59
+ ['cache_key', 'dnssec_key_cache', 'absolute', 1, 1],
60
+ ['cache_dnscss', 'dnscrypt_Shared_Secret_cache', 'absolute', 1, 1],
61
+ ['cache_dnscn', 'dnscrypt_Nonce_cache', 'absolute', 1, 1]
62
]
63
}
64
}
@@ -66,32 +66,32 @@ EXTENDED_CHARTS = {
66
# This is used as a templates for the per-thread charts.
67
PER_THREAD_CHARTS = {
68
'_queries': {
69
- 'options': [None, '{0} Queries Processed', 'queries', 'Queries Processed', 'unbound.threads.queries', 'line'],
69
+ 'options': [None, '{longname} Queries Processed', 'queries', 'Queries Processed', 'unbound.threads.queries', 'line'],
70
'lines': [
71
- ['{0}_ratelimit', 'Ratelimited', 'absolute', 1, 1],
72
- ['{0}_cachemiss', 'Cache Miss', 'absolute', 1, 1],
73
- ['{0}_cachehit', 'Cache Hit', 'absolute', 1, 1],
74
- ['{0}_expired', 'Expired', 'absolute', 1, 1],
75
- ['{0}_prefetch', 'Prefetched', 'absolute', 1, 1],
76
- ['{0}_recursive', 'Recursive', 'absolute', 1, 1]
71
+ ['{shortname}_ratelimit', 'ratelimited', 'absolute', 1, 1],
72
+ ['{shortname}_cachemiss', 'cache_miss', 'absolute', 1, 1],
73
+ ['{shortname}_cachehit', 'cache_hit', 'absolute', 1, 1],
74
+ ['{shortname}_expired', 'expired', 'absolute', 1, 1],
75
+ ['{shortname}_prefetch', 'prefetched', 'absolute', 1, 1],
76
+ ['{shortname}_recursive', 'recursive', 'absolute', 1, 1]
77
]
78
},
79
- '_reqlist': {
80
- 'options': [None, '{0} Request List', 'items', 'Request List', 'unbound.threads.reqlist', 'line'],
79
+ '_recursion': {
80
+ 'options': [None, '{longname} Recursion Timings', 'seconds', 'Recursive Timings', 'unbound.threads.recursion', 'line'],
81
'lines': [
82
- ['{0}_reqlist_avg', 'Average Size', 'absolute', 1, 1],
83
- ['{0}_reqlist_max', 'Maximum Size', 'absolute', 1, 1],
84
- ['{0}_reqlist_overwritten', 'Overwritten Requests', 'absolute', 1, 1],
85
- ['{0}_reqlist_exceeded', 'Overruns', 'absolute', 1, 1],
86
- ['{0}_reqlist_current', 'Current Size', 'absolute', 1, 1],
87
- ['{0}_reqlist_user', 'User Requests', 'absolute', 1, 1]
82
+ ['{shortname}_recursive_avg', 'average', 'absolute', 1, PRECISION],
83
+ ['{shortname}_recursive_med', 'median', 'absolute', 1, PRECISION]
84
]
85
},
90
- '_recursion': {
91
- 'options': [None, '{0} Recursion Timings', 'seconds', 'Recursive Timings', 'unbound.threads.recursion', 'line'],
86
+ '_reqlist': {
87
+ 'options': [None, '{longname} Request List', 'items', 'Request List', 'unbound.threads.reqlist', 'line'],
88
'lines': [
93
- ['{0}_recursive_avg', 'Average', 'absolute', 1, PRECISION],
94
- ['{0}_recursive_med', 'Median', 'absolute', 1, PRECISION]
89
+ ['{shortname}_reqlist_avg', 'average_size', 'absolute', 1, 1],
90
+ ['{shortname}_reqlist_max', 'maximum_size', 'absolute', 1, 1],
91
+ ['{shortname}_reqlist_overwritten', 'overwritten_requests', 'absolute', 1, 1],
92
+ ['{shortname}_reqlist_exceeded', 'overruns', 'absolute', 1, 1],
93
+ ['{shortname}_reqlist_current', 'current_size', 'absolute', 1, 1],
94
+ ['{shortname}_reqlist_user', 'user_requests', 'absolute', 1, 1]
95
]
96
}
97
}
@@ -123,23 +123,48 @@ STAT_MAP = {
123
124
# Same as above, but for per-thread stats.
125
PER_THREAD_STAT_MAP = {
126
- '{0}.num.queries_ip_ratelimited': ('{0}_ratelimit', 1),
127
- '{0}.num.cachehits': ('{0}_cachehit', 1),
128
- '{0}.num.cachemiss': ('{0}_cachemiss', 1),
129
- '{0}.num.zero_ttl': ('{0}_expired', 1),
130
- '{0}.num.prefetch': ('{0}_prefetch', 1),
131
- '{0}.num.recursivereplies': ('{0}_recursive', 1),
132
- '{0}.requestlist.avg': ('{0}_reqlist_avg', 1),
133
- '{0}.requestlist.max': ('{0}_reqlist_max', 1),
134
- '{0}.requestlist.overwritten': ('{0}_reqlist_overwritten', 1),
135
- '{0}.requestlist.exceeded': ('{0}_reqlist_exceeded', 1),
136
- '{0}.requestlist.current.all': ('{0}_reqlist_current', 1),
137
- '{0}.requestlist.current.user': ('{0}_reqlist_user', 1),
138
- '{0}.recursion.time.avg': ('{0}_recursive_avg', PRECISION),
139
- '{0}.recursion.time.median': ('{0}_recursive_med', PRECISION)
126
+ '{shortname}.num.queries_ip_ratelimited': ('{shortname}_ratelimit', 1),
127
+ '{shortname}.num.cachehits': ('{shortname}_cachehit', 1),
128
+ '{shortname}.num.cachemiss': ('{shortname}_cachemiss', 1),
129
+ '{shortname}.num.zero_ttl': ('{shortname}_expired', 1),
130
+ '{shortname}.num.prefetch': ('{shortname}_prefetch', 1),
131
+ '{shortname}.num.recursivereplies': ('{shortname}_recursive', 1),
132
+ '{shortname}.requestlist.avg': ('{shortname}_reqlist_avg', 1),
133
+ '{shortname}.requestlist.max': ('{shortname}_reqlist_max', 1),
134
+ '{shortname}.requestlist.overwritten': ('{shortname}_reqlist_overwritten', 1),
135
+ '{shortname}.requestlist.exceeded': ('{shortname}_reqlist_exceeded', 1),
136
+ '{shortname}.requestlist.current.all': ('{shortname}_reqlist_current', 1),
137
+ '{shortname}.requestlist.current.user': ('{shortname}_reqlist_user', 1),
138
+ '{shortname}.recursion.time.avg': ('{shortname}_recursive_avg', PRECISION),
139
+ '{shortname}.recursion.time.median': ('{shortname}_recursive_med', PRECISION)
140
}
141
142
143
+# Used to actually generate per-thread charts.
144
+def _get_perthread_info(thread):
145
+ sname = 'thread{0}'.format(thread)
146
+ lname = 'Thread {0}'.format(thread)
147
+ charts = dict()
148
+ order = []
149
+ statmap = dict()
150
+
151
+ for item in PER_THREAD_CHARTS:
152
+ cname = '{0}{1}'.format(sname, item)
153
+ chart = deepcopy(PER_THREAD_CHARTS[item])
154
+ chart['options'][1] = chart['options'][1].format(longname=lname)
155
+
156
+ for index, line in enumerate(chart['lines']):
157
+ chart['lines'][index][0] = line[0].format(shortname=sname)
158
+
159
+ order.append(cname)
160
+ charts[cname] = chart
161
+
162
+ for key, value in PER_THREAD_STAT_MAP.items():
163
+ statmap[key.format(shortname=sname)] = (value[0].format(shortname=sname), value[1])
164
+
165
+ return (charts, order, statmap)
166
+
167
+
168
class Service(SocketService):
169
def __init__(self, configuration=None, name=None):
170
# The unbound control protocol is always TLS encapsulated
@@ -155,6 +180,7 @@ class Service(SocketService):
180
self.order = deepcopy(ORDER)
181
self.definitions = deepcopy(CHARTS)
182
self.request = 'UBCT1 stats\n'
183
+ self.statmap = deepcopy(STAT_MAP)
184
self._parse_config()
185
self._auto_config()
186
self.debug('Extended stats: {0}'.format(self.ext))
@@ -193,26 +219,13 @@ class Service(SocketService):
219
self.port = 8953
220
221
def _generate_perthread_charts(self):
196
- # TODO: THis could probably be more efficient, but it's only
197
- # run once, so it probably doesn't really matter.
222
+ tmporder = list()
223
for thread in range(0, self.threads):
199
- shortname = 'thread{0}'.format(thread)
200
- longname = 'Thread {0}'.format(thread)
201
- charts = dict()
202
- order = [[], [], []]
203
- count = 0
204
- for item in PER_THREAD_CHARTS:
205
- chartname = '{0}{1}'.format(shortname, item)
206
- order[count].append(chartname)
207
- count += 1
208
- charts[chartname] = deepcopy(PER_THREAD_CHARTS[item])
209
- charts[chartname]['options'][1] = charts[chartname]['options'][1].format(longname)
210
- for line in range(0, len(charts[chartname]['lines'])):
211
- charts[chartname]['lines'][line][0] = charts[chartname]['lines'][line][0].format(shortname)
212
- self.order = self.order + order[0] + order[1] + order[2]
224
+ charts, order, statmap = _get_perthread_info(thread)
225
+ tmporder.extend(order)
226
self.definitions.update(charts)
214
- for key, value in PER_THREAD_STAT_MAP.items():
215
- STAT_MAP[key.format(shortname)] = (value[0].format(shortname), value[1])
227
+ self.statmap.update(statmap)
228
+ self.order.extend(sorted(tmporder))
229
230
def check(self):
231
# Check if authentication is working.
@@ -253,7 +266,7 @@ class Service(SocketService):
266
for line in raw.splitlines():
267
stat = line.split('=')
268
tmp[stat[0]] = stat[1]
256
- for item in STAT_MAP:
269
+ for item in self.statmap:
270
if item in tmp:
258
- data[STAT_MAP[item][0]] = float(tmp[item]) * STAT_MAP[item][1]
271
+ data[self.statmap[item][0]] = float(tmp[item]) * self.statmap[item][1]
272
return data