feat: add dashboard health actions

This commit is contained in:
Lan
2026-06-03 06:15:15 +08:00
parent aa64359466
commit 12263e3398
2 changed files with 52 additions and 23 deletions
+48 -22
View File
@@ -159,22 +159,13 @@ class FileService:
"textCount": 0, "textCount": 0,
"fileCount": 0, "fileCount": 0,
"chunkedCount": 0, "chunkedCount": 0,
"healthAttentionCount": 0, **self._empty_health_summary(),
"healthDangerCount": 0,
"healthWarningCount": 0,
"expiringSoonCount": 0,
"storageIssueCount": 0,
"neverRetrievedCount": 0,
"storageUsed": sum(file_code.size for file_code in all_files), "storageUsed": sum(file_code.size for file_code in all_files),
"usedCount": sum(file_code.used_count for file_code in all_files), "usedCount": sum(file_code.used_count for file_code in all_files),
} }
for file_code in all_files: for file_code in all_files:
item = await self._build_admin_file_item(file_code, now=now) item = await self._build_admin_file_item(file_code, now=now)
status_insights = item["statusInsights"]
reasons = status_insights["reasons"]
severity = status_insights["severity"]
if item["isExpired"]: if item["isExpired"]:
summary["expiredCount"] += 1 summary["expiredCount"] += 1
else: else:
@@ -185,18 +176,7 @@ class FileService:
summary["fileCount"] += 1 summary["fileCount"] += 1
if item["isChunked"]: if item["isChunked"]:
summary["chunkedCount"] += 1 summary["chunkedCount"] += 1
if severity in {"danger", "warning"}: self._accumulate_health_summary(summary, item)
summary["healthAttentionCount"] += 1
if severity == "danger":
summary["healthDangerCount"] += 1
if severity == "warning":
summary["healthWarningCount"] += 1
if "expires_soon" in reasons:
summary["expiringSoonCount"] += 1
if "storage_metadata_incomplete" in reasons:
summary["storageIssueCount"] += 1
if "never_retrieved" in reasons:
summary["neverRetrievedCount"] += 1
if not self._match_admin_file(item, keyword, status, file_type, health): if not self._match_admin_file(item, keyword, status, file_type, health):
continue continue
@@ -209,6 +189,52 @@ class FileService:
offset = (page - 1) * size offset = (page - 1) * size
return enriched_files[offset : offset + size], len(enriched_files), summary return enriched_files[offset : offset + size], len(enriched_files), summary
def _empty_health_summary(self) -> dict[str, int]:
return {
"healthAttentionCount": 0,
"healthDangerCount": 0,
"healthWarningCount": 0,
"expiringSoonCount": 0,
"storageIssueCount": 0,
"neverRetrievedCount": 0,
"healthyCount": 0,
"permanentCount": 0,
}
def _accumulate_health_summary(self, summary: dict[str, Any], item: dict[str, Any]) -> None:
status_insights = item.get("statusInsights") or {}
reasons = status_insights.get("reasons") or []
severity = status_insights.get("severity")
state = status_insights.get("state")
if severity in {"danger", "warning"}:
summary["healthAttentionCount"] += 1
if severity == "danger":
summary["healthDangerCount"] += 1
if severity == "warning":
summary["healthWarningCount"] += 1
if severity == "success":
summary["healthyCount"] += 1
if state == "permanent":
summary["permanentCount"] += 1
if "expires_soon" in reasons:
summary["expiringSoonCount"] += 1
if "storage_metadata_incomplete" in reasons:
summary["storageIssueCount"] += 1
if "never_retrieved" in reasons:
summary["neverRetrievedCount"] += 1
async def build_file_health_summary(
self, file_codes: list[FileCodes], now: Optional[datetime] = None
) -> dict[str, int]:
if now is None:
now = await get_now()
summary = self._empty_health_summary()
for file_code in file_codes:
item = await self._build_admin_file_item(file_code, now=now)
self._accumulate_health_summary(summary, item)
return summary
async def _build_admin_file_item( async def _build_admin_file_item(
self, file_code: FileCodes, now: Optional[datetime] = None self, file_code: FileCodes, now: Optional[datetime] = None
) -> dict[str, Any]: ) -> dict[str, Any]:
+4 -1
View File
@@ -72,7 +72,7 @@ async def build_dashboard_recent_file(file_code: FileCodes) -> dict:
@admin_api.get("/dashboard") @admin_api.get("/dashboard")
async def dashboard(): async def dashboard(file_service: FileService = Depends(get_file_service)):
all_codes = await FileCodes.all() all_codes = await FileCodes.all()
all_size = sum([code.size for code in all_codes]) all_size = sum([code.size for code in all_codes])
sys_start = await KeyValue.filter(key="sys_start").first() sys_start = await KeyValue.filter(key="sys_start").first()
@@ -90,6 +90,7 @@ async def dashboard():
for file_code in all_codes: for file_code in all_codes:
if await file_code.is_expired(): if await file_code.is_expired():
expired_count += 1 expired_count += 1
health_summary = await file_service.build_file_health_summary(all_codes, now=now)
text_count = sum(1 for file_code in all_codes if file_code.text is not None) text_count = sum(1 for file_code in all_codes if file_code.text is not None)
chunked_count = sum(1 for file_code in all_codes if file_code.is_chunked) chunked_count = sum(1 for file_code in all_codes if file_code.is_chunked)
@@ -125,6 +126,8 @@ async def dashboard():
"openUpload": settings.openUpload, "openUpload": settings.openUpload,
"enableChunk": settings.enableChunk, "enableChunk": settings.enableChunk,
"maxSaveSeconds": settings.max_save_seconds, "maxSaveSeconds": settings.max_save_seconds,
**health_summary,
"healthSummary": health_summary,
"topSuffixes": [ "topSuffixes": [
{"suffix": suffix, "count": count} {"suffix": suffix, "count": count}
for suffix, count in suffix_counter.most_common(8) for suffix, count in suffix_counter.most_common(8)