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