Skip to content
This repository has been archived by the owner on Apr 5, 2019. It is now read-only.

Commit

Permalink
Merge pull request #3 from Axiacore/refactor
Browse files Browse the repository at this point in the history
Refactor
  • Loading branch information
camilonova authored Aug 12, 2016
2 parents 0b0fe09 + adab3fd commit 0305258
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 126 deletions.
52 changes: 19 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Cachet Uptime Robot

Cachet is an open source status page system, this repository is a Python script that does two things, **first**, it reads the status of a page in UptimeRobot and updates a cachet component based on that status and **second**, it updates a metric with the historic uptime data from Uptime Robot.
Cachet is an open source status page system, this repository is a Python script that does two things, **first**, it reads the status of a page in UptimeRobot and updates a cachet component based on that status and **second**, it updates a metric with the historic uptime ratio from Uptime Robot.

**Component status: Uptime Robot (left), Cachet (right)**

Expand All @@ -11,41 +11,35 @@ Cachet is an open source status page system, this repository is a Python script

### Getting started

To get started, you have to specify your Cachet settings and UptimeRobot api key.
```python
UPTIME_ROBOT_API_KEY = 'your-api-key'
```
To get started, you have to specify your Cachet and UptimeRobot settings and in **config.ini**.
```ini
[uptimeRobot]
UptimeRobotMainApiKey = your-api-key

In the `MONITOR_LIST` variable you have to specify some settings for each monitor.

```python
MONITOR_LIST = {
'https://mydomain.com': {
'api_key': 'cachet-api-key',
'status_url': 'https://your-status-page-url.com/api/v1',
'component_id': 1,
'metric_id': 1,
}
}
[https://url.in.uptime.robot.com]
CachetApiKey = cachet-api-key
CachetUrl = https://status.mycompany.com
MetricId = 1
ComponentId = 1
```

* `api_key`: Global Cachet API key
* `status_url`: URL of the API of the status page you want to show the uptime in.
* `component_id`: Id of the Cachet component with site status
* `metric_id`: Id of the metric where you want to show the uptime graph.
* `CachetApiKey`: Cachet API key.
* `CachetUrl`: URL of the API of the status page you want to show the site availability in.
* `MetricId`: Id of the Cachet metric with site availability.
* `ComponentId`: (Optional) Id of the component you want to update on each check.

### Usage

Register a cron that runs `cron.py` every 5 minutes.

```bash
```bash
# Open cron file to edit.
crontab -e
```

Edit the crontab file and add this line:
```bash
*/5 * * * * python3 ~/cachet-uptime-robot/cron.py
*/5 * * * * python3 ~/path/update_status.py ~/path/config.ini
```

_Note that the path of cron.py may vary depending on the location you cloned the repository_
Expand All @@ -55,16 +49,8 @@ _Note that the path of cron.py may vary depending on the location you cloned the
You can also update your Cachet data manually by running this:

```python
from update_status import Monitor

# Create a monitor instance
m = Monitor()

# Gets uptime data from UptimeRobot and send to Cachet.
m.update_all_monitors()
python3 update_status.py config.ini

>>> Updating monitor MyDomain: URL: https://mydomain.com - id: 12345678
>>> Created metric with id 27:
>>> {'data': {'id': 27, 'calculated_value': 7872, 'value': 328, 'updated_at': '2016-08-11 08:35:32', 'created_at': '2016-08-11 09:59:59', 'counter': 24, 'metric_id': 1}}
>>> ...
>>> Updating monitor MySite. URL: http://mysite.co. ID: 12345678
>>> Metric created: {'data': {'calculated_value': 99.99, 'counter': 1, 'metric_id': 4, 'value': 99.99, 'created_at': '2016-08-12 08:23:10', 'updated_at': '2016-08-12 08:23:10', 'id': 99}}
```
8 changes: 8 additions & 0 deletions config.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[uptimeRobot]
UptimeRobotMainApiKey = abcd

[https://url.in.uptime.robot.com]
CachetApiKey = cachet-api-key
CachetUrl = https://status.mycompany.com
MetricId = 1
ComponentId = 1
6 changes: 0 additions & 6 deletions cron.py

This file was deleted.

174 changes: 87 additions & 87 deletions update_status.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,17 @@
#!/usr/bin/env python3

import json
import sys
import time
import configparser
from urllib import request
from urllib import parse
from datetime import datetime

# API Key from `https://uptimerobot.com/`.
UPTIME_ROBOT_API_KEY = ''

# List of monitors to update.
# Each monitor must be an active UptimeRobot monitor and also
# there must be a Cachet metric and component for it.
MONITOR_LIST = {
'https://mydomain.com': {
'api_key': 'cachet-api-key',
'status_url': 'https://your-status-page-url.com',
'component_id': 1,
'metric_id': 1,
}
}

# Terminal colors.
GREEN = '\033[92m'
RED = '\033[91m'
ENDC = '\033[0m'


class UptimeRobot(object):
""" Intermediate class for setting uptime stats.
"""
def __init__(self, api_key=''):
def __init__(self, api_key):
self.api_key = api_key
self.base_url = 'https://api.uptimerobot.com/'

Expand Down Expand Up @@ -83,9 +65,9 @@ class CachetHq(object):
CACHET_SEEMS_DOWN = 3
CACHET_DOWN = 4

def __init__(self, api_key='', base_url=''):
self.api_key = api_key
self.base_url = base_url
def __init__(self, cachet_api_key, cachet_url):
self.cachet_api_key = cachet_api_key
self.cachet_url = cachet_url

def update_component(self, id_component=1, status=None):
component_status = None
Expand All @@ -103,8 +85,8 @@ def update_component(self, id_component=1, status=None):
component_status = self.CACHET_DOWN

if component_status:
url = '{0}/{1}/{2}/'.format(
self.base_url,
url = '{0}/api/v1/{1}/{2}/'.format(
self.cachet_url,
'components',
id_component
)
Expand All @@ -115,16 +97,18 @@ def update_component(self, id_component=1, status=None):
url=url,
data=data,
method='PUT',
headers={
'X-Cachet-Token': self.api_key,
}
headers={'X-Cachet-Token': self.cachet_api_key},
)
response = request.urlopen(req)
content = response.read().decode('utf-8')
return content

def set_data_metrics(self, value, timestamp, id_metric=1):
url = '{0}/metrics/{1}/points/'.format(self.base_url, id_metric)
url = '{0}/api/v1/metrics/{1}/points/'.format(
self.cachet_url,
id_metric
)

data = parse.urlencode({
'value': value,
'timestamp': timestamp,
Expand All @@ -133,21 +117,23 @@ def set_data_metrics(self, value, timestamp, id_metric=1):
url=url,
data=data,
method='POST',
headers={
'X-Cachet-Token': self.api_key,
}
headers={'X-Cachet-Token': self.cachet_api_key},
)
response = request.urlopen(req)
content = response.read().decode('utf-8')
return json.loads(content)

return json.loads(response.read().decode('utf-8'))

def get_last_metric_point(self, id_metric):
url = '{0}/metrics/{1}/points/'.format(self.base_url, id_metric)
url = '{0}/api/v1/metrics/{1}/points/'.format(
self.cachet_url,
id_metric
)

req = request.Request(
url=url,
method='GET',
headers={
'X-Cachet-Token': self.api_key,
'X-Cachet-Token': self.cachet_api_key,
}
)
response = request.urlopen(req)
Expand All @@ -157,93 +143,107 @@ def get_last_metric_point(self, id_metric):
content
).get('meta').get('pagination').get('total_pages')

url = '{0}/metrics/{1}/points?page={2}'.format(
self.base_url,
url = '{0}/api/v1/metrics/{1}/points?page={2}'.format(
self.cachet_url,
id_metric,
last_page
)

req = request.Request(
url=url,
method='GET',
headers={
'X-Cachet-Token': self.api_key,
}
headers={'X-Cachet-Token': self.cachet_api_key},
)
response = request.urlopen(req)
content = response.read().decode('utf-8')

if json.loads(content).get('data'):
return json.loads(content).get('data')[0]
data = json.loads(content).get('data')[0]
else:
return {
data = {
'created_at': datetime.now().date().strftime(
'%Y-%m-%d %H:%M:%S'
)
}

return data


class Monitor(object):
def __init__(self, monitor_list, api_key):
self.monitor_list = monitor_list
self.api_key = api_key

def send_data_to_catchet(self, monitor):
""" Posts data to Cachet API.
Data sent is the value of last `Uptime`.
"""
website_config = MONITOR_LIST[monitor.get('url')]
cachet = CachetHq(
website_config['api_key'],
website_config['status_url']
)
try:
website_config = self.monitor_list[monitor.get('url')]
except KeyError:
print('ERROR: monitor is not valid')
sys.exit(1)

cachet.update_component(
website_config['component_id'],
monitor.get('status')
cachet = CachetHq(
cachet_api_key=website_config['cachet_api_key'],
cachet_url=website_config['cachet_url'],
)

last_date_metric_point = datetime.strptime(
cachet.get_last_metric_point(
website_config['metric_id']
).get('created_at'), '%Y-%m-%d %H:%M:%S')

for point in reversed(monitor.get('responsetime')):
point_datetime = datetime.strptime(
point.get('datetime'),
'%m/%d/%Y %H:%M:%S'
if 'component_id' in website_config:
cachet.update_component(
website_config['component_id'],
int(monitor.get('status'))
)
if point_datetime > last_date_metric_point:
metric = cachet.set_data_metrics(
point.get('value'),
int(point_datetime.strftime('%s')),
website_config['metric_id']
)
print(
'{0}Created metric with id {1}{2}:'.format(
GREEN,
metric['data']['id'],
ENDC,
)
)
print(metric)

def update_all_monitors(self):
metric = cachet.set_data_metrics(
monitor.get('alltimeuptimeratio'),
int(time.time()),
website_config['metric_id']
)
print('Metric created: {0}'.format(metric))

def update(self):
""" Update all monitors uptime and status.
"""
uptime_robot = UptimeRobot(UPTIME_ROBOT_API_KEY)
uptime_robot = UptimeRobot(self.api_key)
success, response = uptime_robot.get_monitors(response_times=1)
if success:
monitors = response.get('monitors').get('monitor')
for monitor in monitors:
print('{0}Updating monitor {1}: URL: {2} - id: {3}{4}'.format(
GREEN,
print('Updating monitor {0}. URL: {1}. ID: {2}'.format(
monitor['friendlyname'],
monitor['url'],
monitor['id'],
ENDC,
))
self.send_data_to_catchet(monitor)
else:
print(
'{0}No data was returned from UptimeMonitor {1}'.format(
RED,
ENDC
)
)
print('ERROR: No data was returned from UptimeMonitor')


if __name__ == "__main__":
CONFIG = configparser.ConfigParser()
CONFIG.read(sys.argv[1])
SECTIONS = CONFIG.sections()

if not SECTIONS:
print('ERROR: File path is not valid')
sys.exit(1)

UPTIME_ROBOT_API_KEY = None
MONITOR_DICT = {}
for element in SECTIONS:
if element == 'uptimeRobot':
uptime_robot_api_key = CONFIG[element]['UptimeRobotMainApiKey']
else:
MONITOR_DICT[element] = {
'cachet_api_key': CONFIG[element]['CachetApiKey'],
'cachet_url': CONFIG[element]['CachetUrl'],
'metric_id': CONFIG[element]['MetricId'],
}
if 'ComponentId' in CONFIG[element]:
MONITOR_DICT[element].update({
'component_id': CONFIG[element]['ComponentId'],
})

MONITOR = Monitor(monitor_list=MONITOR_DICT, api_key=uptime_robot_api_key)
MONITOR.update()

0 comments on commit 0305258

Please sign in to comment.