Added logs for each ping. Contains no data yet and estimates 15.7 mil rows a year. Considering adding log aggregation. Moved some folders and files into mem folder due to circular import.
13
app.py
@@ -1,18 +1,11 @@
|
|||||||
# import requests as r
|
# import requests as r
|
||||||
from flask import jsonify, Flask, render_template, send_file
|
from flask import jsonify, render_template, send_file
|
||||||
from poll_services import start_async_loop
|
from poll_services import start_async_loop
|
||||||
from mem import services
|
from mem import services, app
|
||||||
import threading
|
import threading
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
from flask_migrate import init, upgrade
|
||||||
from flask_migrate import Migrate, init, upgrade
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
# Flask app to serve status
|
|
||||||
app = Flask(__name__)
|
|
||||||
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///app.db"
|
|
||||||
|
|
||||||
db = SQLAlchemy(app=app)
|
|
||||||
migration = Migrate(app=app, db=db)
|
|
||||||
|
|
||||||
# Init and upgrade
|
# Init and upgrade
|
||||||
with app.app_context():
|
with app.app_context():
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
|
from flask import Flask
|
||||||
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
|
from flask_migrate import Migrate
|
||||||
|
|
||||||
|
|
||||||
class service:
|
class service:
|
||||||
@@ -78,3 +81,10 @@ services: list[service] = [
|
|||||||
id=11, url="https://unifi.local/", label="Unifi Server", public=False
|
id=11, url="https://unifi.local/", label="Unifi Server", public=False
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Flask app to serve status
|
||||||
|
app = Flask(__name__)
|
||||||
|
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///app.db"
|
||||||
|
|
||||||
|
db = SQLAlchemy(app=app)
|
||||||
|
migration = Migrate(app=app, db=db)
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 191 B After Width: | Height: | Size: 191 B |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 680 B After Width: | Height: | Size: 680 B |
|
Before Width: | Height: | Size: 550 B After Width: | Height: | Size: 550 B |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 389 B After Width: | Height: | Size: 389 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 950 B After Width: | Height: | Size: 950 B |
|
Before Width: | Height: | Size: 642 B After Width: | Height: | Size: 642 B |
32
migrations/versions/d7d380435347_.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: d7d380435347
|
||||||
|
Revises:
|
||||||
|
Create Date: 2025-09-02 08:43:16.682424
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'd7d380435347'
|
||||||
|
down_revision = None
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table('log',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('dateCreated', sa.DateTime(), nullable=False),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_table('log')
|
||||||
|
# ### end Alembic commands ###
|
||||||
10
models.py
@@ -1,6 +1,12 @@
|
|||||||
from app import db
|
from mem import db
|
||||||
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
|
|
||||||
class logs(db.Model):
|
class log(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
dateCreated = db.Column(db.DateTime, nullable=False)
|
dateCreated = db.Column(db.DateTime, nullable=False)
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.dateCreated = datetime.now(timezone.utc)
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
from mem import services, service
|
from mem import services, service, db, app
|
||||||
import httpx
|
import httpx
|
||||||
import asyncio
|
import asyncio
|
||||||
import time
|
import time
|
||||||
|
from models import log
|
||||||
|
from sqlalchemy.orm import sessionmaker
|
||||||
|
|
||||||
|
|
||||||
async def check_service(client: httpx.AsyncClient, s: service):
|
async def check_service(client: httpx.AsyncClient, s: service) -> log:
|
||||||
try:
|
try:
|
||||||
before = time.perf_counter()
|
before = time.perf_counter()
|
||||||
match s.ping_type:
|
match s.ping_type:
|
||||||
@@ -22,7 +24,6 @@ async def check_service(client: httpx.AsyncClient, s: service):
|
|||||||
)
|
)
|
||||||
case _:
|
case _:
|
||||||
raise httpx.HTTPError("Unknown ping type")
|
raise httpx.HTTPError("Unknown ping type")
|
||||||
|
|
||||||
after = time.perf_counter()
|
after = time.perf_counter()
|
||||||
s.set_error(None)
|
s.set_error(None)
|
||||||
s.set_online(r.status_code == 200)
|
s.set_online(r.status_code == 200)
|
||||||
@@ -33,6 +34,7 @@ async def check_service(client: httpx.AsyncClient, s: service):
|
|||||||
s.set_online(False)
|
s.set_online(False)
|
||||||
s.set_status(None)
|
s.set_status(None)
|
||||||
s.set_ping(None)
|
s.set_ping(None)
|
||||||
|
return log()
|
||||||
|
|
||||||
|
|
||||||
def start_async_loop():
|
def start_async_loop():
|
||||||
@@ -44,14 +46,25 @@ def start_async_loop():
|
|||||||
|
|
||||||
async def update_services(loop: asyncio.AbstractEventLoop):
|
async def update_services(loop: asyncio.AbstractEventLoop):
|
||||||
print("Starting service updates...")
|
print("Starting service updates...")
|
||||||
|
with app.app_context():
|
||||||
|
WorkerSession = sessionmaker(bind=db.engine)
|
||||||
async with (
|
async with (
|
||||||
httpx.AsyncClient() as public_client,
|
httpx.AsyncClient() as public_client,
|
||||||
httpx.AsyncClient(verify=False) as local_client,
|
httpx.AsyncClient(verify=False) as local_client,
|
||||||
):
|
):
|
||||||
while True:
|
while True:
|
||||||
|
session = WorkerSession()
|
||||||
tasks = [
|
tasks = [
|
||||||
check_service(public_client if s.public else local_client, s)
|
check_service(public_client if s.public else local_client, s)
|
||||||
for s in services
|
for s in services
|
||||||
]
|
]
|
||||||
await asyncio.gather(*tasks)
|
logs = await asyncio.gather(*tasks)
|
||||||
|
try:
|
||||||
|
session.add_all(logs)
|
||||||
|
session.commit()
|
||||||
|
except Exception as e:
|
||||||
|
session.rollback()
|
||||||
|
raise e
|
||||||
|
finally:
|
||||||
|
session.close()
|
||||||
await asyncio.sleep(2)
|
await asyncio.sleep(2)
|
||||||
|
|||||||