diff --git a/src/haiku/rag/cli.py b/src/haiku/rag/cli.py index efa5dbe5..45dca2f6 100644 --- a/src/haiku/rag/cli.py +++ b/src/haiku/rag/cli.py @@ -8,6 +8,7 @@ from rich.console import Console from haiku.rag.app import HaikuRAGApp from haiku.rag.config import Config +from haiku.rag.logging import configure_cli_logging from haiku.rag.migration import migrate_sqlite_to_lancedb from haiku.rag.utils import is_up_to_date @@ -49,6 +50,8 @@ def main( ), ): """haiku.rag CLI - Vector database RAG system""" + # Ensure only haiku.rag logs are emitted in CLI context + configure_cli_logging() # Run version check before any command asyncio.run(check_version()) diff --git a/src/haiku/rag/logging.py b/src/haiku/rag/logging.py index 34aeaf5a..3c5202e9 100644 --- a/src/haiku/rag/logging.py +++ b/src/haiku/rag/logging.py @@ -3,13 +3,9 @@ import logging from rich.console import Console from rich.logging import RichHandler -logging.basicConfig(level=logging.DEBUG) -logging.getLogger("httpx").setLevel(logging.WARNING) -logging.getLogger("httpcore").setLevel(logging.WARNING) -logging.getLogger("docling").setLevel(logging.WARNING) - def get_logger() -> logging.Logger: + """Return the library logger configured with a Rich handler.""" logger = logging.getLogger("haiku.rag") handler = RichHandler( @@ -19,11 +15,39 @@ def get_logger() -> logging.Logger: formatter = logging.Formatter("%(message)s") handler.setFormatter(formatter) - logger.setLevel("INFO") + logger.setLevel(logging.INFO) # Remove any existing handlers to avoid duplicates on reconfiguration for hdlr in logger.handlers[:]: logger.removeHandler(hdlr) logger.addHandler(handler) + # Do not let messages propagate to the root logger + logger.propagate = False + return logger + + +def configure_cli_logging(level: int = logging.INFO) -> logging.Logger: + """Configure logging for CLI runs. + + - Silence ALL non-haiku.rag loggers by detaching root handlers and setting + their level to ERROR. + - Attach a Rich handler only to the "haiku.rag" logger. + - Prevent propagation so only our logger prints in the CLI. + """ + # Silence root logger completely + root = logging.getLogger() + for hdlr in root.handlers[:]: + root.removeHandler(hdlr) + root.setLevel(logging.ERROR) + + # Optionally silence some commonly noisy libraries explicitly as a safeguard + for noisy in ("httpx", "httpcore", "docling", "urllib3", "asyncio"): + logging.getLogger(noisy).setLevel(logging.ERROR) + logging.getLogger(noisy).propagate = False + + # Configure and return our app logger + logger = get_logger() + logger.setLevel(level) + logger.propagate = False return logger