Spaces:
Sleeping
Sleeping
| # app/core/logging_config.py | |
| import logging | |
| import logging.config | |
| import sys | |
| import os # Added to potentially create log directory | |
| # Optional: Could make log level configurable via settings | |
| # from app.core.config import settings | |
| LOG_LEVEL = "INFO" # Default level (e.g., INFO, DEBUG, WARNING) | |
| # You could override this with an environment variable if needed: | |
| # LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO").upper() | |
| # Define the logging configuration dictionary | |
| LOGGING_CONFIG = { | |
| "version": 1, | |
| "disable_existing_loggers": False, # Let default loggers (like uvicorn) work | |
| "formatters": { | |
| "default": { | |
| # Example format: timestamp | level | logger_name | function:line | message | |
| "format": "%(asctime)s | %(levelname)-8s | %(name)-30s | %(funcName)s:%(lineno)d | %(message)s", | |
| "datefmt": "%Y-%m-%d %H:%M:%S", | |
| }, | |
| "simple": { | |
| "format": "%(levelname)-8s | %(name)-20s | %(message)s", | |
| }, | |
| }, | |
| "handlers": { | |
| # Handler for console output | |
| "console": { | |
| "class": "logging.StreamHandler", | |
| "formatter": "default", # Use the detailed default formatter | |
| "stream": sys.stdout, # Log to standard output | |
| }, | |
| # --- Example File Handler (Optional) --- | |
| # Uncomment and configure if you want to log to a file | |
| # "file": { | |
| # "class": "logging.handlers.RotatingFileHandler", | |
| # "formatter": "default", # Use the detailed formatter for file logs too | |
| # "filename": "logs/chatbot_v2.log", # Path to log file | |
| # "maxBytes": 10 * 1024 * 1024, # 10 MB | |
| # "backupCount": 5, # Keep 5 backup files | |
| # "encoding": "utf-8", | |
| # }, | |
| # --- End File Handler --- | |
| }, | |
| "loggers": { | |
| # Root logger configuration | |
| "": { | |
| "handlers": ["console"], # Add "file" here if using file handler | |
| "level": LOG_LEVEL, # Default level for all loggers | |
| "propagate": False, # Prevent logs from propagating to higher-level handlers if any | |
| }, | |
| # Specific configuration for YOUR application's logger(s) | |
| # This assumes your code uses loggers like logging.getLogger("app.api.v2_endpoints") | |
| "app": { | |
| "handlers": ["console"], # Add "file" here if using file handler | |
| # Set your app's code to DEBUG for more detailed logs during development | |
| "level": "INFO", # Or keep as LOG_LEVEL if preferred | |
| "propagate": False, # Don't pass messages up to the root logger | |
| }, | |
| # Configuration for noisy third-party libraries | |
| "uvicorn": { | |
| "handlers": ["console"], | |
| "level": "INFO", # Keep uvicorn's own info messages | |
| "propagate": False, | |
| }, | |
| "uvicorn.error": { | |
| "handlers": ["console"], | |
| "level": "INFO", # Keep uvicorn errors visible | |
| "propagate": False, | |
| }, | |
| "uvicorn.access": { | |
| # Use simple formatter and higher level for access logs to reduce noise | |
| "handlers": ["console"], | |
| "level": "WARNING", # Change to INFO to see every request path | |
| "propagate": False, | |
| # "formatter": "simple", # Optional: Use simpler format | |
| }, | |
| "sqlalchemy": { # Catch-all for sqlalchemy loggers | |
| "handlers": ["console"], | |
| "level": "WARNING", # Set to INFO/DEBUG to see SQL statements/pool info | |
| "propagate": False, | |
| }, | |
| # Example: Quieten down specific noisy loggers if needed | |
| # "httpx": { | |
| # "handlers": ["console"], | |
| # "level": "WARNING", | |
| # "propagate": False, | |
| # }, | |
| # "openai": { | |
| # "handlers": ["console"], | |
| # "level": "WARNING", | |
| # "propagate": False, | |
| # }, | |
| }, | |
| } | |
| def get_logger(name: str = __name__) -> logging.Logger: | |
| """ | |
| Returns a logger configured with a StreamHandler and a basic formatter. | |
| """ | |
| logger = logging.getLogger(name) | |
| if not logger.handlers: | |
| handler = logging.StreamHandler() | |
| handler.setFormatter(logging.Formatter( | |
| "%(asctime)s | %(levelname)-8s | %(name)s | %(message)s" | |
| )) | |
| logger.addHandler(handler) | |
| logger.setLevel(logging.INFO) | |
| return logger | |
| def setup_logging(): | |
| """ | |
| Applies the logging configuration using dictConfig. | |
| Creates log directory if file handler is used and directory doesn't exist. | |
| """ | |
| # --- Optional: Create log directory if file handler is used --- | |
| # if "file" in LOGGING_CONFIG["handlers"]: | |
| # log_dir = os.path.dirname(LOGGING_CONFIG["handlers"]["file"]["filename"]) | |
| # if log_dir and not os.path.exists(log_dir): | |
| # try: | |
| # os.makedirs(log_dir) | |
| # print(f"Created log directory: {log_dir}") | |
| # except OSError as e: | |
| # print(f"Error creating log directory {log_dir}: {e}", file=sys.stderr) | |
| # # Decide if this is critical and should prevent startup | |
| # --- End Optional Directory Creation --- | |
| try: | |
| logging.config.dictConfig(LOGGING_CONFIG) | |
| # Get a logger for this module *after* config is applied | |
| logger = logging.getLogger(__name__) | |
| logger.info(f"Logging configured successfully using dictConfig. Root level: {LOG_LEVEL}") | |
| except Exception as e: | |
| # Fallback to basic config if dictConfig fails for any reason | |
| print(f"Error configuring logging with dictConfig, falling back to basicConfig: {e}", file=sys.stderr) | |
| logging.basicConfig(level=logging.INFO, format="%(asctime)s | %(levelname)-8s | %(name)-20s | %(message)s") | |
| logger = logging.getLogger(__name__) | |
| logger.exception("Logging setup failed, using basic config.") |