From 37bec316ff7159cceeebb9d634ada3c2cd6223c2 Mon Sep 17 00:00:00 2001 From: Mitsuo Takaki Date: Wed, 27 Apr 2016 21:45:24 -0700 Subject: [PATCH] Initial implementation but taking a different approach. --- .gitignore | 7 +++ cachet_url_monitor/__init__.py | 0 cachet_url_monitor/configuration.py | 71 +++++++++++++++++++++++++++++ config.yml | 14 ++++++ dev_requirements.txt | 4 ++ 5 files changed, 96 insertions(+) create mode 100644 .gitignore create mode 100644 cachet_url_monitor/__init__.py create mode 100644 cachet_url_monitor/configuration.py create mode 100644 config.yml create mode 100644 dev_requirements.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..099d114 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +bin/ +include/ +lib/ +share/ +.Python +*.swp +*.pyc diff --git a/cachet_url_monitor/__init__.py b/cachet_url_monitor/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/cachet_url_monitor/configuration.py b/cachet_url_monitor/configuration.py new file mode 100644 index 0000000..551f74f --- /dev/null +++ b/cachet_url_monitor/configuration.py @@ -0,0 +1,71 @@ +import abc +import requests +import timeit +from yaml import load + + +class Configuration(object): + def __init__(self, config_file): + #TODO(mtakaki|2016-04-26): Needs validation if the config is correct. + self.config_file = config_file + self.data = load(file(self.config_file, 'r')) + self.expectations = [Expectaction.create(expectation) for expectation + in self.data['endpoint']['expectation']] + + def evaluate(self): + self.request = requests.request(self.data['endpoint']['method'], + self.data['endpoint']['url']) + self.status = True + self.message = '' + for expectation in self.expectations: + status = expectation.is_healthy(self.request) + self.status = self.status and status + + def push_status_and_metrics(self): + if not self.status: + params = {'id': self.data['cachet']['component_id'], 'status': 0} + headers = {'X-Cachet-Token': self.data['cachet']['token']} + incident_request = requests.post('%s/api/v1/components/%d' % + (self.data['cachet']['api_url'], + self.data['cachet']['component_id']), + params=params, headers=headers) + +class Expectaction(object): + @staticmethod + def create(configuration): + expectations = { + 'HTTP_STATUS': HttpStatus, + 'LATENCY': Latency + } + return expectations.get(configuration['type'])(configuration) + + @abc.abstractmethod + def is_healthy(self, response): + """Returns true if the endpoint is healthy and false if otherwise.""" + + @abc.abstractmethod + def get_message(self, response): + """Gets the error message.""" + + +class HttpStatus(Expectaction): + def __init__(self, configuration): + self.status = configuration['status'] + + def is_healthy(self, response): + return response.status_code == self.status + + def get_message(self, response): + return 'Unexpected HTTP status (%s)' % (response.status_code,) + + +class Latency(Expectaction): + def __init__(self, configuration): + self.threshold = configuration['threshold'] + + def is_healthy(self, response): + return response.elapsed.total_seconds() <= self.threshold + + def get_message(self, response): + return 'Latency above threshold: %d' % + (response.elapsed.total_seconds(),) diff --git a/config.yml b/config.yml new file mode 100644 index 0000000..44bd3e4 --- /dev/null +++ b/config.yml @@ -0,0 +1,14 @@ +endpoint: + url: http://www.google.com + method: GET + expectation: + - type: HTTP_STATUS + status: 200 + - type: LATENCY + threshold: 80 +cachet: + api_url: http://status.cachethq.io/api/v1/ + token: my_token + component_id: 1 + metric_id: 1 +frequency: 30 diff --git a/dev_requirements.txt b/dev_requirements.txt new file mode 100644 index 0000000..2792593 --- /dev/null +++ b/dev_requirements.txt @@ -0,0 +1,4 @@ +PyYAML==3.11 +ipython==4.2.0 +pudb==2016.1 +requests==2.9.1