@cryptotaxi247 / netdata-1 / commits / 5f241dd01

Add http check plugin

Chris committed Feb 20, 2018 at 17:51 UTC 5f241dd011f68b3b2f4487c70cc45a2ccf425691
2 files changed +119
python.d/Makefile.am
+1
@@ -32,6 +32,7 @@ dist_python_DATA = \
32 go_expvar.chart.py \
33 haproxy.chart.py \
34 hddtemp.chart.py \
35 + httpcheck.chart.py \
36 ipfs.chart.py \
37 isc_dhcpd.chart.py \
38 mdstat.chart.py \
python.d/httpcheck.chart.py new
+118
@@ -0,0 +1,118 @@
1 +# -*- coding: utf-8 -*-
2 +# Description: http check netdata python.d module
3 +# Original Author: ccremer (github.com/ccremer)
4 +
5 +import urllib3
6 +import time
7 +import re
8 +
9 +from bases.FrameworkServices.UrlService import UrlService
10 +
11 +try:
12 + urllib3.disable_warnings()
13 +except AttributeError:
14 + pass
15 +
16 +# default module values (can be overridden per job in `config`)
17 +# update_every = 2
18 +priority = 60000
19 +retries = 60
20 +
21 +HTTP_RESPONSE_TIME = 'http_responsetime'
22 +HTTP_ERROR = 'http_error'
23 +
24 +ORDER = ['responsetime', 'error']
25 +
26 +CHARTS = {
27 + 'responsetime': {
28 + 'options': [None, 'HTTP response time', 'ms', 'response time', 'httpcheck.responsetime', 'line'],
29 + 'lines': [
30 + [HTTP_RESPONSE_TIME, 'response_time', 'absolute', 100, 1000]
31 + ]},
32 + 'error': {
33 + 'options': [None, 'HTTP check error code', 'code', 'error', 'httpcheck.error', 'line'],
34 + 'lines': [
35 + [HTTP_ERROR, 'error', 'absolute']
36 + ]}
37 +}
38 +
39 +CONTENT_MISMATCH = 1
40 +STATUS_NOT_ACCEPTED = 2
41 +CONNECTION_TIMED_OUT = 3
42 +CONNECTION_FAILED = 4
43 +
44 +
45 +class Service(UrlService):
46 + def __init__(self, configuration=None, name=None):
47 + UrlService.__init__(self, configuration=configuration, name=name)
48 + self.url = self.configuration.get('url', None)
49 + self.regex = re.compile(self.configuration.get('regex', '.*'))
50 + self.status_codes_accepted = self.configuration.get('status_accepted', [200])
51 + self.follow_redirect = self.configuration.get('redirect', False)
52 + self.order = ORDER
53 + self.definitions = CHARTS
54 + self._manager = None
55 +
56 + def check(self):
57 + """
58 + Format configuration data and try to connect to server
59 + :return: boolean
60 + """
61 + if not (self.url and isinstance(self.url, str)):
62 + self.error('URL is not defined or type is not <str>')
63 + return False
64 +
65 + self._manager = self._build_manager()
66 + if not self._manager:
67 + return False
68 +
69 + self.info('Enabled {url} with (redirect={redirect}, status_accepted={accepted}, update_every={update}, '
70 + 'timeout={timeout})'
71 + .format(
72 + url=self.url, redirect=self.follow_redirect, accepted=self.status_codes_accepted,
73 + update=self.update_every, timeout=self.request_timeout
74 + ))
75 + return True
76 +
77 + def _get_data(self):
78 + """
79 + Format data received from http request
80 + :return: dict
81 + """
82 + data = dict()
83 + data[HTTP_RESPONSE_TIME] = 0
84 + data[HTTP_ERROR] = 0
85 + url = self.url
86 + try:
87 + start = time.time()
88 + response = self._manager.request(
89 + method='GET', url=url, timeout=self.request_timeout, retries=1, headers=self._manager.headers,
90 + redirect=self.follow_redirect
91 + )
92 + diff = time.time() - start
93 + data[HTTP_RESPONSE_TIME] = max(round(diff * 10000), 1)
94 +
95 + self.debug('Url: {url}. Http response status code: {code}'.format(url=url, code=response.status))
96 + if response.status in self.status_codes_accepted:
97 + content = response.data
98 + self.debug('Content: \n\n{content}\n'.format(content=content))
99 + match = self.regex.search(content)
100 + if match is None:
101 + self.debug('No match for regex \'{regex}\' found'.format(regex=self.regex.pattern))
102 + data[HTTP_ERROR] = CONTENT_MISMATCH
103 + else:
104 + data[HTTP_ERROR] = STATUS_NOT_ACCEPTED
105 +
106 + except urllib3.exceptions.TimeoutError:
107 + self.debug("Connection timed out: {url}".format(url=url))
108 + data[HTTP_ERROR] = CONNECTION_TIMED_OUT
109 +
110 + except urllib3.exceptions.HTTPError:
111 + self.debug("Connection timed out: {url}".format(url=url))
112 + data[HTTP_ERROR] = CONNECTION_FAILED
113 +
114 + except (TypeError, AttributeError) as error:
115 + self.error('Url: {url}. Error: {error}'.format(url=url, error=error))
116 + return None
117 +
118 + return data