fix: spurious health alerts, show rotated logs, clear history button

app.py:
- Alert logic now checks status.running (container up/down) instead of healthy
  (which requires connectivity tests) — services are only alerted when actually down
- Add POST /api/health/history/clear endpoint to reset history + alert counters

log_manager.py:
- get_all_log_file_infos: include rotated backup files (*.log.1, *.log.2 ...) in listing,
  marked with backup=true so UI can dim them and hide rotate button

api.js: add monitoringAPI.clearHealthHistory

Logs page:
- Health History: add Clear button with confirmation
- File panel: show full filename (including .log.1 backups), explain host path and naming,
  hide rotate button for backup files

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-21 03:05:04 -04:00
parent a5381b2ebc
commit 8e1814c7d2
4 changed files with 61 additions and 40 deletions
+21 -9
View File
@@ -134,24 +134,29 @@ function ApiServiceLogsTab() {
{/* File info panel */}
{showFiles && (
<div className="border rounded bg-gray-50 p-3">
<div className="flex justify-between items-center mb-2">
<span className="text-sm font-medium text-gray-700">Log Files (persisted to ./data/logs/)</span>
<div className="flex justify-between items-center mb-1">
<div>
<span className="text-sm font-medium text-gray-700">Log Files</span>
<span className="ml-2 text-xs text-gray-400">host path: <code>./data/logs/</code> rotated backups saved as <code>wireguard.log.1</code>, <code>wireguard.log.2</code> </span>
</div>
<button className="btn btn-secondary text-xs px-2 py-0.5" onClick={() => rotate(null)} disabled={rotating === 'all'}>
<RotateCcw className={`h-3 w-3 inline mr-1 ${rotating === 'all' ? 'animate-spin' : ''}`} />Rotate All
</button>
</div>
<table className="w-full text-xs">
<thead><tr className="text-gray-500"><th className="text-left py-1">Service</th><th className="text-right py-1">Size</th><th className="text-left py-1 pl-3">Modified</th><th className="text-center py-1"></th></tr></thead>
<thead><tr className="text-gray-500"><th className="text-left py-1">File</th><th className="text-right py-1">Size</th><th className="text-left py-1 pl-3">Modified</th><th className="text-center py-1"></th></tr></thead>
<tbody>
{fileInfos.map(f => (
<tr key={f.name} className="border-t">
<td className="py-1 font-mono">{f.name}</td>
<tr key={f.file} className={`border-t ${f.backup ? 'text-gray-400' : ''}`}>
<td className="py-1 font-mono">{f.file}</td>
<td className="py-1 text-right font-mono">{fmtSize(f.size)}</td>
<td className="py-1 pl-3 text-gray-500">{f.modified?.slice(0, 19)}</td>
<td className="py-1 text-center">
<button className="btn btn-secondary px-1.5 py-0.5 text-xs" onClick={() => rotate(f.name)} disabled={rotating === f.name}>
<RotateCcw className={`h-3 w-3 ${rotating === f.name ? 'animate-spin' : ''}`} />
</button>
{!f.backup && (
<button className="btn btn-secondary px-1.5 py-0.5 text-xs" onClick={() => rotate(f.name)} disabled={rotating === f.name}>
<RotateCcw className={`h-3 w-3 ${rotating === f.name ? 'animate-spin' : ''}`} />
</button>
)}
</td>
</tr>
))}
@@ -373,7 +378,14 @@ function HealthHistoryTab() {
<div className="space-y-4">
<div className="flex justify-between items-center">
<h3 className="text-lg font-medium text-gray-900">Health History</h3>
<button className="btn btn-secondary text-sm" onClick={load}><RefreshCw className="h-4 w-4 mr-1 inline" />Refresh</button>
<div className="flex gap-2">
<button className="btn btn-secondary text-sm" onClick={load}><RefreshCw className="h-4 w-4 mr-1 inline" />Refresh</button>
<button className="btn btn-secondary text-sm text-red-600" onClick={async () => {
if (!window.confirm('Clear all health history and reset alert counters?')) return;
await monitoringAPI.clearHealthHistory();
await load();
}}>Clear</button>
</div>
</div>
{loading ? <div className="text-gray-500 text-sm">Loading</div> : (
<div className="overflow-x-auto">