refactor: enhance error handling with structured logging across multiple modules
- Updated various modules including cli.py, run_agent.py, gateway, and tools to replace silent exception handling with structured logging. - Improved error messages to provide more context, aiding in debugging and monitoring. - Ensured consistent logging practices throughout the codebase, enhancing traceability and maintainability.
This commit is contained in:
parent
cbff1b818c
commit
748fd3db88
14 changed files with 134 additions and 110 deletions
|
|
@ -31,6 +31,8 @@ import uuid
|
|||
from typing import Any, Dict, List, Optional
|
||||
|
||||
# Availability gate: UDS requires a POSIX OS
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
SANDBOX_AVAILABLE = sys.platform != "win32"
|
||||
|
||||
# The 7 tools allowed inside the sandbox. The intersection of this list
|
||||
|
|
@ -488,8 +490,8 @@ def execute_code(
|
|||
try:
|
||||
import shutil
|
||||
shutil.rmtree(tmpdir, ignore_errors=True)
|
||||
except Exception:
|
||||
pass
|
||||
except Exception as e:
|
||||
logger.debug("Could not clean temp dir: %s", e)
|
||||
try:
|
||||
os.unlink(sock_path)
|
||||
except OSError:
|
||||
|
|
@ -503,8 +505,8 @@ def _kill_process_group(proc, escalate: bool = False):
|
|||
except (ProcessLookupError, PermissionError):
|
||||
try:
|
||||
proc.kill()
|
||||
except Exception:
|
||||
pass
|
||||
except Exception as e:
|
||||
logger.debug("Could not kill process: %s", e)
|
||||
|
||||
if escalate:
|
||||
# Give the process 5s to exit after SIGTERM, then SIGKILL
|
||||
|
|
@ -516,8 +518,8 @@ def _kill_process_group(proc, escalate: bool = False):
|
|||
except (ProcessLookupError, PermissionError):
|
||||
try:
|
||||
proc.kill()
|
||||
except Exception:
|
||||
pass
|
||||
except Exception as e:
|
||||
logger.debug("Could not kill process: %s", e)
|
||||
|
||||
|
||||
def _load_config() -> dict:
|
||||
|
|
|
|||
|
|
@ -277,14 +277,14 @@ class ProcessRegistry:
|
|||
session.output_buffer += chunk
|
||||
if len(session.output_buffer) > session.max_output_chars:
|
||||
session.output_buffer = session.output_buffer[-session.max_output_chars:]
|
||||
except Exception:
|
||||
pass
|
||||
except Exception as e:
|
||||
logger.debug("Process stdout reader ended: %s", e)
|
||||
|
||||
# Process exited
|
||||
try:
|
||||
session.process.wait(timeout=5)
|
||||
except Exception:
|
||||
pass
|
||||
except Exception as e:
|
||||
logger.debug("Process wait timed out or failed: %s", e)
|
||||
session.exited = True
|
||||
session.exit_code = session.process.returncode
|
||||
self._move_to_finished(session)
|
||||
|
|
@ -351,14 +351,14 @@ class ProcessRegistry:
|
|||
break
|
||||
except Exception:
|
||||
break
|
||||
except Exception:
|
||||
pass
|
||||
except Exception as e:
|
||||
logger.debug("PTY stdout reader ended: %s", e)
|
||||
|
||||
# Process exited
|
||||
try:
|
||||
pty.wait()
|
||||
except Exception:
|
||||
pass
|
||||
except Exception as e:
|
||||
logger.debug("PTY wait timed out or failed: %s", e)
|
||||
session.exited = True
|
||||
session.exit_code = pty.exitstatus if hasattr(pty, 'exitstatus') else -1
|
||||
self._move_to_finished(session)
|
||||
|
|
@ -719,8 +719,8 @@ class ProcessRegistry:
|
|||
# Clear the checkpoint (will be rewritten as processes finish)
|
||||
try:
|
||||
CHECKPOINT_PATH.write_text("[]", encoding="utf-8")
|
||||
except Exception:
|
||||
pass
|
||||
except Exception as e:
|
||||
logger.debug("Could not write checkpoint file: %s", e)
|
||||
|
||||
return recovered
|
||||
|
||||
|
|
|
|||
|
|
@ -154,8 +154,8 @@ class GitHubAuth:
|
|||
)
|
||||
if result.returncode == 0 and result.stdout.strip():
|
||||
return result.stdout.strip()
|
||||
except (FileNotFoundError, subprocess.TimeoutExpired):
|
||||
pass
|
||||
except (FileNotFoundError, subprocess.TimeoutExpired) as e:
|
||||
logger.debug("gh CLI token lookup failed: %s", e)
|
||||
return None
|
||||
|
||||
def _try_github_app(self) -> Optional[str]:
|
||||
|
|
@ -438,8 +438,8 @@ class GitHubSource(SkillSource):
|
|||
)
|
||||
if resp.status_code == 200:
|
||||
return resp.text
|
||||
except httpx.HTTPError:
|
||||
pass
|
||||
except httpx.HTTPError as e:
|
||||
logger.debug("GitHub contents API fetch failed: %s", e)
|
||||
return None
|
||||
|
||||
def _read_cache(self, key: str) -> Optional[list]:
|
||||
|
|
@ -461,8 +461,8 @@ class GitHubSource(SkillSource):
|
|||
cache_file = INDEX_CACHE_DIR / f"{key}.json"
|
||||
try:
|
||||
cache_file.write_text(json.dumps(data, ensure_ascii=False))
|
||||
except OSError:
|
||||
pass
|
||||
except OSError as e:
|
||||
logger.debug("Could not write cache: %s", e)
|
||||
|
||||
@staticmethod
|
||||
def _meta_to_dict(meta: SkillMeta) -> dict:
|
||||
|
|
@ -826,8 +826,8 @@ class LobeHubSource(SkillSource):
|
|||
resp = httpx.get(url, timeout=15)
|
||||
if resp.status_code == 200:
|
||||
return resp.json()
|
||||
except (httpx.HTTPError, json.JSONDecodeError):
|
||||
pass
|
||||
except (httpx.HTTPError, json.JSONDecodeError) as e:
|
||||
logger.debug("LobeHub agent fetch failed: %s", e)
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
|
|
@ -890,8 +890,8 @@ def _write_index_cache(key: str, data: Any) -> None:
|
|||
cache_file = INDEX_CACHE_DIR / f"{key}.json"
|
||||
try:
|
||||
cache_file.write_text(json.dumps(data, ensure_ascii=False, default=str))
|
||||
except OSError:
|
||||
pass
|
||||
except OSError as e:
|
||||
logger.debug("Could not write cache: %s", e)
|
||||
|
||||
|
||||
def _skill_meta_to_dict(meta: SkillMeta) -> dict:
|
||||
|
|
@ -1037,8 +1037,8 @@ def append_audit_log(action: str, skill_name: str, source: str,
|
|||
try:
|
||||
with open(AUDIT_LOG, "a") as f:
|
||||
f.write(line)
|
||||
except OSError:
|
||||
pass
|
||||
except OSError as e:
|
||||
logger.debug("Could not write audit log: %s", e)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -13,11 +13,14 @@ newline-delimited list of skill names that have been offered to the user.
|
|||
"""
|
||||
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
from typing import List, Tuple
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
HERMES_HOME = Path(os.getenv("HERMES_HOME", Path.home() / ".hermes"))
|
||||
SKILLS_DIR = HERMES_HOME / "skills"
|
||||
|
|
@ -131,8 +134,8 @@ def sync_skills(quiet: bool = False) -> dict:
|
|||
try:
|
||||
dest_desc.parent.mkdir(parents=True, exist_ok=True)
|
||||
shutil.copy2(desc_md, dest_desc)
|
||||
except (OSError, IOError):
|
||||
pass
|
||||
except (OSError, IOError) as e:
|
||||
logger.debug("Could not copy %s: %s", desc_md, e)
|
||||
|
||||
_write_manifest(manifest)
|
||||
|
||||
|
|
|
|||
|
|
@ -122,8 +122,8 @@ def _convert_to_opus(mp3_path: str) -> Optional[str]:
|
|||
)
|
||||
if os.path.exists(ogg_path) and os.path.getsize(ogg_path) > 0:
|
||||
return ogg_path
|
||||
except Exception:
|
||||
pass
|
||||
except Exception as e:
|
||||
logger.warning("ffmpeg OGG conversion failed: %s", e)
|
||||
return None
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue