mirror of
https://github.com/aljazceru/enclava.git
synced 2025-12-17 15:34:36 +01:00
156 lines
3.8 KiB
Python
156 lines
3.8 KiB
Python
"""
|
|
Logging configuration
|
|
"""
|
|
|
|
import logging
|
|
import sys
|
|
from typing import Any, Dict
|
|
import structlog
|
|
from structlog.stdlib import LoggerFactory
|
|
|
|
from app.core.config import settings
|
|
|
|
|
|
def setup_logging() -> None:
|
|
"""Setup structured logging"""
|
|
|
|
# Configure structlog
|
|
structlog.configure(
|
|
processors=[
|
|
structlog.stdlib.filter_by_level,
|
|
structlog.stdlib.add_logger_name,
|
|
structlog.stdlib.add_log_level,
|
|
structlog.stdlib.PositionalArgumentsFormatter(),
|
|
structlog.processors.StackInfoRenderer(),
|
|
structlog.processors.format_exc_info,
|
|
structlog.processors.UnicodeDecoder(),
|
|
structlog.processors.JSONRenderer()
|
|
if settings.LOG_FORMAT == "json"
|
|
else structlog.dev.ConsoleRenderer(),
|
|
],
|
|
context_class=dict,
|
|
logger_factory=LoggerFactory(),
|
|
wrapper_class=structlog.stdlib.BoundLogger,
|
|
cache_logger_on_first_use=True,
|
|
)
|
|
|
|
# Configure standard logging
|
|
logging.basicConfig(
|
|
format="%(message)s",
|
|
stream=sys.stdout,
|
|
level=getattr(logging, settings.LOG_LEVEL.upper()),
|
|
)
|
|
|
|
# Set specific loggers
|
|
logging.getLogger("uvicorn").setLevel(logging.WARNING)
|
|
logging.getLogger("uvicorn.access").setLevel(logging.WARNING)
|
|
logging.getLogger("sqlalchemy.engine").setLevel(logging.WARNING)
|
|
|
|
|
|
def get_logger(name: str) -> structlog.stdlib.BoundLogger:
|
|
"""Get a structured logger"""
|
|
return structlog.get_logger(name)
|
|
|
|
|
|
class RequestContextFilter(logging.Filter):
|
|
"""Add request context to log records"""
|
|
|
|
def filter(self, record: logging.LogRecord) -> bool:
|
|
# Add request context if available
|
|
from contextvars import ContextVar
|
|
|
|
request_id: ContextVar[str] = ContextVar("request_id", default="")
|
|
user_id: ContextVar[str] = ContextVar("user_id", default="")
|
|
|
|
record.request_id = request_id.get()
|
|
record.user_id = user_id.get()
|
|
|
|
return True
|
|
|
|
|
|
def log_request(
|
|
method: str,
|
|
path: str,
|
|
status_code: int,
|
|
processing_time: float,
|
|
user_id: str = None,
|
|
request_id: str = None,
|
|
**kwargs: Any,
|
|
) -> None:
|
|
"""Log HTTP request"""
|
|
logger = get_logger("api.request")
|
|
|
|
log_data = {
|
|
"method": method,
|
|
"path": path,
|
|
"status_code": status_code,
|
|
"processing_time": processing_time,
|
|
"user_id": user_id,
|
|
"request_id": request_id,
|
|
**kwargs,
|
|
}
|
|
|
|
if status_code >= 500:
|
|
logger.error("Request failed", **log_data)
|
|
elif status_code >= 400:
|
|
logger.warning("Request error", **log_data)
|
|
else:
|
|
logger.info("Request completed", **log_data)
|
|
|
|
|
|
def log_security_event(
|
|
event_type: str,
|
|
user_id: str = None,
|
|
ip_address: str = None,
|
|
details: Dict[str, Any] = None,
|
|
**kwargs: Any,
|
|
) -> None:
|
|
"""Log security event"""
|
|
logger = get_logger("security")
|
|
|
|
log_data = {
|
|
"event_type": event_type,
|
|
"user_id": user_id,
|
|
"ip_address": ip_address,
|
|
"details": details or {},
|
|
**kwargs,
|
|
}
|
|
|
|
logger.warning("Security event", **log_data)
|
|
|
|
|
|
def log_module_event(
|
|
module_id: str,
|
|
event_type: str,
|
|
details: Dict[str, Any] = None,
|
|
**kwargs: Any,
|
|
) -> None:
|
|
"""Log module event"""
|
|
logger = get_logger("module")
|
|
|
|
log_data = {
|
|
"module_id": module_id,
|
|
"event_type": event_type,
|
|
"details": details or {},
|
|
**kwargs,
|
|
}
|
|
|
|
logger.info("Module event", **log_data)
|
|
|
|
|
|
def log_api_request(
|
|
endpoint: str,
|
|
params: Dict[str, Any] = None,
|
|
**kwargs: Any,
|
|
) -> None:
|
|
"""Log API request for modules endpoints"""
|
|
logger = get_logger("api.module")
|
|
|
|
log_data = {
|
|
"endpoint": endpoint,
|
|
"params": params or {},
|
|
**kwargs,
|
|
}
|
|
|
|
logger.info("API request", **log_data)
|