Xu ly SSO

This commit is contained in:
2026-05-09 10:31:28 +00:00
parent 9d04e7484c
commit f937d1a98e
21 changed files with 2515 additions and 271 deletions

62
core/logging.py Normal file
View File

@@ -0,0 +1,62 @@
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)

View File

@@ -64,6 +64,7 @@ class DocumentChunk(BaseModel):
embedding: Optional[list[float]] = None
page_from: int
page_to: int
source_url: str
source_url: Optional[str] = None
download_url: Optional[str] = None
permissions: list[str] = []
site_id: str = ""