| """ |
| Centralized logging setup. |
| |
| Every module does `from logs.logger import get_logger` and |
| `logger = get_logger(__name__)` rather than configuring logging itself. |
| Writes to both console and logs/app.log (paths from config.py). |
| """ |
|
|
| import logging |
| import os |
| import sys |
|
|
| import config |
|
|
| _CONFIGURED = False |
|
|
|
|
| def _configure_root(): |
| global _CONFIGURED |
| if _CONFIGURED: |
| return |
|
|
| os.makedirs(config.LOG_DIR, exist_ok=True) |
|
|
| root = logging.getLogger("dsa_chatbot") |
| root.setLevel(config.LOG_LEVEL) |
| root.propagate = False |
|
|
| formatter = logging.Formatter( |
| "%(asctime)s | %(levelname)-8s | %(name)s | %(message)s" |
| ) |
|
|
| if not root.handlers: |
| stream_handler = logging.StreamHandler(sys.stdout) |
| stream_handler.setFormatter(formatter) |
| root.addHandler(stream_handler) |
|
|
| file_handler = logging.FileHandler(config.LOG_FILE_PATH, encoding="utf-8") |
| file_handler.setFormatter(formatter) |
| root.addHandler(file_handler) |
|
|
| _CONFIGURED = True |
|
|
|
|
| def get_logger(name: str) -> logging.Logger: |
| """Returns a named logger nested under the shared 'dsa_chatbot' root.""" |
| _configure_root() |
| return logging.getLogger(f"dsa_chatbot.{name}") |
|
|