diff --git a/app/crud.py b/app/crud.py index 6416d99..7d1f6cf 100644 --- a/app/crud.py +++ b/app/crud.py @@ -1,10 +1,11 @@ import bcrypt, time -from sqlalchemy.orm import Session +from sqlalchemy.orm import Session, load_only from app import models, schemas User=models.User Service=models.Service +Metric=models.Metric def get_user(db: Session, user_id: int): return db.query(User).filter(User.id == user_id).first() @@ -44,6 +45,8 @@ def update_user(db: Session, user_id: int, user: schemas.UserUpdate): db.query(User).filter(User.id==user_id).update({User.full_name: updated_user.full_name}) if (updated_user.is_active is not None): db.query(User).filter(User.id==user_id).update({User.is_active: updated_user.is_active}) + if (updated_user.is_superuser is not None): + db.query(User).filter(User.id==user_id).update({User.is_superuser: updated_user.is_superuser}) if (updated_user is not user): db.query(User).filter(User.id==user_id).update({User.updated_unix: time.time()}) return db.commit() @@ -109,3 +112,25 @@ def login_info(db: Session, name: str, password: str): return return usr + + +def get_urls(db: Session): + # return db.query(Service).filter(Service.is_active == True).options(load_only(Service.url)).all() + return db.query(Service).filter(Service.is_active == True).all() + + +def get_metrics(db: Session, skip: int = 0, limit: int = 90): + return db.query(Metrics).offset(skip).limit(limit).all() + +def create_metric(db: Session, me: schemas.MetricCreate): + db_metric = User(**me.dict()) + if (me.http_response_code >=500): + db_metric.status=2 + elif (me.http_response_code >=400): + db_metric.status=1 + elif (me.http_response_code >=200): + db_metric.status=0 + db.add(db_metric) + db.commit() + return db.commit() + diff --git a/app/main.py b/app/main.py index 9891949..57bf82b 100644 --- a/app/main.py +++ b/app/main.py @@ -1,6 +1,7 @@ # vim:fileencoding=utf-8:ft=python:foldmethod=marker # statuspage/app/main.py +import asyncio from typing import List, Optional from fastapi import FastAPI, Depends, Security, HTTPException @@ -8,6 +9,7 @@ from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm from sqlalchemy.orm import Session from app import crud, models, schemas, auth +from app import ultrametrics from app.database import SessionLocal, engine @@ -111,7 +113,7 @@ async def read_user(user_id: int, db: Session = Depends(get_db)): @app.patch("/api/v1/users/{user_id}") async def update_user(user_id: int, user: schemas.UserUpdate, db: Session = Depends(get_db), token: str = Security(is_auth)): - if ((user.name is None) and (user.password is None) and (user.full_name is None) and (user.is_active is None)): + if ((user.name is None) and (user.password is None) and (user.full_name is None) and (user.is_active is None) and (user.is_superuser is None)): raise HTTPException(status_code=400, detail="No data provided") db_user = get_usr(user_id, db) if db_user is None: @@ -142,3 +144,14 @@ async def validate_token(token: str): if a: return a + + + +@app.get("/api/v1/metrics", response_model=List[schemas.Metric]) +async def get_metrics(skip: int = 0, limit: int = 90, db: Session = Depends(get_db)): + return crud.get_metrics(db=db, skip=skip, limit=limit) + +@app.get("/api/v1/urls") +async def get_urls(skip: int = 0, limit: int = 90, db: Session = Depends(get_db)): + return crud.get_urls(db=db, skip=skip, limit=limit) + diff --git a/app/models.py b/app/models.py index 13f8803..43651fb 100644 --- a/app/models.py +++ b/app/models.py @@ -28,9 +28,23 @@ class User(Base): full_name = Column(String, index=True) password = Column(String) is_active = Column(Boolean, index=True) + is_superuser = Column(Boolean, default=False) created_unix = Column(Float) updated_unix = Column(Float, default=None) last_login_unix = Column(Float, default=None) service = relationship("Service", back_populates="user") + +class Metric(Base): + __tablename__ = "metric" + + id = Column(Integer, primary_key=True, index=True) + service_id = Column(Integer, ForeignKey("service.id"), index=True) + request_unix = Column(Float) + response_unix = Column(Float) + http_response_code = Column(Integer) + status = Column(Integer) + + # service = relationship("Service", back_populates="metric") + diff --git a/app/run_tasks.py b/app/run_tasks.py new file mode 100644 index 0000000..562a124 --- /dev/null +++ b/app/run_tasks.py @@ -0,0 +1,6 @@ +from .tasks import api, metrics +import time + +if __name__ == '__main__': + metrics() + # api() diff --git a/app/tasks.py b/app/tasks.py new file mode 100644 index 0000000..316f0ea --- /dev/null +++ b/app/tasks.py @@ -0,0 +1,14 @@ +import time, asyncio, uvicorn +from celery import Celery +from celery.schedules import crontab +from app.celery import app +from app import ultrametrics +from app.main import app as statuspage + +@app.task +def metrics(): + task = asyncio.create_task(ultrametrics.main()) + +@app.task +def api(): + task = asyncio.create_task(uvicorn.run(statuspage)) diff --git a/app/ultrametrics.py b/app/ultrametrics.py index 97290bd..3bc52ff 100644 --- a/app/ultrametrics.py +++ b/app/ultrametrics.py @@ -1,12 +1,15 @@ -import asyncio, logging, time +import asyncio, logging, time, aiohttp from datetime import datetime from threading import Thread from typing import Optional, Tuple, Sequence +from app import crud +from app.database import SessionLocal -import aiohttp logging.basicConfig(format='%(levelname)s:%(message)s', filename='example.log', filemode='w', level=logging.INFO) +db=SessionLocal() + URLS = [ "https://python.org", "https://google.com", @@ -20,6 +23,7 @@ URLS = [ 'https://testdotya.dotya.ml', "https://ubuntu.com", ] +URL = crud.get_urls(db=db) def start_background_loop(loop: asyncio.AbstractEventLoop) -> None: asyncio.set_event_loop(loop) @@ -28,6 +32,7 @@ def start_background_loop(loop: asyncio.AbstractEventLoop) -> None: async def fetch(url: str, session: aiohttp.ClientSession = None) -> Tuple[str, str]: async def _fetch(url: str, session: aiohttp.ClientSession): + URL = crud.get_urls(db=db) s = time.time() async with session.head(url) as response: f = time.time() - s @@ -45,7 +50,7 @@ async def fetch(url: str, session: aiohttp.ClientSession = None) -> Tuple[str, s async def fetch_urls(loop: asyncio.AbstractEventLoop) -> Sequence[Tuple[str, str]]: async with aiohttp.ClientSession() as session: - tasks = [loop.create_task(fetch(url, session)) for url in URLS] + tasks = [loop.create_task(fetch(url, session)) for url in URL] results = await asyncio.gather(*tasks) return results diff --git a/nurun.sh b/nurun.sh index 742155a..0bad1d0 100644 --- a/nurun.sh +++ b/nurun.sh @@ -2,4 +2,6 @@ celery worker -A app.celery --loglevel=info & sleep 5 -python -m app.run_tasks & + +python -m app.run_tasks +