Skip to content

feat(logging): per-module log filters and default to DEBUG log levels - #2477

Open
presentyourlove wants to merge 1 commit into
exo-explore:mainfrom
presentyourlove:feature/log-cleanup-per-module-filters
Open

presentyourlove wants to merge 1 commit into
exo-explore:mainfrom
presentyourlove:feature/log-cleanup-per-module-filters

Conversation

@presentyourlove

Copy link
Copy Markdown

Description

This PR implements official TODO item #27: "Log cleanup - per-module log filters and default to DEBUG log levels".

Background & Problem

Prior to this PR:

  1. Exo had a binary verbosity system (-q, default, -v). Setting -v (DEBUG) caused all modules—including high-frequency polling monitors (info_gatherer, macmon), network ping heartbeats, and low-level communication libraries—to spam the console and log files simultaneously.
  2. Developers investigating a specific component (e.g. exo.routing or exo.download) could not selectively enable debug messages for that module without getting overwhelmed by unrelated logs.
  3. Disk log files (EXO_LOG) only logged INFO by default unless -v was passed. In production or background service runs, crashes or unexpected node drops lacked crucial pre-crash debug context.
  4. Noisy third-party and background libraries (httpx, httpcore, urllib3, asyncio, anyio, zenoh, hpack) lacked centralized suppression.

Solution

This PR introduces per-module log filtering with hierarchical prefix matching, defaults file logging to DEBUG, and cleans up log spam:

  1. Module Log Filter Parsing (src/exo/shared/logging.py):

    • parse_module_log_filters(filter_str: str | None) -> dict[str, str]: Parses comma-separated module specifications (e.g. exo.routing=DEBUG,exo.master=INFO,exo.download=WARNING).
    • Supports case-insensitive levels, trims whitespace, and validates log level names against Loguru's valid levels.
  2. Hierarchical Log Filtering (src/exo/shared/logging.py):

    • create_module_log_filter(module_levels, base_level): Matches records against module prefixes.
    • Longest matching prefix wins: for instance, setting exo.routing=DEBUG and exo.routing.zenoh=WARNING enables DEBUG for exo.routing.router while suppressing verbose packets from exo.routing.zenoh.
    • Supports both static module names (record["name"]) and dynamically bound module contexts (record["extra"]["name"]).
  3. Default to DEBUG for File Logs:

    • logger_setup now defaults file_log_level to "DEBUG".
    • All critical debug diagnostics are persisted to disk log files by default, providing full forensic context if a background node fails or restarts.
  4. Third-Party Log Cleanup:

    • Suppresses noisy stdlib and external loggers (httpx, httpcore, urllib3, asyncio, anyio, zenoh, hpack) to WARNING.
  5. CLI & Environment Variable Configuration (src/exo/main.py):

    • Adds --log-modules option to exo CLI.
    • Automatically reads EXO_LOG_MODULES environment variable (e.g. export EXO_LOG_MODULES="exo.routing=DEBUG,exo.download=DEBUG").
    • Passed seamlessly into logger_setup.
  6. Automated Unit Tests (src/exo/shared/tests/test_module_logging.py):

    • Tests filter string parsing, whitespace tolerance, and invalid level discarding.
    • Tests hierarchical prefix matching, longest-prefix precedence, and fallback to base level.
    • Tests selective console output filtering.
    • Tests file logging default to DEBUG.
    • Tests CLI --log-modules argument and EXO_LOG_MODULES environment variable integration.

Verification

  • Unit Tests:
    .venv/Scripts/pytest.exe src/exo/shared/tests/test_console_verbosity.py src/exo/shared/tests/test_log_rotation.py src/exo/shared/tests/test_module_logging.py -v
    # 15 passed in 3.52s
  • Linting & Formatting:
    .venv/Scripts/ruff.exe check src/exo/shared/logging.py src/exo/shared/tests/test_module_logging.py
    .venv/Scripts/ruff.exe format --check ...
    # All checks passed!

Related Issues

  • Resolves: Item 27 in TODO.md ("Log cleanup - per-module log filters and default to DEBUG log levels")

- Add parse_module_log_filters to parse comma-separated module=LEVEL specifications
- Implement create_module_log_filter with hierarchical prefix matching for Loguru records
- Update file logging in logger_setup to default to DEBUG level for comprehensive diagnostic persistence
- Add --log-modules CLI argument in Args and respect EXO_LOG_MODULES environment variable
- Suppress noisy third-party loggers (httpx, httpcore, urllib3, asyncio, anyio, zenoh, hpack) to WARNING
- Add comprehensive automated unit tests in test_module_logging.py covering parsing, prefix matching, console output, file defaults, and CLI/ENV options
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant