mirror of
https://github.com/lllin000/PaperForge.git
synced 2026-07-22 06:50:53 +00:00
69 lines
2.4 KiB
Python
69 lines
2.4 KiB
Python
"""PaperForge — logging configuration single entry point.
|
|
|
|
Call ``configure_logging(verbose)`` once at CLI startup before command dispatch.
|
|
All worker and command modules use ``logging.getLogger(__name__)`` for
|
|
diagnostic/trace/error output.
|
|
|
|
Environment:
|
|
PAPERFORGE_LOG_LEVEL — default log level (DEBUG/INFO/WARNING/ERROR).
|
|
Invalid values silently fall back to WARNING.
|
|
"""
|
|
|
|
import logging
|
|
import os
|
|
import sys
|
|
|
|
|
|
def configure_logging(verbose: bool = False) -> None:
|
|
"""Configure the root ``paperforge`` logger.
|
|
|
|
Sets up a StreamHandler writing to stderr with a ``LEVEL:name:message``
|
|
format string. Idempotent — does nothing if handlers are already
|
|
configured (guards against double ``basicConfig()`` or ``dictConfig()``).
|
|
|
|
Args:
|
|
verbose: If True, forces ``DEBUG`` level regardless of env var.
|
|
"""
|
|
logger = logging.getLogger("paperforge")
|
|
|
|
# Idempotency guard: if handlers already exist, only adjust level.
|
|
# This prevents duplicate log lines from multiple configure_logging calls.
|
|
if logger.handlers:
|
|
if verbose:
|
|
logger.setLevel(logging.DEBUG)
|
|
return
|
|
|
|
# Resolve log level from environment or default
|
|
level_name = os.environ.get("PAPERFORGE_LOG_LEVEL", "INFO").strip().upper()
|
|
level = getattr(logging, level_name, None)
|
|
if not isinstance(level, int) or level_name not in ("DEBUG", "INFO", "WARNING", "ERROR"):
|
|
level = logging.WARNING
|
|
|
|
if verbose:
|
|
level = logging.DEBUG
|
|
|
|
logger.setLevel(level)
|
|
|
|
handler = logging.StreamHandler(stream=sys.stderr)
|
|
handler.setLevel(logging.DEBUG) # handler-level always DEBUG; logger controls filtering
|
|
formatter = logging.Formatter(
|
|
fmt="%(levelname)s:%(name)s:%(message)s",
|
|
datefmt="%H:%M:%S",
|
|
)
|
|
handler.setFormatter(formatter)
|
|
logger.addHandler(handler)
|
|
|
|
|
|
def get_paperforge_logger() -> logging.Logger:
|
|
"""Convenience accessor for the ``paperforge`` logger.
|
|
|
|
Equivalent to ``logging.getLogger("paperforge")`` but provides a single
|
|
well-known reference point for early-boot logging before
|
|
``configure_logging()`` has been called.
|
|
|
|
Callers in worker/command modules should still prefer the per-module
|
|
``logger = logging.getLogger(__name__)`` pattern. This function exists
|
|
for places (like ``cli.py:main()``) that need the root logger before
|
|
per-module loggers are established.
|
|
"""
|
|
return logging.getLogger("paperforge")
|