mirror of
https://github.com/netdata/netdata.git
synced 2025-04-23 13:00:23 +00:00

* apache units fix * beanstalk * bind_rndc * boinc * ceph * chrony * couchdb * dns_query * dnsdist * dockerd * dovecot * elasticsearch by @vlvkobal <3 * example * exim * fail2ban * freeradius minor fixes * freeradius minor fixes * freeradius minor fixes * go_expvar * haproxy * hddtemp * httpcheck * icecast * ipfs * isc_dhcpd * litespeed * logind * megacli * memcached * mongodb * monit * mysql * nginx * nginx_plus * nsd * ntpd * nvidia_smi * openldap * ovpn_status * phpfm * portcheck * postfix * postgres * powerdns * proxysql * puppet * rabbitmq * redis * restroshare * samba * sensors * smartdlog * spigotmc * springboot * squid * retroshare * tomcat * retroshare * tor * traefik * traefik * unbound * uwsgi * varnish * w1sensor * web_log * ok codacy * retroshare * ipfs
200 lines
6.6 KiB
Python
200 lines
6.6 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Description: traefik netdata python.d module
|
|
# Author: Alexandre Menezes (@ale_menezes)
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
from collections import defaultdict
|
|
|
|
from json import loads
|
|
|
|
from bases.FrameworkServices.UrlService import UrlService
|
|
|
|
|
|
ORDER = [
|
|
'response_statuses',
|
|
'response_codes',
|
|
'detailed_response_codes',
|
|
'requests',
|
|
'total_response_time',
|
|
'average_response_time',
|
|
'average_response_time_per_iteration',
|
|
'uptime'
|
|
]
|
|
|
|
CHARTS = {
|
|
'response_statuses': {
|
|
'options': [None, 'Response statuses', 'requests/s', 'responses', 'traefik.response_statuses', 'stacked'],
|
|
'lines': [
|
|
['successful_requests', 'success', 'incremental'],
|
|
['server_errors', 'error', 'incremental'],
|
|
['redirects', 'redirect', 'incremental'],
|
|
['bad_requests', 'bad', 'incremental'],
|
|
['other_requests', 'other', 'incremental']
|
|
]
|
|
},
|
|
'response_codes': {
|
|
'options': [None, 'Responses by codes', 'requests/s', 'responses', 'traefik.response_codes', 'stacked'],
|
|
'lines': [
|
|
['2xx', None, 'incremental'],
|
|
['5xx', None, 'incremental'],
|
|
['3xx', None, 'incremental'],
|
|
['4xx', None, 'incremental'],
|
|
['1xx', None, 'incremental'],
|
|
['other', None, 'incremental']
|
|
]
|
|
},
|
|
'detailed_response_codes': {
|
|
'options': [None, 'Detailed response codes', 'requests/s', 'responses', 'traefik.detailed_response_codes',
|
|
'stacked'],
|
|
'lines': []
|
|
},
|
|
'requests': {
|
|
'options': [None, 'Requests', 'requests/s', 'requests', 'traefik.requests', 'line'],
|
|
'lines': [
|
|
['total_count', 'requests', 'incremental']
|
|
]
|
|
},
|
|
'total_response_time': {
|
|
'options': [None, 'Total response time', 'seconds', 'timings', 'traefik.total_response_time', 'line'],
|
|
'lines': [
|
|
['total_response_time_sec', 'response', 'absolute', 1, 10000]
|
|
]
|
|
},
|
|
'average_response_time': {
|
|
'options': [None, 'Average response time', 'milliseconds', 'timings', 'traefik.average_response_time', 'line'],
|
|
'lines': [
|
|
['average_response_time_sec', 'response', 'absolute', 1, 1000]
|
|
]
|
|
},
|
|
'average_response_time_per_iteration': {
|
|
'options': [None, 'Average response time per iteration', 'milliseconds', 'timings',
|
|
'traefik.average_response_time_per_iteration', 'line'],
|
|
'lines': [
|
|
['average_response_time_per_iteration_sec', 'response', 'incremental', 1, 10000]
|
|
]
|
|
},
|
|
'uptime': {
|
|
'options': [None, 'Uptime', 'seconds', 'uptime', 'traefik.uptime', 'line'],
|
|
'lines': [
|
|
['uptime_sec', 'uptime', 'absolute']
|
|
]
|
|
}
|
|
}
|
|
|
|
HEALTH_STATS = [
|
|
'uptime_sec',
|
|
'average_response_time_sec',
|
|
'total_response_time_sec',
|
|
'total_count',
|
|
'total_status_code_count'
|
|
]
|
|
|
|
|
|
class Service(UrlService):
|
|
def __init__(self, configuration=None, name=None):
|
|
UrlService.__init__(self, configuration=configuration, name=name)
|
|
self.url = self.configuration.get('url', 'http://localhost:8080/health')
|
|
self.order = ORDER
|
|
self.definitions = CHARTS
|
|
self.last_total_response_time = 0
|
|
self.last_total_count = 0
|
|
self.data = {
|
|
'successful_requests': 0,
|
|
'redirects': 0,
|
|
'bad_requests': 0,
|
|
'server_errors': 0,
|
|
'other_requests': 0,
|
|
'1xx': 0,
|
|
'2xx': 0,
|
|
'3xx': 0,
|
|
'4xx': 0,
|
|
'5xx': 0,
|
|
'other': 0,
|
|
'average_response_time_per_iteration_sec': 0,
|
|
}
|
|
|
|
def _get_data(self):
|
|
data = self._get_raw_data()
|
|
|
|
if not data:
|
|
return None
|
|
|
|
data = loads(data)
|
|
|
|
self.get_data_per_code_status(raw_data=data)
|
|
|
|
self.get_data_per_code_family(raw_data=data)
|
|
|
|
self.get_data_per_code(raw_data=data)
|
|
|
|
self.data.update(fetch_data_(raw_data=data, metrics=HEALTH_STATS))
|
|
|
|
self.data['average_response_time_sec'] *= 1000000
|
|
self.data['total_response_time_sec'] *= 10000
|
|
if data['total_count'] != self.last_total_count:
|
|
self.data['average_response_time_per_iteration_sec'] = \
|
|
(data['total_response_time_sec'] - self.last_total_response_time) * \
|
|
1000000 / (data['total_count'] - self.last_total_count)
|
|
else:
|
|
self.data['average_response_time_per_iteration_sec'] = 0
|
|
self.last_total_response_time = data['total_response_time_sec']
|
|
self.last_total_count = data['total_count']
|
|
|
|
return self.data or None
|
|
|
|
def get_data_per_code_status(self, raw_data):
|
|
data = defaultdict(int)
|
|
for code, value in raw_data['total_status_code_count'].items():
|
|
code_prefix = code[0]
|
|
if code_prefix == '1' or code_prefix == '2' or code == '304':
|
|
data['successful_requests'] += value
|
|
elif code_prefix == '3':
|
|
data['redirects'] += value
|
|
elif code_prefix == '4':
|
|
data['bad_requests'] += value
|
|
elif code_prefix == '5':
|
|
data['server_errors'] += value
|
|
else:
|
|
data['other_requests'] += value
|
|
self.data.update(data)
|
|
|
|
def get_data_per_code_family(self, raw_data):
|
|
data = defaultdict(int)
|
|
for code, value in raw_data['total_status_code_count'].items():
|
|
code_prefix = code[0]
|
|
if code_prefix == '1':
|
|
data['1xx'] += value
|
|
elif code_prefix == '2':
|
|
data['2xx'] += value
|
|
elif code_prefix == '3':
|
|
data['3xx'] += value
|
|
elif code_prefix == '4':
|
|
data['4xx'] += value
|
|
elif code_prefix == '5':
|
|
data['5xx'] += value
|
|
else:
|
|
data['other'] += value
|
|
self.data.update(data)
|
|
|
|
def get_data_per_code(self, raw_data):
|
|
for code, value in raw_data['total_status_code_count'].items():
|
|
if self.charts:
|
|
if code not in self.data:
|
|
self.charts['detailed_response_codes'].add_dimension([code, code, 'incremental'])
|
|
self.data[code] = value
|
|
|
|
|
|
def fetch_data_(raw_data, metrics):
|
|
data = dict()
|
|
|
|
for metric in metrics:
|
|
value = raw_data
|
|
metrics_list = metric.split('.')
|
|
try:
|
|
for m in metrics_list:
|
|
value = value[m]
|
|
except KeyError:
|
|
continue
|
|
data['_'.join(metrics_list)] = value
|
|
|
|
return data
|