varnish plugin: backend hosts reponse charts added
Ilya committed
Jan 15, 2017 at 01:08 UTC
b314a58e3077e1431025aeda2cb113b347afc06f
1 file changed
+62
-21
python.d/varnish.chart.py
+62
-21
@@ -179,36 +179,50 @@ class Service(SimpleService):
179
if is_executable(''.join([directory, 'varnishstat']), X_OK)][0]
180
except IndexError:
181
self.varnish = False
182
- self.regex = compile(r'([A-Z]+\.)([\d\w_.]+)\s+([0-9]+)')
182
+ self.rgx_all = compile(r'([A-Z]+\.)([\d\w_.]+)\s+(\d+)')
183
+ # Could be
184
+ # VBE.boot.super_backend.pipe_hdrbyte (new)
185
+ # or
186
+ # VBE.default2(127.0.0.2,,81).bereq_bodybytes (old)
187
+ # Regex result: [('super_backend', 'beresp_hdrbytes', '0'), ('super_backend', 'beresp_bodybytes', '0')]
188
+ self.rgx_bck = (compile(r'VBE.([\d\w_.]+)\(.*?\).(beresp[\w_]+)\s+(\d+)'),
189
+ compile(r'VBE.boot.([\w\d_]+).(beresp[\w_]+)\s+(\d+)'))
190
self.extra_charts = self.configuration.get('extra_charts', [])
191
192
def check(self):
186
- # Cant start without varnishstat command
193
+ # Cant start without 'varnishstat' command
194
if not self.varnish:
188
- self.error('varnishstat command was not found in %s or not executable by netdata' % DIRECTORIES)
195
+ self.error('\'varnishstat\' command was not found in %s or not executable by netdata' % DIRECTORIES)
196
return False
197
198
# If command is present and we can execute it we need to make sure..
199
# 1. STDOUT is not empty
200
reply = self._get_raw_data()
201
if not reply:
195
- self.error('No output from varnishstat (not enough privileges?)')
202
+ self.error('No output from \'varnishstat\' (not enough privileges?)')
203
return False
204
205
# 2. Output is parsable (list is not empty after regex findall)
199
- is_parsable = self.regex.findall(reply)
206
+ is_parsable = self.rgx_all.findall(reply)
207
if not is_parsable:
208
self.error('Cant parse output (only varnish version 4+ supported)')
209
return False
203
-
210
+
211
+ # We need to find the right regex for backend parse
212
+ self.backend_list = self.rgx_bck[0].findall(reply)[::2]
213
+ if self.backend_list:
214
+ self.rgx_bck = self.rgx_bck[0]
215
+ else:
216
+ self.backend_list = self.rgx_bck[1].findall(reply)[::2]
217
+ self.rgx_bck = self.rgx_back[1]
218
+
219
# We are about to start!
220
self.create_charts()
221
222
self.info('Active charts: %s' % self.order)
208
- self.info('Plugin was started succesfully')
223
+ self.info('Plugin was started successfully')
224
return True
225
211
-
226
def _get_raw_data(self):
227
try:
228
reply = Popen([self.varnish, '-1'], stdout=PIPE, stderr=PIPE, shell=False)
@@ -228,45 +242,72 @@ class Service(SimpleService):
242
:return: dict
243
"""
244
raw_data = self._get_raw_data()
231
- data = self.regex.findall(raw_data)
245
+ data_all = self.rgx_all.findall(raw_data)
246
+ data_backend = self.rgx_bck.findall(raw_data)
247
233
- if not data:
248
+ if not data_all:
249
return None
250
236
- # ALL data from 'varnishstat -1'. t - type(MAIN, MEMPOOL etc)
237
- to_netdata = {k: int(v) for t, k, v in data}
251
+ # 1. ALL data from 'varnishstat -1'. t - type(MAIN, MEMPOOL etc)
252
+ to_netdata = {k: int(v) for t, k, v in data_all}
253
+
254
+ # 2. ADD backend statistics
255
+ to_netdata.update({'_'.join([n, k]): int(v) for n, k, v in data_backend})
256
239
- # ADD additional keys to dict
240
- cache_summary = sum([to_netdata.get('cache_hit', 0), to_netdata.get('cache_miss', 0), to_netdata.get('cache_hitpass', 0)])
257
+ # 3. ADD additional keys to dict
258
+ # 3.1 Cache hit/miss/hitpass overall in percent
259
+ cache_summary = sum([to_netdata.get('cache_hit', 0), to_netdata.get('cache_miss', 0),
260
+ to_netdata.get('cache_hitpass', 0)])
261
to_netdata['cache_hit_perc'] = find_percent(to_netdata.get('cache_hit', 0), cache_summary, 10000)
262
to_netdata['cache_miss_perc'] = find_percent(to_netdata.get('cache_miss', 0), cache_summary, 10000)
263
to_netdata['cache_hitpass_perc'] = find_percent(to_netdata.get('cache_hitpass', 0), cache_summary, 10000)
244
- to_netdata['obj_per_objhead'] = find_percent(to_netdata.get('n_object', 0), to_netdata.get('n_objecthead', 0), 100)
264
+
265
+ # 3.2 Copy random stuff to new keys (do we need this?)
266
+ to_netdata['obj_per_objhead'] = find_percent(to_netdata.get('n_object', 0),
267
+ to_netdata.get('n_objecthead', 0), 100)
268
to_netdata['backend_conn_bt'] = to_netdata.get('backend_conn', 0)
269
to_netdata['sess_conn_rr'] = to_netdata.get('sess_conn', 0)
270
to_netdata['n_lru_nuked_e'] = to_netdata.get('n_lru_nuked', 0)
271
249
- for elem in ['backend_busy', 'backend_unhealthy', 'esi_errors', 'esi_warnings', 'losthdr', 'sess_drop', 'sess_fail', 'sess_pipe_overflow',
250
- 'threads_destroyed', 'threads_failed', 'threads_limited']:
272
+ for elem in ['backend_busy', 'backend_unhealthy', 'esi_errors', 'esi_warnings', 'losthdr', 'sess_drop',
273
+ 'sess_fail', 'sess_pipe_overflow', 'threads_destroyed', 'threads_failed', 'threads_limited']:
274
to_netdata[''.join([elem, '_b'])] = to_netdata.get(elem, 0)
275
276
+ # Ready steady go!
277
return to_netdata
278
279
def create_charts(self):
280
+ # If 'all_charts' is true...ALL charts are displayed. If no only default + 'extra_charts'
281
if self.configuration.get('all_charts'):
257
- self.order = EXTRA_CHARTS
282
+ self.order = EXTRA_ORDER
283
else:
284
try:
285
extra_charts = list(filter(lambda chart: chart in EXTRA_ORDER, self.extra_charts.split()))
261
- except Exception:
286
+ except (AttributeError, NameError, ValueError):
287
self.error('Extra charts disabled.')
288
extra_charts = []
289
290
self.order = ORDER[:]
291
self.order.extend(extra_charts)
267
- self.order = self.order
292
269
- self.definitions = {k: v for k, v in CHARTS.items() if k in self.order}
293
+ # Create static charts
294
+ self.definitions = {chart: values for chart, values in CHARTS.items() if chart in self.order}
295
+
296
+ # Create dynamic backend charts
297
+ if self.backend_list:
298
+ for backend in self.backend_list:
299
+ self.order.insert(0, ''.join([backend[0], '_resp_stats']))
300
+ self.definitions.update({''.join([backend[0], '_resp_stats']): {
301
+ 'options': [None,
302
+ '%s response statistics' % backend[0].capitalize(),
303
+ "bits/s",
304
+ 'Backend response',
305
+ 'varnish.backend',
306
+ 'area'],
307
+ 'lines': [[''.join([backend[0], '_beresp_hdrbytes']),
308
+ 'header', 'incremental', 8, 1],
309
+ [''.join([backend[0], '_beresp_bodybytes']),
310
+ 'body', 'incremental', -8, 1]]}})
311
312
313
def find_percent(value1, value2, multiply):