v0.5.0: Backup bugfixes + monitoring page with metrics store

- Fix "Helyi mentés" showing "–" after controller restart by synthesizing
  LastBackup from snapshot history and LastDBDump from dump files on disk
- New monitoring page (/monitoring) with system info, metrics charts, and
  container resource overview
- SQLite metrics store (modernc.org/sqlite, pure Go, no CGO) with 60s
  collection interval and 30-day auto-prune
- REST API endpoints: /api/metrics/system, /api/metrics/containers/summary,
  /api/metrics/containers/{name}, /api/metrics/sysinfo
- Chart.js 4.4.7 embedded locally for offline environments
- System info provider reads hostname, OS, kernel, CPU, uptime from /proc
- Docker compose updated with /etc/os-release host mount

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-16 10:14:46 +01:00
parent 87e79548b0
commit 3e8baebfa5
19 changed files with 1691 additions and 5 deletions
+122
View File
@@ -1477,6 +1477,125 @@ a.stat-card:hover {
font-size: .8rem;
}
/* --- Monitoring page --- */
.monitor-card {
background: var(--bg-card);
border-radius: var(--radius);
padding: 1.25rem;
border: 1px solid var(--border-color);
margin-bottom: 1.5rem;
}
.monitor-card h3 {
margin-bottom: .75rem;
}
.monitor-card-header {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 1rem;
flex-wrap: wrap;
}
.monitor-card-header h3 {
margin-bottom: 0;
flex: 1;
min-width: 150px;
}
.time-range-bar {
display: flex;
gap: .35rem;
}
.sysinfo-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: .5rem;
}
.sysinfo-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: .35rem .5rem;
border-bottom: 1px solid rgba(48, 54, 61, 0.3);
font-size: .9rem;
}
.sysinfo-row:last-child { border-bottom: none; }
.sysinfo-label {
color: var(--text-secondary);
font-weight: 500;
}
.sysinfo-value {
color: var(--text-primary);
font-family: 'JetBrains Mono', monospace;
font-size: .85rem;
}
.charts-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
}
.charts-grid-2 {
grid-template-columns: 1fr 1fr;
}
.chart-box {
background: var(--bg-secondary);
border-radius: 8px;
padding: .75rem;
border: 1px solid rgba(48, 54, 61, 0.5);
}
.chart-box-half {
flex: 1;
min-width: 0;
}
.chart-title {
font-size: .8rem;
font-weight: 600;
color: var(--text-secondary);
margin-bottom: .5rem;
text-transform: uppercase;
letter-spacing: .3px;
}
.chart-wrap {
position: relative;
height: 180px;
}
.chart-wrap-bar {
position: relative;
height: 250px;
}
.container-charts-row {
display: flex;
gap: 1rem;
}
.chart-empty {
text-align: center;
padding: 2rem;
color: var(--text-muted);
font-size: .9rem;
}
.storage-bars {
display: flex;
flex-direction: column;
gap: 1rem;
}
.storage-item {
padding: .25rem 0;
}
.storage-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: .4rem;
}
.storage-label {
font-size: .85rem;
font-weight: 600;
color: var(--text-secondary);
}
.storage-value {
font-size: .8rem;
color: var(--text-muted);
font-family: 'JetBrains Mono', monospace;
}
/* Responsive */
@media(max-width: 768px) {
.sidebar { width: 100%; height: auto; position: relative; border-right: none; border-bottom: 1px solid var(--border-color); }
@@ -1491,4 +1610,7 @@ a.stat-card:hover {
.stats-grid { grid-template-columns: repeat(3, 1fr); }
.deploy-info { flex-direction: column; }
.system-info-items { flex-direction: column; gap: 1rem; }
.charts-grid { grid-template-columns: 1fr; }
.container-charts-row { flex-direction: column; }
.sysinfo-grid { grid-template-columns: 1fr; }
}