Files
ProductionDataBaseSync_Data…/src/sync/logging_setup.py
Misaka_Company 3a3d3d0292 feat: cleanup phase and main service loop with error isolation
Wires capture -> apply -> cleanup into cycle(cfg): per-file capture and
cleanup each wrapped in try/except + log.exception so one file's failure
does not abort the cycle; apply failure does not block cleanup; writer is
always closed in finally. run(cfg) loops cycle with sleep; main() loads
config from argv. logging_setup uses RotatingFileHandler 10MBx5 + console.

Unit tests cover all three error-isolation branches via mocks (no real
end-to-end smoke; integration deferred to Task 9 pilot).

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-14 12:39:22 +08:00

31 lines
1.2 KiB
Python

"""Logging configuration for the sync service.
Configures the root logger with a RotatingFileHandler (10 MB x 5, UTF-8) plus
a console StreamHandler. The level and log path come from ``cfg.logging``.
"""
import logging
import logging.handlers
import os
def setup_logging(cfg_dict: dict | None):
"""Configure root logging from the ``cfg.logging`` dict.
``cfg_dict`` is ``SyncConfig.logging`` (a dict or None). ``level`` is a
logging-level name string (default ``"INFO"``); ``path`` is the log file
path (default ``"sync.log"``). The parent directory is created if missing.
"""
level = getattr(logging, (cfg_dict or {}).get("level", "INFO")) if cfg_dict else logging.INFO
path = (cfg_dict or {}).get("path", "sync.log")
os.makedirs(os.path.dirname(path) or ".", exist_ok=True)
h = logging.handlers.RotatingFileHandler(
path, maxBytes=10 * 1024 * 1024, backupCount=5, encoding="utf-8"
)
h.setFormatter(logging.Formatter("%(asctime)s %(levelname)s [%(name)s] %(message)s"))
root = logging.getLogger()
root.setLevel(level)
root.addHandler(h)
sh = logging.StreamHandler()
sh.setFormatter(logging.Formatter("%(levelname)s %(message)s"))
root.addHandler(sh)