@cryptotaxi247 / netdata-1 / commits / b314a58e3

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):