backend_chatbot / app /core /logging_config.py
helal94hb1's picture
feat: Update application with new changes14
a9b43b2
# 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.")