Skip to content
Snippets Groups Projects
Commit f7248f2d authored by jurgenhaas's avatar jurgenhaas
Browse files

Improved version of haproxy charts

parent fc66bc93
No related branches found
No related tags found
No related merge requests found
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Description: haproxy netdata python.d module # Description: haproxy netdata python.d module
# Author: l2isbad # Author: l2isbad
from base import UrlService from base import UrlService, SocketService
# default module values (can be overridden per job in `config`) # default module values (can be overridden per job in `config`)
# update_every = 2 # update_every = 2
...@@ -10,14 +10,14 @@ priority = 60000 ...@@ -10,14 +10,14 @@ priority = 60000
retries = 60 retries = 60
# charts order (can be overridden if you want less charts, or different order) # charts order (can be overridden if you want less charts, or different order)
ORDER = ['fbin', 'fbout', 'fscur', 'fqcur', 'bbin', 'bbout', 'bscur', 'bqcur'] ORDER = ['fbin', 'fbout', 'fscur', 'fqcur', 'bbin', 'bbout', 'bscur', 'bqcur', 'health_down']
CHARTS = { CHARTS = {
'fbin': { 'fbin': {
'options': [None, "Bytes in", "bytes/s", 'Frontend', 'f.bin', 'line'], 'options': [None, "Kilobytes in", "kilobytes in/s", 'Frontend', 'f.bin', 'line'],
'lines': [ 'lines': [
]}, ]},
'fbout': { 'fbout': {
'options': [None, "Bytes out", "bytes/s", 'Frontend', 'f.bout', 'line'], 'options': [None, "Kilobytes out", "kilobytes out/s", 'Frontend', 'f.bout', 'line'],
'lines': [ 'lines': [
]}, ]},
'fscur': { 'fscur': {
...@@ -29,11 +29,11 @@ CHARTS = { ...@@ -29,11 +29,11 @@ CHARTS = {
'lines': [ 'lines': [
]}, ]},
'bbin': { 'bbin': {
'options': [None, "Bytes in", "bytes/s", 'Backend', 'b.bin', 'line'], 'options': [None, "Kilobytes in", "kilobytes in/s", 'Backend', 'b.bin', 'line'],
'lines': [ 'lines': [
]}, ]},
'bbout': { 'bbout': {
'options': [None, "Bytes out", "bytes/s", 'Backend', 'b.bout', 'line'], 'options': [None, "Kilobytes out", "kilobytes out/s", 'Backend', 'b.bout', 'line'],
'lines': [ 'lines': [
]}, ]},
'bscur': { 'bscur': {
...@@ -43,55 +43,74 @@ CHARTS = { ...@@ -43,55 +43,74 @@ CHARTS = {
'bqcur': { 'bqcur': {
'options': [None, "Sessions in queue", "sessions", 'Backend', 'b.qcur', 'line'], 'options': [None, "Sessions in queue", "sessions", 'Backend', 'b.qcur', 'line'],
'lines': [ 'lines': [
]},
'health_down': {
'options': [None, "Servers in DOWN state", "failed servers", 'Health', 'h.down', 'line'],
'lines': [
]} ]}
} }
class Service(UrlService): class Service(UrlService, SocketService):
def __init__(self, configuration=None, name=None): def __init__(self, configuration=None, name=None):
UrlService.__init__(self, configuration=configuration, name=name) SocketService.__init__(self, configuration=configuration, name=name)
self.url = "http://127.0.0.1:7000/haproxy_stats;csv" self.user = self.configuration.get('user')
self.password = self.configuration.get('pass')
self.request = 'show stat\n'
self.poll_method = (UrlService, SocketService)
self.order = ORDER self.order = ORDER
self.order_front = [_ for _ in ORDER if _.startswith('f')] self.order_front = [_ for _ in ORDER if _.startswith('f')]
self.order_back = [_ for _ in ORDER if _.startswith('b')] self.order_back = [_ for _ in ORDER if _.startswith('b')]
self.definitions = CHARTS self.definitions = CHARTS
self.charts = True self.charts = True
def check(self):
if self.configuration.get('url'):
self.poll_method = self.poll_method[0]
url = self.configuration.get('url')
if not url.endswith(';csv;norefresh'):
self.error('Bad url(%s). Must be http://<ip.address>:<port>/<url>;csv;norefresh' % url)
return False
elif self.configuration.get('socket'):
self.poll_method = self.poll_method[1]
else:
self.error('No configuration is specified')
return False
if self.poll_method.check(self):
self.info('Plugin was started succesfully. We are using %s.' % self.poll_method.__name__)
return True
def create_charts(self, front_ends, back_ends): def create_charts(self, front_ends, back_ends):
for chart in self.order_front: for _ in range(len(front_ends)):
for _ in range(len(front_ends)): self.definitions['fbin']['lines'].append(['_'.join(['fbin', front_ends[_]['# pxname']]), front_ends[_]['# pxname'], 'incremental', 1, 1024])
self.definitions[chart]['lines'].append(['_'.join([chart, front_ends[_]['# pxname']]), self.definitions['fbout']['lines'].append(['_'.join(['fbout', front_ends[_]['# pxname']]), front_ends[_]['# pxname'], 'incremental', 1, 1024])
front_ends[_]['# pxname'], self.definitions['fscur']['lines'].append(['_'.join(['fscur', front_ends[_]['# pxname']]), front_ends[_]['# pxname'], 'absolute'])
'incremental' if chart.startswith( self.definitions['fqcur']['lines'].append(['_'.join(['fqcur', front_ends[_]['# pxname']]), front_ends[_]['# pxname'], 'absolute'])
('fb', 'bb')) else 'absolute'])
for chart in self.order_back: for _ in range(len(back_ends)):
for _ in range(len(back_ends)): self.definitions['bbin']['lines'].append(['_'.join(['bbin', back_ends[_]['# pxname']]), back_ends[_]['# pxname'], 'incremental', 1, 1024])
self.definitions[chart]['lines'].append(['_'.join([chart, back_ends[_]['# pxname']]), self.definitions['bbout']['lines'].append(['_'.join(['bbout', back_ends[_]['# pxname']]), back_ends[_]['# pxname'], 'incremental', 1, 1024])
back_ends[_]['# pxname'], self.definitions['bscur']['lines'].append(['_'.join(['bscur', back_ends[_]['# pxname']]), back_ends[_]['# pxname'], 'absolute'])
'incremental' if chart.startswith( self.definitions['bqcur']['lines'].append(['_'.join(['bqcur', back_ends[_]['# pxname']]), back_ends[_]['# pxname'], 'absolute'])
('fb', 'bb')) else 'absolute']) self.definitions['health_down']['lines'].append(['_'.join(['hdown', back_ends[_]['# pxname']]), back_ends[_]['# pxname'], 'absolute'])
def _get_data(self): def _get_data(self):
""" """
Format data received from http request Format data received from http request
:return: dict :return: dict
""" """
if self.url[-4:] != ';csv':
self.url += ';csv'
self.info('Url rewritten to %s' % self.url)
try: try:
raw_data = self._get_raw_data().splitlines() raw_data = self.poll_method._get_raw_data(self).splitlines()
except Exception as e: except Exception as e:
self.error(str(e)) self.error(str(e))
return None return None
all_instances = [dict(zip(raw_data[0].split(','), raw_data[_].split(','))) for _ in range(1, len(raw_data))] all_instances = [dict(zip(raw_data[0].split(','), raw_data[_].split(','))) for _ in range(1, len(raw_data))]
back_ends = [backend for backend in all_instances back_ends = list(filter(is_backend, all_instances))
if backend['svname'] == 'BACKEND' and backend['# pxname'] != 'stats'] front_ends = list(filter(is_frontend, all_instances))
front_ends = [frontend for frontend in all_instances servers = list(filter(is_server, all_instances))
if frontend['svname'] == 'FRONTEND' and frontend['# pxname'] != 'stats']
if self.charts: if self.charts:
self.create_charts(front_ends, back_ends) self.create_charts(front_ends, back_ends)
...@@ -107,4 +126,40 @@ class Service(UrlService): ...@@ -107,4 +126,40 @@ class Service(UrlService):
for _ in self.order_back: for _ in self.order_back:
to_netdata.update({'_'.join([_, backend['# pxname']]): int(backend[_[1:]]) if backend.get(_[1:]) else 0}) to_netdata.update({'_'.join([_, backend['# pxname']]): int(backend[_[1:]]) if backend.get(_[1:]) else 0})
for _ in range(len(back_ends)):
to_netdata.update({'_'.join(['hdown', back_ends[_]['# pxname']]):
len([server for server in servers if is_server_down(server, back_ends, _)])})
return to_netdata return to_netdata
def _check_raw_data(self, data):
"""
Check if all data has been gathered from socket
:param data: str
:return: boolean
"""
return not bool(data)
def is_backend(backend):
try:
return backend['svname'] == 'BACKEND' and backend['# pxname'] != 'stats'
except Exception:
return False
def is_frontend(frontend):
try:
return frontend['svname'] == 'FRONTEND' and frontend['# pxname'] != 'stats'
except Exception:
return False
def is_server(server):
try:
return not server['svname'].startswith(('FRONTEND', 'BACKEND'))
except Exception:
return False
def is_server_down(server, back_ends, _):
try:
return server['# pxname'] == back_ends[_]['# pxname'] and server['status'] != 'UP'
except Exception:
return False
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment