fix: persist dashboard metrics and count versions instead of repos

Metrics (downloads, uploads, cache hits) were stored in-memory only
and reset to zero on every restart. Now they persist to metrics.json
in the storage directory with:
- Load on startup from {storage_path}/metrics.json
- Background save every 30 seconds
- Final save on graceful shutdown
- Atomic writes (tmp + rename) to prevent corruption

Artifact count on dashboard now shows total tags/versions across
all registries instead of just counting unique repository names.
This matches user expectations when pushing multiple tags to the
same image (e.g. myapp:v1, myapp:v2 now shows 2, not 1).
This commit is contained in:
2026-03-13 15:43:03 +00:00
parent b80c7c5160
commit 61de6c6ddd
3 changed files with 119 additions and 11 deletions

View File

@@ -336,7 +336,7 @@ async fn run_server(config: Config, storage: Storage) {
start_time,
auth,
tokens,
metrics: DashboardMetrics::new(),
metrics: DashboardMetrics::with_persistence(&storage_path),
activity: ActivityLog::new(50),
audit: AuditLog::new(&storage_path),
docker_auth,
@@ -387,6 +387,16 @@ async fn run_server(config: Config, storage: Storage) {
"Available endpoints"
);
// Background task: persist metrics every 30 seconds
let metrics_state = state.clone();
tokio::spawn(async move {
let mut interval = tokio::time::interval(std::time::Duration::from_secs(30));
loop {
interval.tick().await;
metrics_state.metrics.save();
}
});
// Graceful shutdown on SIGTERM/SIGINT
axum::serve(
listener,
@@ -396,6 +406,9 @@ async fn run_server(config: Config, storage: Storage) {
.await
.expect("Server error");
// Save metrics on shutdown
state.metrics.save();
info!(
uptime_seconds = state.start_time.elapsed().as_secs(),
"Nora shutdown complete"