Fixed Issues with Log Management System

This commit is contained in:
2025-11-27 03:51:51 -07:00
parent 2655a06874
commit 04aafae90b
3 changed files with 56 additions and 4 deletions

View File

@@ -120,6 +120,8 @@ _QUIET_SERVICE_LOGS = {"scheduled_jobs"}
def _make_service_logger(base: Path, logger: logging.Logger) -> Callable[[str, str, Optional[str]], None]:
quiet_services = {name.strip().lower().replace("-", "_") for name in _QUIET_SERVICE_LOGS if name}
def _log(service: str, msg: str, scope: Optional[str] = None, *, level: str = "INFO") -> None:
level_upper = level.upper()
service_key = (service or "").strip().lower()
@@ -134,12 +136,13 @@ def _make_service_logger(base: Path, logger: logging.Logger) -> Callable[[str, s
prefix_parts.append(f"[CONTEXT-{resolved_scope}]")
prefix = "".join(prefix_parts)
with path.open("a", encoding="utf-8") as handle:
handle.write(f"[{timestamp}] {prefix} {msg}\\n")
handle.write(f"[{timestamp}] {prefix} {msg}\n")
except Exception:
logger.debug("Failed to write service log entry", exc_info=True)
numeric_level = getattr(logging, level_upper, logging.INFO)
if service_key not in _QUIET_SERVICE_LOGS:
suppress_engine_log = service_key in quiet_services or service_key.replace("-", "_") in quiet_services
if not suppress_engine_log:
logger.log(numeric_level, "[service:%s] %s", service, msg)
return _log

View File

@@ -203,6 +203,46 @@ class EngineLogManager:
files.append(entry)
return files
def _truncate_active_log(self, path: Path) -> bool:
"""Best-effort truncate for logs held open by logging handlers (Windows-safe)."""
resolved = path.resolve()
truncated = False
for logger_name in list(logging.root.manager.loggerDict.keys()) + [self.logger.name]:
try:
logger_obj = logging.getLogger(logger_name)
except Exception:
continue
handlers = list(getattr(logger_obj, "handlers", []))
for handler in handlers:
base = getattr(handler, "baseFilename", None)
if not base:
continue
try:
if Path(base).resolve() != resolved:
continue
except Exception:
continue
try:
handler.acquire()
stream = getattr(handler, "stream", None)
if stream:
stream.seek(0)
stream.truncate()
stream.flush()
else:
with resolved.open("w", encoding="utf-8"):
pass
truncated = True
except Exception:
self.logger.debug("Failed to truncate active log file: %s", path, exc_info=True)
finally:
try:
handler.release()
except Exception:
pass
return truncated
def apply_retention(self, retention: Mapping[str, int], default_days: int) -> List[str]:
deleted: List[str] = []
now = datetime.now(tz=timezone.utc)
@@ -306,7 +346,11 @@ class EngineLogManager:
def delete_file(self, filename: str) -> str:
path = self._resolve(filename)
path.unlink()
try:
path.unlink()
except PermissionError:
if not self._truncate_active_log(path):
raise
return filename
def delete_family(self, filename: str) -> List[str]:
@@ -320,6 +364,12 @@ class EngineLogManager:
entry.unlink()
except FileNotFoundError:
continue
except PermissionError:
handled = self._truncate_active_log(entry)
if handled:
deleted.append(entry.name)
else:
self.logger.debug("Failed to delete family log file (in use): %s", entry, exc_info=True)
except Exception:
self.logger.debug("Failed to delete family log file: %s", entry, exc_info=True)
else:

View File

@@ -322,7 +322,6 @@ const defaultColDef = useMemo(
setLogs(Array.isArray(data?.logs) ? data.logs : logs);
setEntries([]);
setEntriesMeta(null);
setActionMessage("Log files deleted.");
if (target) {
sendNotification(`Log "${target}" Deleted Successfully`);
}