diff --git a/README.md b/README.md index 64b0cdb..76a98dc 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,27 @@ # Argos monitoring -Argos is an HTTP monitoring service. It allows you to define a list of websites to monitor, and a list of checks to run on these websites. It will then run these checks periodically, and alert you if something goes wrong. +An HTTP monitoring service. -See the online documentation at http://framasoft.frama.io/framaspace/argos +1. Define a list of websites to monitor +2. Specify a list of checks to run on these websites. +3. Argos will run the checks periodically and alert you if something goes wrong. -Todo: +Internally, a HTTP API is exposed, and a job queue is used to distribute the checks to the agents. + +- [Online documentation](http://framasoft.frama.io/framaspace/argos) +- [Issue tracker](https://framagit.org/framasoft/framaspace/argos/-/issues) + +## Resquirements + +- **Python**: 3.11+ +- **Backends**: SQLite (development), PostgreSQL 14+ (production) + +## Todo: -- [ ] Cleandb should keep max number of results by task - [ ] Do not return empty list on / when no results from agents. - [ ] Last seen agents - [ ] donner un aperçu rapide de l’état de la supervision. +- [ ] Allow passing a dict to check - [ ] Rename error in unexpected error - [ ] Use background tasks for alerting - [ ] Delete outdated tasks from config diff --git a/argos/commands.py b/argos/commands.py index a3acf3a..71ba697 100644 --- a/argos/commands.py +++ b/argos/commands.py @@ -64,13 +64,13 @@ def start(host, port, reload, log_config): @server.command() -@click.option("--max-results", default=100, help="Maximum number of results to keep") +@click.option("--max-results", default=100, help="Number of results per tasks to keep") @click.option( "--max-lock-seconds", default=100, help="The number of seconds after which a lock is considered stale", ) -def clean(max_results, max_lock_seconds): +def cleandb(max_results, max_lock_seconds): """Clean the database (to run routinely) - Removes old results from the database. diff --git a/argos/server/queries.py b/argos/server/queries.py index e309c86..266186d 100644 --- a/argos/server/queries.py +++ b/argos/server/queries.py @@ -117,16 +117,27 @@ async def get_severity_counts(db: Session): async def remove_old_results(db: Session, max_results: int): - # Get the id of the oldest result to keep, then delete all results older than that - subquery = ( - db.query(Result.id).order_by(desc(Result.id)).limit(max_results).subquery() - ) - min_id = db.query(func.min(subquery.c.id)).scalar() - if min_id: - deleted = db.query(Result).where(Result.id < min_id).delete() - db.commit() - else: - deleted = 0 + tasks = db.query(Task).all() + deleted = 0 + for task in tasks: + # Get the id of the oldest result to keep + subquery = ( + db.query(Result.id) + .filter(Result.task_id == task.id) + .order_by(desc(Result.id)) + .limit(max_results) + .subquery() + ) + min_id = db.query(func.min(subquery.c.id)).scalar() + + # Delete all the results older than min_id + if min_id: + deleted += ( + db.query(Result) + .where(Result.id < min_id, Result.task_id == task.id) + .delete() + ) + db.commit() return deleted diff --git a/docs/cli.md b/docs/cli.md index cdfa659..6956233 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -102,7 +102,7 @@ Options: ### Server clean ```man diff --git a/tests/test_queries.py b/tests/test_queries.py index b52434c..1d9ccab 100644 --- a/tests/test_queries.py +++ b/tests/test_queries.py @@ -7,13 +7,28 @@ from argos.server.models import Result, Task @pytest.mark.asyncio -async def test_remove_old_results(db, ten_results): - assert db.query(Result).count() == 10 +async def test_remove_old_results(db, ten_tasks): + for task in ten_tasks: + for i in range(5): + result = Result( + submitted_at=datetime.now(), + status="success", + context={"foo": "bar"}, + task=task, + agent_id="test", + severity="ok", + ) + db.add(result) + db.commit() + + # So we have 5 results per tasks + assert db.query(Result).count() == 50 + # Keep only 2 deleted = await queries.remove_old_results(db, 2) - assert deleted == 8 - assert db.query(Result).count() == 2 - # We should keep the last two results - assert db.query(Result).all() == ten_results[-2:] + assert deleted == 30 + assert db.query(Result).count() == 20 + for task in ten_tasks: + assert db.query(Result).filter(Result.task == task).count() == 2 @pytest.mark.asyncio