63 lines
1.9 KiB
Python
63 lines
1.9 KiB
Python
import logging
|
|
import json
|
|
import sys
|
|
from datetime import datetime
|
|
from typing import Optional
|
|
|
|
|
|
class StructuredFormatter(logging.Formatter):
|
|
"""JSON structured log formatter for production."""
|
|
|
|
def format(self, record):
|
|
log_entry = {
|
|
"timestamp": datetime.utcnow().isoformat() + "Z",
|
|
"level": record.levelname,
|
|
"logger": record.name,
|
|
"message": record.getMessage(),
|
|
}
|
|
|
|
if record.exc_info and record.exc_info[0]:
|
|
log_entry["exception"] = self.formatException(record.exc_info)
|
|
|
|
if hasattr(record, "extra_data"):
|
|
log_entry["data"] = record.extra_data
|
|
|
|
return json.dumps(log_entry, ensure_ascii=False)
|
|
|
|
|
|
class HumanFormatter(logging.Formatter):
|
|
"""Human-readable log formatter for development."""
|
|
|
|
def format(self, record):
|
|
return f"{datetime.now().strftime('%H:%M:%S')} [{record.levelname}] {record.name}: {record.getMessage()}"
|
|
|
|
|
|
def setup_logging(level: str = "INFO", structured: bool = False):
|
|
"""
|
|
Setup logging cho toàn bộ ứng dụng.
|
|
|
|
Args:
|
|
level: Log level (DEBUG, INFO, WARNING, ERROR)
|
|
structured: True = JSON format (production), False = human readable (development)
|
|
"""
|
|
root_logger = logging.getLogger()
|
|
root_logger.setLevel(getattr(logging, level.upper(), logging.INFO))
|
|
|
|
# Xóa existing handlers
|
|
root_logger.handlers.clear()
|
|
|
|
handler = logging.StreamHandler(sys.stdout)
|
|
handler.setFormatter(StructuredFormatter() if structured else HumanFormatter())
|
|
root_logger.addHandler(handler)
|
|
|
|
|
|
def log_event(logger: logging.Logger, level: str, message: str, **kwargs):
|
|
"""
|
|
Ghi log với structured data.
|
|
|
|
Usage:
|
|
log_event(logger, "info", "File processed", file_name="test.pdf", pages=5)
|
|
"""
|
|
extra = {"extra_data": kwargs} if kwargs else {}
|
|
getattr(logger, level.lower(), logger.info)(message, extra=extra)
|