Refactored code
Chris committed
Feb 28, 2018 at 18:03 UTC
6795391ddb7c78e8dcfc52e1d882d47255f7af42
4 files changed
+51
-60
conf.d/python.d/httpcheck.conf
+1
-1
@@ -19,7 +19,7 @@
19
# may define its own, overriding the defaults.
20
21
# update_every sets the default data collection frequency.
22
-# If unset, the python.d.plugin default is used.
22
+# If unset, the httpcheck default is used, which is at 3 seconds.
23
# update_every: 1
24
25
# priority controls the order of charts at the netdata dashboard.
python.d/README.md
+1
-1
@@ -880,7 +880,7 @@ server:
880
status_accepted: # optional
881
- 200
882
timeout: 1 # optional, supports decimals (e.g. 0.2)
883
- update_every: 1 # optional
883
+ update_every: 3 # optional
884
regex: '.*' # optional
885
redirect: yes # optional
886
```
python.d/httpcheck.chart.py
+28
-47
@@ -3,18 +3,17 @@
3
# Original Author: ccremer (github.com/ccremer)
4
5
import urllib3
6
-import time
6
import re
7
9
-from bases.FrameworkServices.UrlService import UrlService
10
-
8
try:
12
- urllib3.disable_warnings()
13
-except AttributeError:
14
- pass
9
+ from time import monotonic as time
10
+except ImportError:
11
+ from time import time
12
+
13
+from bases.FrameworkServices.UrlService import UrlService
14
15
# default module values (can be overridden per job in `config`)
17
-# update_every = 2
16
+update_every = 3
17
priority = 60000
18
retries = 60
19
@@ -57,32 +56,15 @@ CHARTS = {
56
class Service(UrlService):
57
def __init__(self, configuration=None, name=None):
58
UrlService.__init__(self, configuration=configuration, name=name)
60
- self.url = self.configuration.get('url', None)
61
- self.regex = re.compile(self.configuration.get('regex', '.*'))
59
+ self.regex = self._compile(self.configuration.get('regex'))
60
self.status_codes_accepted = self.configuration.get('status_accepted', [200])
61
self.follow_redirect = self.configuration.get('redirect', True)
62
self.order = ORDER
63
self.definitions = CHARTS
66
- self._manager = None
64
68
- def check(self):
69
- """
70
- Format configuration data and try to connect to server
71
- :return: boolean
72
- """
73
- if not (self.url and isinstance(self.url, str)):
74
- self.error('URL is not defined or type is not <str>')
75
- return False
76
-
77
- self._manager = self._build_manager()
78
- if not self._manager:
79
- return False
80
-
81
- self.info('Enabled {url} with (redirect={redirect}, status={accepted}, interval={update}, timeout={timeout}, '
82
- 'regex={regex})'
83
- .format(url=self.url, redirect=self.follow_redirect, accepted=self.status_codes_accepted,
84
- update=self.update_every, timeout=self.request_timeout, regex=self.regex.pattern))
85
- return True
65
+ @staticmethod
66
+ def _compile(pattern=None):
67
+ return None if pattern is None else re.compile(pattern)
68
69
def _get_data(self):
70
"""
@@ -97,28 +79,15 @@ class Service(UrlService):
79
data[HTTP_NO_CONNECTION] = 0
80
url = self.url
81
try:
100
- retr = 1 if self.follow_redirect else False
101
- start = time.time()
102
- response = self._manager.request(
103
- method='GET', url=url, timeout=self.request_timeout, retries=retr, headers=self._manager.headers,
104
- redirect=self.follow_redirect
105
- )
106
- content = response.data
107
- diff = time.time() - start
82
+ start = time()
83
+ status, content = self._get_raw_data_with_status(retries=1 if self.follow_redirect else False,
84
+ redirect=self.follow_redirect)
85
+ diff = time() - start
86
data[HTTP_RESPONSE_TIME] = max(round(diff * 10000), 0)
109
- data[HTTP_RESPONSE_LENGTH] = len(content)
87
self.debug('Url: {url}. Host responded with status code {code} in {diff} s'.format(
111
- url=url, code=response.status, diff=diff
88
+ url=url, code=status, diff=diff
89
))
113
- self.debug('Content: \n\n{content}\n'.format(content=content))
114
- if response.status in self.status_codes_accepted:
115
- if self.regex.search(content) is None:
116
- self.debug('No match for regex \'{regex}\' found'.format(regex=self.regex.pattern))
117
- data[HTTP_BAD_CONTENT] = 1
118
- else:
119
- data[HTTP_SUCCESS] = 1
120
- else:
121
- data[HTTP_BAD_STATUS] = 1
90
+ self.process_response(content, data, status)
91
92
except urllib3.exceptions.NewConnectionError as error:
93
self.debug("Connection failed: {url}. Error: {error}".format(url=url, error=error))
@@ -137,3 +106,15 @@ class Service(UrlService):
106
return None
107
108
return data
109
+
110
+ def process_response(self, content, data, status):
111
+ data[HTTP_RESPONSE_LENGTH] = len(content)
112
+ self.debug('Content: \n\n{content}\n'.format(content=content))
113
+ if status in self.status_codes_accepted:
114
+ if self.regex is not None and self.regex.search(content) is None:
115
+ self.debug("No match for regex '{regex}' found".format(regex=self.regex.pattern))
116
+ data[HTTP_BAD_CONTENT] = 1
117
+ else:
118
+ data[HTTP_SUCCESS] = 1
119
+ else:
120
+ data[HTTP_BAD_STATUS] = 1
python.d/python_modules/bases/FrameworkServices/UrlService.py
+21
-11
@@ -75,20 +75,30 @@ class UrlService(SimpleService):
75
:return: str
76
"""
77
try:
78
- url = url or self.url
79
- manager = manager or self._manager
80
- response = manager.request(method='GET',
81
- url=url,
82
- timeout=self.request_timeout,
83
- retries=1,
84
- headers=manager.headers)
78
+ status, data = self._get_raw_data_with_status(url, manager)
79
+ if status == 200:
80
+ return data
81
+ else:
82
+ self.debug('Url: {url}. Http response status code: {code}'.format(url=url, code=status))
83
+ return None
84
except (urllib3.exceptions.HTTPError, TypeError, AttributeError) as error:
85
self.error('Url: {url}. Error: {error}'.format(url=url, error=error))
86
return None
88
- if response.status == 200:
89
- return response.data.decode()
90
- self.debug('Url: {url}. Http response status code: {code}'.format(url=url, code=response.status))
91
- return None
87
+
88
+ def _get_raw_data_with_status(self, url=None, manager=None, retries=1, redirect=True):
89
+ """
90
+ Get status and response body content from http request. Does not catch exceptions
91
+ :return: int, str
92
+ """
93
+ url = url or self.url
94
+ manager = manager or self._manager
95
+ response = manager.request(method='GET',
96
+ url=url,
97
+ timeout=self.request_timeout,
98
+ retries=retries,
99
+ headers=manager.headers,
100
+ redirect=redirect)
101
+ return response.status, response.data.decode()
102
103
def check(self):
104
"""