diff --git a/README.md b/README.md index 2a171fc..524a9b5 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ cachet: token: my_token component_id: 1 metric_id: 1 - update_status: true + action: CREATE_INCIDENT frequency: 30 ``` @@ -50,7 +50,9 @@ frequency: 30 - **token**, the API token. - **component_id**, the id of the component we're monitoring. This will be used to update the status of the component. - **metric_id**, this will be used to store the latency of the API. If this is not set, it will be ignored. - - **update_status**, boolean to decide if the component status should be changed in case of a check failure. + - **action**, the action to be done when one of the expectations fails. This is optional and if left blank, nothing will be done to the component. + - **CREATE_INCIDENT**, we will create an incident when the expectation fails. + - **UPDATE_STATUS**, updates the component status - **frequency**, how often we'll send a request to the given URL. The unit is in seconds. ## Setting up diff --git a/cachet_url_monitor/configuration.py b/cachet_url_monitor/configuration.py index cce6c4d..a5369ec 100644 --- a/cachet_url_monitor/configuration.py +++ b/cachet_url_monitor/configuration.py @@ -7,10 +7,11 @@ import re import time import requests -import status as st from yaml import dump from yaml import load +import status as st + # This is the mandatory fields that must be in the configuration file in this # same exact structure. configuration_mandatory_fields = { @@ -100,6 +101,15 @@ class Configuration(object): """ return 'update_status' in self.data['cachet'] and self.data['cachet']['update_status'] + def get_action(self): + """Retrieves the action list from the configuration. If it's empty, returns an empty list. + :return: The list of actions, which can be an empty list. + """ + if self.data['cachet'].get('action') is None: + return [] + else: + return self.data['cachet']['action'] + def validate(self): """Validates the configuration by verifying the mandatory fields are present and in the correct format. If the validation fails, a diff --git a/cachet_url_monitor/scheduler.py b/cachet_url_monitor/scheduler.py index cd8bb10..3668fdf 100644 --- a/cachet_url_monitor/scheduler.py +++ b/cachet_url_monitor/scheduler.py @@ -1,18 +1,21 @@ #!/usr/bin/env python -from configuration import Configuration import logging -import schedule import sys import time +import schedule + +from configuration import Configuration + class Agent(object): """Monitor agent that will be constantly verifying if the URL is healthy and updating the component. """ - def __init__(self, configuration): + def __init__(self, configuration, decorators=[]): self.configuration = configuration + self.decorators = decorators def execute(self): """Will verify the API status and push the status and metrics to the @@ -21,43 +24,49 @@ class Agent(object): self.configuration.evaluate() self.configuration.push_metrics() + for decorator in self.decorators: + decorator.execute(self.configuration) + def start(self): """Sets up the schedule based on the configuration file.""" 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 Decorator(object): + def execute(self, configuration): + pass -class CreateIncidentAgent(Agent): - def __init__(self, configuration): - super(CreateIncidentAgent, self).__init__(configuration) +class UpdateStatusAgent(Decorator): + def execute(self, configuration): + configuration.push_status() - def execute(self): - super(CreateIncidentAgent, self).execute() - self.configuration.push_incident() + +class CreateIncidentAgent(Decorator): + def execute(self, configuration): + configuration.push_incident() class Scheduler(object): def __init__(self, config_file): self.logger = logging.getLogger('cachet_url_monitor.scheduler.Scheduler') self.configuration = Configuration(config_file) - - if self.configuration.is_create_incident(): - self.agent = CreateIncidentAgent(self.configuration) - elif self.configuration.is_update_status(): - self.agent = UpdateStatusAgent(self.configuration) - else: - self.agent = Agent(self.configuration) + self.agent = self.get_agent() self.stop = False + def get_agent(self): + action_names = { + 'CREATE_INCIDENT': CreateIncidentAgent, + 'UPDATE_STATUS': UpdateStatusAgent, + None: Agent + } + actions = [] + for action in self.configuration.get_action(): + self.logger.info('Registering action %s' % (action)) + actions.append(action_names[action]()) + return Agent(self.configuration, decorators=actions) + def start(self): self.agent.start() self.logger.info('Starting monitor agent...') diff --git a/config.yml b/config.yml index 8282ed0..1c68a99 100644 --- a/config.yml +++ b/config.yml @@ -14,6 +14,7 @@ cachet: token: my_token component_id: 1 #metric_id: 1 - create_incident: true - update_status: true + action: + - CREATE_INCIDENT + - UPDATE_STATUS frequency: 30