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