Skip to content

Commit

Permalink
Merge pull request #22 from dabluecaboose/master
Browse files Browse the repository at this point in the history
Adds support for groupings in status page and checks.yaml
  • Loading branch information
harsxv authored Sep 11, 2024
2 parents a58cd00 + 2b65706 commit 6c15e1f
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 71 deletions.
122 changes: 64 additions & 58 deletions checks.yaml
Original file line number Diff line number Diff line change
@@ -1,71 +1,77 @@
- name: GitHub Home
type: http
host: https://github.com
expected_code: 200
- title: 'Group 1'
checks:
- name: GitHub Home
type: http
host: https://github.com
expected_code: 200

- name: GitHub API
type: http
host: https://api.github.com
expected_code: 200
- name: GitHub API
type: http
host: https://api.github.com
expected_code: 200

- name: Wikipedia Home
type: http
host: https://www.wikipedia.org
expected_code: 200
- name: Wikipedia Home
type: http
host: https://www.wikipedia.org
expected_code: 200

- name: Wikipedia API
type: http
host: https://en.wikipedia.org/w/api.php
expected_code: 200
- name: Wikipedia API
type: http
host: https://en.wikipedia.org/w/api.php
expected_code: 200

- name: Hacker News
type: http
host: https://news.ycombinator.com
expected_code: 200
- name: Hacker News
type: http
host: https://news.ycombinator.com
expected_code: 200

- name: Google Home
type: http
host: https://www.google.com
expected_code: 200
- name: Google Home
type: http
host: https://www.google.com
expected_code: 200

- name: Cloudflare DNS Checker
type: ping
host: 1.1.1.1
- title: 'Group 2'
checks:
- name: Cloudflare DNS Checker
type: ping
host: 1.1.1.1

- name: Google Public DNS
type: ping
host: 8.8.8.8
- name: Google Public DNS
type: ping
host: 8.8.8.8

- name: Dummy Postgres Database
type: port
host: ec2-54-173-89-248.compute-1.amazonaws.com
port: 5432
- name: Dummy Postgres Database
type: port
host: ec2-54-173-89-248.compute-1.amazonaws.com
port: 5432

- name: Dummy MySQL Database
type: port
host: db.example.com
port: 3306
- name: Dummy MySQL Database
type: port
host: db.example.com
port: 3306

- name: Amazon Web Services
type: http
host: https://aws.amazon.com
expected_code: 200
- title: 'Group 3'
checks:
- name: Amazon Web Services
type: http
host: https://aws.amazon.com
expected_code: 200

- name: AWS S3 API
type: http
host: https://s3.amazonaws.com
expected_code: 200
- name: AWS S3 API
type: http
host: https://s3.amazonaws.com
expected_code: 200

- name: Twitter
type: http
host: https://twitter.com
expected_code: 200
- name: Twitter
type: http
host: https://twitter.com
expected_code: 200

- name: Facebook Home
type: http
host: https://www.facebook.com
expected_code: 200
- name: Localhost
type: ping
host: localhost
- name: Facebook Home
type: http
host: https://www.facebook.com
expected_code: 200

- name: Localhost
type: ping
host: localhost
3 changes: 3 additions & 0 deletions index.html.theme
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@
<body>
<h1>TinyStatus</h1>
<h2>Current Status</h2>
{% for group, checks in groups.items() %}
<h3>{{group}} Status</h3>
<div class="status-grid">
{% for check in checks %}
<div class="status-item">
Expand All @@ -93,6 +95,7 @@
</div>
{% endfor %}
</div>
{% endfor %}
<h2>Incident History</h2>
<div class="incidents">
{{ incidents | safe }}
Expand Down
45 changes: 32 additions & 13 deletions tinystatus.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
STATUS_HISTORY_FILE = os.getenv('STATUS_HISTORY_FILE', 'history.json')
HTML_OUTPUT_DIRECTORY = os.getenv('HTML_OUTPUT_DIRECTORY', os.getcwd())


# Service check functions
async def check_http(url, expected_code):
async with aiohttp.ClientSession() as session:
Expand All @@ -34,13 +35,15 @@ async def check_http(url, expected_code):
except:
return False


async def check_ping(host):
try:
result = subprocess.run(['ping', '-c', '1', '-W', '2', host], capture_output=True, text=True)
return result.returncode == 0
except:
return False


async def check_port(host, port):
try:
_, writer = await asyncio.open_connection(host, port)
Expand All @@ -50,6 +53,7 @@ async def check_port(host, port):
except:
return False


async def run_checks(checks):
background_tasks = {}
async with asyncio.TaskGroup() as tg:
Expand All @@ -70,35 +74,42 @@ async def run_checks(checks):

return results


# History management
def load_history():
if os.path.exists(STATUS_HISTORY_FILE):
with open(STATUS_HISTORY_FILE, 'r') as f:
return json.load(f)
return {}


def save_history(history):
with open(STATUS_HISTORY_FILE, 'w') as f:
json.dump(history, f, indent=2)


def update_history(results):
# TODO: Configure groups in history page
history = load_history()
current_time = datetime.now().isoformat()
for check in results:
if check['name'] not in history:
history[check['name']] = []
history[check['name']].append({'timestamp': current_time, 'status': check['status']})
history[check['name']] = history[check['name']][-MAX_HISTORY_ENTRIES:]
for group in results.keys():
for check in results[group]:
if check['name'] not in history:
history[check['name']] = []
history[check['name']].append({'timestamp': current_time, 'status': check['status']})
history[check['name']] = history[check['name']][-MAX_HISTORY_ENTRIES:]
save_history(history)


# Main monitoring loop
async def monitor_services():
os.makedirs(HTML_OUTPUT_DIRECTORY, exist_ok=True)

while True:
down_services = []
try:
with open(CHECKS_FILE, 'r') as f:
checks = yaml.safe_load(f)
groups = yaml.safe_load(f)

with open(INCIDENTS_FILE, 'r') as f:
incidents = markdown.markdown(f.read())
Expand All @@ -109,11 +120,13 @@ async def monitor_services():
with open(HISTORY_TEMPLATE_FILE, 'r') as f:
history_template = Template(f.read())

results = await run_checks(checks)
results = {}
for group in groups:
results[group['title']] = await run_checks(group['checks'])

update_history(results)

html = template.render(checks=results, incidents=incidents, last_updated=datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
html = template.render(groups=results, incidents=incidents, last_updated=datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
with open(os.path.join(HTML_OUTPUT_DIRECTORY, 'index.html'), 'w') as f:
f.write(html)

Expand All @@ -122,18 +135,24 @@ async def monitor_services():
f.write(history_html)

logging.info(f"Status page and history updated at {datetime.now()}")
down_services = [check['name'] for check in results if not check['status']]
if down_services:
logging.warning(f"Services currently down: {', '.join(down_services)}")

for group in results:
group_down = [check['name'] for check in results[group] if not check['status']]
down_services += group_down

except Exception as e:
logging.error(f"An error occurred: {str(e)}")

if MONITOR_CONTINOUSLY == False:
# down_services = [group[check]['name'] for check in group in results if not check['status']]
if down_services:
logging.warning(f"Services currently down: {', '.join(down_services)}")

if not MONITOR_CONTINOUSLY:
return

await asyncio.sleep(CHECK_INTERVAL)


# Main function
def main():
with open(CHECKS_FILE, 'r') as f:
Expand Down

0 comments on commit 6c15e1f

Please sign in to comment.