mirror of
https://github.com/mtan93/cachet-url-monitor.git
synced 2026-03-08 05:31:58 +00:00
Verifying component status when we initialize to set the initial state. Tests are failing, but checking it in nonetheless.
This commit is contained in:
@@ -25,6 +25,16 @@ class ConfigurationValidationError(Exception):
|
|||||||
return repr(self.value)
|
return repr(self.value)
|
||||||
|
|
||||||
|
|
||||||
|
class ComponentNonexistentError(Exception):
|
||||||
|
"""Exception raised when the component does not exist."""
|
||||||
|
|
||||||
|
def __init__(self, component_id):
|
||||||
|
self.component_id = component_id
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return repr('Component with id [%d] does not exist.' % (self.component_id,))
|
||||||
|
|
||||||
|
|
||||||
class Configuration(object):
|
class Configuration(object):
|
||||||
"""Represents a configuration file, but it also includes the functionality
|
"""Represents a configuration file, but it also includes the functionality
|
||||||
of assessing the API and pushing the results to cachet.
|
of assessing the API and pushing the results to cachet.
|
||||||
@@ -37,7 +47,10 @@ class Configuration(object):
|
|||||||
self.config_file = config_file
|
self.config_file = config_file
|
||||||
self.data = load(file(self.config_file, 'r'))
|
self.data = load(file(self.config_file, 'r'))
|
||||||
|
|
||||||
|
# We need to validate the configuration is correct and then validate the component actually exists.
|
||||||
self.validate()
|
self.validate()
|
||||||
|
self.headers = {'X-Cachet-Token': self.data['cachet']['token']}
|
||||||
|
self.status = self.get_current_status(self.data['cachet']['component_id'])
|
||||||
|
|
||||||
self.logger.info('Monitoring URL: %s %s' %
|
self.logger.info('Monitoring URL: %s %s' %
|
||||||
(self.data['endpoint']['method'], self.data['endpoint']['url']))
|
(self.data['endpoint']['method'], self.data['endpoint']['url']))
|
||||||
@@ -46,7 +59,16 @@ class Configuration(object):
|
|||||||
for expectation in self.expectations:
|
for expectation in self.expectations:
|
||||||
self.logger.info('Registered expectation: %s' % (expectation,))
|
self.logger.info('Registered expectation: %s' % (expectation,))
|
||||||
|
|
||||||
self.headers = {'X-Cachet-Token': self.data['cachet']['token']}
|
def get_current_status(self, component_id):
|
||||||
|
get_status_request = requests.get(
|
||||||
|
'%s/components/%d' % (self.data['cachet']['api_url'], self.data['cachet']['component_id']),
|
||||||
|
headers=self.headers)
|
||||||
|
|
||||||
|
if get_status_request.ok:
|
||||||
|
# The component exists.
|
||||||
|
return get_status_request.json()['data']['status']
|
||||||
|
else:
|
||||||
|
raise ComponentNonexistentError(component_id)
|
||||||
|
|
||||||
def is_create_incident(self):
|
def is_create_incident(self):
|
||||||
"""Will verify if the configuration is set to create incidents or not.
|
"""Will verify if the configuration is set to create incidents or not.
|
||||||
@@ -172,7 +194,8 @@ class Configuration(object):
|
|||||||
if incident_request.ok:
|
if incident_request.ok:
|
||||||
# Successful metrics upload
|
# Successful metrics upload
|
||||||
self.logger.info(
|
self.logger.info(
|
||||||
'Incident updated: component status [%d], message: "%s"' % (self.status, self.message))
|
'Incident updated, API healthy again: component status [%d], message: "%s"' % (
|
||||||
|
self.status, self.message))
|
||||||
del self.incident_id
|
del self.incident_id
|
||||||
else:
|
else:
|
||||||
self.logger.warning(
|
self.logger.warning(
|
||||||
@@ -253,10 +276,10 @@ class Latency(Expectaction):
|
|||||||
return cachet_url_monitor.status.COMPONENT_STATUS_PERFORMANCE_ISSUES
|
return cachet_url_monitor.status.COMPONENT_STATUS_PERFORMANCE_ISSUES
|
||||||
|
|
||||||
def get_message(self, response):
|
def get_message(self, response):
|
||||||
return 'Latency above threshold: %.4f' % (response.elapsed.total_seconds(),)
|
return 'Latency above threshold: %.4f seconds' % (response.elapsed.total_seconds(),)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return repr('Latency threshold: %.4f' % (self.threshold,))
|
return repr('Latency threshold: %.4f seconds' % (self.threshold,))
|
||||||
|
|
||||||
|
|
||||||
class Regex(Expectaction):
|
class Regex(Expectaction):
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ class Agent(object):
|
|||||||
"""Monitor agent that will be constantly verifying if the URL is healthy
|
"""Monitor agent that will be constantly verifying if the URL is healthy
|
||||||
and updating the component.
|
and updating the component.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, configuration):
|
def __init__(self, configuration):
|
||||||
self.configuration = configuration
|
self.configuration = configuration
|
||||||
|
|
||||||
@@ -18,7 +19,6 @@ class Agent(object):
|
|||||||
cachet server.
|
cachet server.
|
||||||
"""
|
"""
|
||||||
self.configuration.evaluate()
|
self.configuration.evaluate()
|
||||||
self.configuration.push_status()
|
|
||||||
self.configuration.push_metrics()
|
self.configuration.push_metrics()
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
@@ -26,11 +26,34 @@ class Agent(object):
|
|||||||
schedule.every(self.configuration.data['frequency']).seconds.do(self.execute)
|
schedule.every(self.configuration.data['frequency']).seconds.do(self.execute)
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateStatusAgent(Agent):
|
||||||
|
def __init__(self, configuration):
|
||||||
|
super(UpdateStatusAgent, self).__init__(configuration)
|
||||||
|
|
||||||
|
def execute(self):
|
||||||
|
super(UpdateStatusAgent, self).execute()
|
||||||
|
self.configuration.push_status()
|
||||||
|
|
||||||
|
|
||||||
|
class CreateIncidentAgent(Agent):
|
||||||
|
def __init__(self, configuration):
|
||||||
|
super(CreateIncidentAgent, self).__init__(configuration)
|
||||||
|
|
||||||
|
def execute(self):
|
||||||
|
super(CreateIncidentAgent, self).execute()
|
||||||
|
self.configuration.push_incident()
|
||||||
|
|
||||||
|
|
||||||
class Scheduler(object):
|
class Scheduler(object):
|
||||||
def __init__(self, config_file):
|
def __init__(self, config_file):
|
||||||
self.logger = logging.getLogger('cachet_url_monitor.scheduler.Scheduler')
|
self.logger = logging.getLogger('cachet_url_monitor.scheduler.Scheduler')
|
||||||
self.configuration = Configuration(config_file)
|
self.configuration = Configuration(config_file)
|
||||||
self.agent = Agent(self.configuration)
|
|
||||||
|
if self.configuration.is_create_incident():
|
||||||
|
self.agent = CreateIncidentAgent(self.configuration)
|
||||||
|
else:
|
||||||
|
self.agent = UpdateStatusAgent(self.configuration)
|
||||||
|
|
||||||
self.stop = False
|
self.stop = False
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
endpoint:
|
endpoint:
|
||||||
url: http://localhost:8080/swagger
|
url: http://localhost:8080/swagger
|
||||||
method: GET
|
method: GET
|
||||||
timeout: 0.01
|
timeout: 0.1
|
||||||
expectation:
|
expectation:
|
||||||
- type: HTTP_STATUS
|
- type: HTTP_STATUS
|
||||||
status: 200
|
status: 200
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ class LatencyTest(unittest.TestCase):
|
|||||||
elapsed.total_seconds = total_seconds
|
elapsed.total_seconds = total_seconds
|
||||||
|
|
||||||
assert self.expectation.get_message(request) == ('Latency above '
|
assert self.expectation.get_message(request) == ('Latency above '
|
||||||
'threshold: 0.1000')
|
'threshold: 0.1000 seconds')
|
||||||
|
|
||||||
|
|
||||||
class HttpStatusTest(unittest.TestCase):
|
class HttpStatusTest(unittest.TestCase):
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
import mock
|
|
||||||
import unittest
|
|
||||||
import sys
|
import sys
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import mock
|
||||||
|
|
||||||
sys.modules['schedule'] = mock.Mock()
|
sys.modules['schedule'] = mock.Mock()
|
||||||
sys.modules['cachet_url_monitor.configuration.Configuration'] = mock.Mock()
|
# sys.modules['cachet_url_monitor.configuration.Configuration'] = mock.Mock()
|
||||||
from cachet_url_monitor.scheduler import Agent,Scheduler
|
sys.modules['requests'] = mock.Mock()
|
||||||
|
from cachet_url_monitor.scheduler import Agent, Scheduler
|
||||||
|
|
||||||
|
|
||||||
class AgentTest(unittest.TestCase):
|
class AgentTest(unittest.TestCase):
|
||||||
@@ -21,7 +24,7 @@ class AgentTest(unittest.TestCase):
|
|||||||
self.agent.execute()
|
self.agent.execute()
|
||||||
|
|
||||||
evaluate.assert_called_once()
|
evaluate.assert_called_once()
|
||||||
push_status.assert_called_once()
|
push_status.assert_not_called()
|
||||||
|
|
||||||
def test_start(self):
|
def test_start(self):
|
||||||
every = sys.modules['schedule'].every
|
every = sys.modules['schedule'].every
|
||||||
@@ -33,16 +36,28 @@ class AgentTest(unittest.TestCase):
|
|||||||
|
|
||||||
|
|
||||||
class SchedulerTest(unittest.TestCase):
|
class SchedulerTest(unittest.TestCase):
|
||||||
|
@mock.patch('cachet_url_monitor.configuration.Configuration.__init__', mock.Mock(return_value=None))
|
||||||
|
@mock.patch('cachet_url_monitor.configuration.Configuration.is_create_incident', mock.Mock(return_value=False))
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.mock_configuration = sys.modules[('cachet_url_monitor.configuration'
|
def get(url, headers):
|
||||||
'.Configuration')]
|
get_return = mock.Mock()
|
||||||
|
get_return.ok = True
|
||||||
|
get_return.json = mock.Mock()
|
||||||
|
get_return.json.return_value = {'data': {'status': 1}}
|
||||||
|
return get_return
|
||||||
|
|
||||||
|
sys.modules['requests'].get = get
|
||||||
|
|
||||||
self.scheduler = Scheduler('config.yml')
|
self.scheduler = Scheduler('config.yml')
|
||||||
|
|
||||||
def test_init(self):
|
def test_init(self):
|
||||||
assert self.scheduler.stop == False
|
assert self.scheduler.stop == False
|
||||||
|
|
||||||
def test_start(self):
|
@mock.patch('cachet_url_monitor.configuration.Configuration', create=True)
|
||||||
#TODO(mtakaki|2016-05-01): We need a better way of testing this method.
|
def test_start(self, mock_configuration):
|
||||||
|
# TODO(mtakaki|2016-05-01): We need a better way of testing this method.
|
||||||
# Leaving it as a placeholder.
|
# Leaving it as a placeholder.
|
||||||
|
mock_configuration.data = {'frequency': 30}
|
||||||
|
|
||||||
self.scheduler.stop = True
|
self.scheduler.stop = True
|
||||||
self.scheduler.start()
|
self.scheduler.start()
|
||||||
|
|||||||
Reference in New Issue
Block a user