File size: 5,860 Bytes
80dbe44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
"""
Logging Configuration Module
Cấu hình logging tập trung cho toàn bộ ứng dụng
"""

import logging
import logging.handlers
from pathlib import Path
from datetime import datetime
from typing import Optional

from .setting import settings


class LoggerSetup:
    """Cấu hình logging cho ứng dụng"""
    
    def __init__(self):
        self.log_dir = Path(__file__).resolve().parents[2] / "logs"
        self.log_dir.mkdir(exist_ok=True)
        self.setup_done = False
    
    def setup_logging(self, 
                     log_level: Optional[str] = None,
                     enable_file_logging: bool = True,
                     enable_console_logging: bool = True) -> None:
        """
        Cấu hình logging cho toàn bộ ứng dụng
        
        Args:
            log_level: Mức độ log (DEBUG, INFO, WARNING, ERROR, CRITICAL)
            enable_file_logging: Có ghi log ra file không
            enable_console_logging: Có hiển thị log trên console không
        """
        if self.setup_done:
            return
            
        # Sử dụng log level từ settings nếu không được truyền vào
        if log_level is None:
            log_level = settings.LOG_LEVEL
        
        # Cấu hình root logger
        root_logger = logging.getLogger()
        root_logger.setLevel(getattr(logging, log_level.upper()))
        
        # Xóa các handler cũ nếu có
        for handler in root_logger.handlers[:]:
            root_logger.removeHandler(handler)
        
        # Định dạng log message
        formatter = logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s',
            datefmt='%Y-%m-%d %H:%M:%S'
        )
        
        detailed_formatter = logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(filename)s:%(lineno)d - %(funcName)s() - %(message)s',
            datefmt='%Y-%m-%d %H:%M:%S'
        )
        
        # Console handler
        if enable_console_logging:
            console_handler = logging.StreamHandler()
            console_handler.setLevel(getattr(logging, log_level.upper()))
            console_handler.setFormatter(formatter)
            root_logger.addHandler(console_handler)
        
        # File handlers
        if enable_file_logging:
            # General log file (with rotation)
            general_log_file = self.log_dir / "transportation.log"
            file_handler = logging.handlers.RotatingFileHandler(
                general_log_file,
                maxBytes=10*1024*1024,  # 10MB
                backupCount=5,
                encoding='utf-8'
            )
            file_handler.setLevel(logging.INFO)
            file_handler.setFormatter(detailed_formatter)
            root_logger.addHandler(file_handler)
            
            # Error log file (only errors and above)
            error_log_file = self.log_dir / "errors.log"
            error_handler = logging.handlers.RotatingFileHandler(
                error_log_file,
                maxBytes=10*1024*1024,  # 10MB
                backupCount=3,
                encoding='utf-8'
            )
            error_handler.setLevel(logging.ERROR)
            error_handler.setFormatter(detailed_formatter)
            root_logger.addHandler(error_handler)
            
            # Daily log file (one file per day)
            daily_log_file = self.log_dir / f"daily_{datetime.now().strftime('%Y%m%d')}.log"
            daily_handler = logging.handlers.TimedRotatingFileHandler(
                daily_log_file,
                when='midnight',
                interval=1,
                backupCount=30,  # Keep 30 days
                encoding='utf-8'
            )
            daily_handler.setLevel(logging.DEBUG)
            daily_handler.setFormatter(detailed_formatter)
            root_logger.addHandler(daily_handler)
        
        # Cấu hình cho các logger cụ thể
        self._configure_specific_loggers()
        
        self.setup_done = True
        logging.info("Logging system initialized successfully")
    
    def _configure_specific_loggers(self):
        """Cấu hình các logger cho các module cụ thể"""
        
        # FastAPI và Uvicorn
        logging.getLogger("uvicorn").setLevel(logging.INFO)
        logging.getLogger("uvicorn.access").setLevel(logging.WARNING)
        logging.getLogger("fastapi").setLevel(logging.INFO)
        
        # Transportation specific loggers
        logging.getLogger("transportation").setLevel(logging.INFO)
        logging.getLogger("prediction").setLevel(logging.INFO)
        logging.getLogger("chat").setLevel(logging.INFO)
        
        # External libraries
        logging.getLogger("requests").setLevel(logging.WARNING)
        logging.getLogger("urllib3").setLevel(logging.WARNING)
        logging.getLogger("google").setLevel(logging.WARNING)
    
    def get_logger(self, name: str) -> logging.Logger:
        """
        Lấy logger với tên cụ thể
        
        Args:
            name: Tên của logger (thường là __name__)
            
        Returns:
            Logger instance
        """
        if not self.setup_done:
            self.setup_logging()
        
        return logging.getLogger(name)


# Global logger setup instance
logger_setup = LoggerSetup()

def get_logger(name: str) -> logging.Logger:
    """
    Convenience function để lấy logger
    
    Usage:
        from src.config.logging_config import get_logger
        logger = get_logger(__name__)
    """
    return logger_setup.get_logger(name)

def setup_logging(**kwargs):
    """
    Convenience function để setup logging
    
    Usage:
        from src.config.logging_config import setup_logging
        setup_logging(log_level="DEBUG")
    """
    return logger_setup.setup_logging(**kwargs)