# retoor 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}