(feature) Summarize backup trends in the Django UI

Add a stats summary layer that aggregates recent successful real backup runs
into dashboard and host-level trend metrics.

Show backup-root usage, available space, average new data, average duration,
estimated runs until full, and link-dest savings on the dashboard. Add a host
trend table with recent run duration, file count, new data, matched data, and
snapshot links.

Keep the implementation based on existing run and snapshot stats JSON so the
UI gains useful trend visibility without introducing a schema migration yet.
This commit is contained in:
2026-05-19 22:31:24 +02:00
parent 6940dc55b7
commit fc22842fc4
5 changed files with 298 additions and 3 deletions

View File

@@ -34,10 +34,12 @@ from .retention import run_sql_retention_apply, run_sql_retention_plan
from .self_check import collect_self_checks, summarize_self_checks
from .snapshot_discovery import discover_snapshots, inspect_snapshot_discovery
from .ssh_keys import SshKeyError, delete_generated_key_files, generate_ssh_key, merge_known_hosts, scan_known_host
from .stats_summary import collect_dashboard_stats, collect_host_stats
@staff_member_required
def dashboard(request):
global_config = GlobalConfig.objects.filter(name="default").first()
hosts = list(
HostConfig.objects.annotate(snapshot_count=Count("snapshots", distinct=True), run_count=Count("runs", distinct=True))
.order_by("host")
@@ -48,9 +50,11 @@ def dashboard(request):
.order_by("-started_at", "-discovered_at", "-id")
.first()
)
stats_summary = collect_dashboard_stats(hosts=hosts, global_config=global_config)
context = {
"hosts": hosts,
"global_config": GlobalConfig.objects.filter(name="default").first(),
"global_config": global_config,
"stats_summary": stats_summary,
"latest_runs": BackupRun.objects.select_related("host", "snapshot").order_by("-created_at")[:10],
"counts": {
"global_configs": GlobalConfig.objects.count(),
@@ -258,12 +262,14 @@ def host_detail(request, host: str):
).order_by("created_at", "id").first()
has_global_config = GlobalConfig.objects.filter(name="default").exists()
host_checks = collect_host_checks(host_config)
stats_summary = collect_host_stats(host=host_config, limit=10)
context = {
"host": host_config,
"schedule": _schedule_for_host(host_config),
"discovery": inspect_snapshot_discovery(host=host_config),
"host_checks": host_checks,
"host_check_summary": summarize_self_checks(host_checks),
"stats_summary": stats_summary,
"manual_backup_form": ManualBackupForm(initial=_default_manual_backup_initial(host_config)),
"can_queue_backup": host_config.enabled and has_global_config,
"has_global_config": has_global_config,