cohorta/backend/logging_config.py
2025-12-19 19:26:16 +00:00

103 lines
No EOL
3.8 KiB
Python
Executable file

"""
Custom logging configuration for the application to reduce noise.
"""
import logging
import sys
from typing import Dict, Any
class CustomHTTPFilter(logging.Filter):
"""Filter to reduce noise from routine HTTP requests."""
# Define routes that should be logged only on errors/warnings
QUIET_ROUTES = {
'/api/focus-groups/',
'/api/focus-group-ai/key-themes/',
'/api/focus-group-ai/autonomous/status/',
'/api/personas',
'/api/ai-personas',
'/static/',
'/favicon.ico',
'/health',
'/ping'
}
# Define HTTP methods that should be quiet for routine operations
QUIET_METHODS = {'GET', 'OPTIONS'}
def filter(self, record: logging.LogRecord) -> bool:
"""Filter log records to reduce noise from routine operations."""
# Allow all non-HTTP logs
if not hasattr(record, 'pathname') and not hasattr(record, 'msg'):
return True
# Check if this is an HTTP access log
msg = str(record.msg) if hasattr(record, 'msg') else str(record)
# If it's not an HTTP request log, allow it
if not any(method in msg for method in ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS']):
return True
# Check if it's a successful response (2xx) to a quiet route
if any(route in msg for route in self.QUIET_ROUTES):
# Allow if it's an error response (4xx, 5xx) or warning/error level
if record.levelno >= logging.WARNING:
return True
# Check if it's a successful response (2xx)
if ' 2' in msg and any(method in msg for method in self.QUIET_METHODS):
return False # Filter out successful GET requests to quiet routes
return True
def setup_logging(log_level: str = 'INFO') -> None:
"""Setup custom logging configuration."""
# Convert log level string to logging constant
numeric_level = getattr(logging, log_level.upper(), logging.INFO)
# Create custom formatter
formatter = logging.Formatter(
'[%(asctime)s] %(levelname)s in %(name)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
# Setup root logger
root_logger = logging.getLogger()
root_logger.setLevel(numeric_level)
# Clear existing handlers
root_logger.handlers.clear()
# Create console handler
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setFormatter(formatter)
console_handler.setLevel(numeric_level)
# Add custom filter to reduce HTTP noise
http_filter = CustomHTTPFilter()
console_handler.addFilter(http_filter)
root_logger.addHandler(console_handler)
# Set specific logger levels
logging.getLogger('pymongo').setLevel(logging.WARNING) # Reduce MongoDB driver noise
logging.getLogger('werkzeug').setLevel(logging.WARNING) # Reduce Flask dev server noise
logging.getLogger('hypercorn').setLevel(logging.WARNING) # Reduce Hypercorn noise
logging.getLogger('hypercorn.access').setLevel(logging.WARNING) # Reduce access log noise
logging.getLogger('engineio.server').setLevel(logging.WARNING) # Reduce WebSocket PING/PONG spam
logging.getLogger('socketio.server').setLevel(logging.WARNING) # Reduce WebSocket noise
# Keep application loggers at INFO level
logging.getLogger('app').setLevel(numeric_level)
# Setup MongoDB connection logging to be quieter
logging.getLogger('app.db').setLevel(logging.WARNING)
def create_app_logger(name: str) -> logging.Logger:
"""Create a logger for application modules."""
logger = logging.getLogger(f'app.{name}')
return logger
# Default configuration - changed to DEBUG for troubleshooting
DEFAULT_LOG_LEVEL = 'INFO'