|
# retoor <retoor@molodetz.nl>
|
|
|
|
import logging
|
|
from datetime import datetime, timedelta, timezone
|
|
|
|
from devplacepy.database import get_int_setting
|
|
from devplacepy.services.base import BaseService, ConfigField
|
|
from devplacepy.services.audit import store
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
RETENTION_KEY = "audit_log_retention_days"
|
|
DEFAULT_RETENTION_DAYS = 90
|
|
|
|
|
|
class AuditService(BaseService):
|
|
title = "Audit retention"
|
|
description = "Prunes audit_log rows and their links older than the retention window."
|
|
default_enabled = True
|
|
min_interval = 3600
|
|
METRICS_SECONDS = 300
|
|
config_fields = [
|
|
ConfigField(
|
|
RETENTION_KEY,
|
|
"Retention (days)",
|
|
type="int",
|
|
default=DEFAULT_RETENTION_DAYS,
|
|
minimum=0,
|
|
help="Audit rows older than this are pruned. 0 disables pruning.",
|
|
group="General",
|
|
)
|
|
]
|
|
|
|
def __init__(self) -> None:
|
|
super().__init__("audit", interval_seconds=86400)
|
|
|
|
async def run_once(self) -> None:
|
|
days = get_int_setting(RETENTION_KEY, DEFAULT_RETENTION_DAYS)
|
|
if days <= 0:
|
|
self.log("Retention disabled (0 days); nothing pruned")
|
|
return
|
|
cutoff = (datetime.now(timezone.utc) - timedelta(days=days)).isoformat()
|
|
removed_links, removed_events = store.sweep(cutoff)
|
|
self.log(
|
|
f"Pruned {removed_events} audit rows and {removed_links} links older than {days}d"
|
|
)
|
|
|
|
def collect_metrics(self) -> dict:
|
|
from devplacepy.database import db
|
|
|
|
if store.AUDIT_TABLE not in db.tables:
|
|
return {"total_events": 0}
|
|
rows = list(db.query(f"SELECT COUNT(*) AS c FROM {store.AUDIT_TABLE}"))
|
|
return {"total_events": int(rows[0]["c"]) if rows else 0}
|