Spaces:
Sleeping
Sleeping
File size: 5,875 Bytes
58de15f a9b43b2 58de15f |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# 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.") |