Spaces:
Sleeping
Sleeping
File size: 2,666 Bytes
aeb3f7c |
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 |
"""Structured logging configuration with rotation support."""
import logging
import sys
from logging.handlers import RotatingFileHandler
from pathlib import Path
from typing import Optional
from pythonjsonlogger import jsonlogger
from writing_studio.core.config import settings
class CustomJsonFormatter(jsonlogger.JsonFormatter):
"""Custom JSON formatter with additional fields."""
def add_fields(self, log_record: dict, record: logging.LogRecord, message_dict: dict) -> None:
"""Add custom fields to log records."""
super().add_fields(log_record, record, message_dict)
log_record["level"] = record.levelname
log_record["logger"] = record.name
log_record["app"] = settings.app_name
log_record["environment"] = settings.environment
def setup_logging(
name: Optional[str] = None,
level: Optional[str] = None,
log_file: Optional[str] = None,
) -> logging.Logger:
"""
Configure structured logging with file rotation.
Args:
name: Logger name (default: root logger)
level: Log level (default: from settings)
log_file: Log file path (default: from settings)
Returns:
Configured logger instance
"""
logger = logging.getLogger(name)
logger.setLevel(level or settings.log_level)
logger.handlers.clear()
# Console handler
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(level or settings.log_level)
# Format based on settings
if settings.log_format == "json":
formatter = CustomJsonFormatter(
"%(timestamp)s %(level)s %(name)s %(message)s",
rename_fields={"timestamp": "asctime"},
)
else:
formatter = logging.Formatter(
"%(asctime)s - %(name)s - %(levelname)s - %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
# File handler with rotation
log_file_path = log_file or settings.log_file_path
if log_file_path:
# Ensure log directory exists
Path(log_file_path).parent.mkdir(parents=True, exist_ok=True)
file_handler = RotatingFileHandler(
log_file_path,
maxBytes=settings.log_max_bytes,
backupCount=settings.log_backup_count,
)
file_handler.setLevel(level or settings.log_level)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
# Prevent propagation to avoid duplicate logs
logger.propagate = False
return logger
# Global logger instance
logger = setup_logging("writing_studio")
|