# 高级日志系统学习 - shared/logger.py
## 📋 模块概述
Chat-Room项目采用了基于Loguru的高级日志系统,提供了结构化日志、多级别输出、文件轮转、性能监控等企业级功能。本文档深入解析现代Python应用的日志系统设计与实现。
## 🎯 为什么选择Loguru?
### 传统logging vs Loguru对比
```mermaid
graph LR
A[Python标准logging] --> A1[配置复杂]
A --> A2[格式化繁琐]
A --> A3[性能一般]
B[Loguru] --> B1[零配置启动]
B --> B2[丰富格式化]
B --> B3[高性能异步]
B --> B4[结构化日志]
style B fill:#e8f5e8
style A fill:#ffeaa7
```
**Loguru的优势**:
- **简单易用**:无需复杂配置,开箱即用
- **性能优异**:异步写入,不阻塞主线程
- **功能丰富**:自动轮转、压缩、序列化
- **格式灵活**:支持彩色输出、自定义格式
- **结构化日志**:原生支持JSON格式
## 🏗️ 日志系统架构设计
### 整体架构
```mermaid
graph TD
A[应用代码] --> B[LoggerManager]
B --> C[Loguru Logger]
C --> D[控制台输出]
C --> E[文件输出]
C --> F[错误文件]
D --> D1[彩色格式化]
D --> D2[级别过滤]
E --> E1[JSON序列化]
E --> E2[文件轮转]
E --> E3[压缩存储]
F --> F1[错误专用]
F --> F2[堆栈跟踪]
subgraph "配置管理"
G[YAML配置]
H[环境变量]
I[默认配置]
end
B --> G
B --> H
B --> I
```
### 核心类设计
```python
class LoggerManager:
"""日志管理器 - 统一管理所有日志配置"""
def __init__(self):
"""初始化日志管理器"""
self.initialized = False
self.component = "server"
self.config = {}
# 默认配置
self.default_config = {
'level': 'INFO',
'file_enabled': True,
'console_enabled': True,
'file_max_size': 10485760, # 10MB
'file_backup_count': 5,
'compression': 'gz',
'serialize': True,
'enqueue': True # 异步写入
}
def initialize(self, config: Dict[str, Any], component: str = "server"):
"""
初始化日志系统
Args:
config: 日志配置字典
component: 组件名称(server/client)
"""
if self.initialized:
return
self.component = component
self.config = {**self.default_config, **config}
# 移除默认的logger配置
logger.remove()
# 创建日志目录
log_dir = Path("logs") / component
log_dir.mkdir(parents=True, exist_ok=True)
# 配置控制台日志
self._setup_console_logging()
# 配置文件日志
self._setup_file_logging(log_dir)
self.initialized = True
logger.info(f"日志系统初始化完成: {component}")
```
**设计特点**:
- **单例模式**:全局唯一的日志管理器
- **配置驱动**:通过配置文件控制所有行为
- **组件隔离**:不同组件使用独立的日志目录
- **延迟初始化**:避免重复初始化
## 🎨 日志格式化系统
### 控制台日志格式
```python
def _setup_console_logging(self):
"""配置控制台日志输出"""
if not self.config.get('console_enabled', True):
return
level = self.config.get('level', 'INFO')
# 彩色格式化模板
console_format = (
"{time:YYYY-MM-DD HH:mm:ss} | "
"{level: <8} | "
"{name}:{function}:{line} | "
"{message}"
)
logger.add(
sys.stdout,
level=level,
format=console_format,
colorize=True,
filter=self._console_filter,
enqueue=self.config.get('enqueue', True)
)
def _console_filter(self, record):
"""控制台日志过滤器"""
# 过滤掉过于频繁的调试信息
if record["level"].name == "DEBUG":
# 只显示重要的调试信息
return any(keyword in record["message"] for keyword in [
"用户登录", "消息发送", "文件上传", "AI响应"
])
# 过滤掉数据库操作的详细日志
if "database" in record.get("extra", {}):
return record["level"].name != "DEBUG"
return True
```
**格式化特点**:
- **彩色输出**:不同级别使用不同颜色
- **详细信息**:包含时间、级别、位置、消息
- **智能过滤**:避免控制台信息过载
- **性能优化**:异步输出不阻塞主线程
### 文件日志格式
```python
def _setup_file_logging(self, log_dir: Path):
"""配置文件日志输出"""
if not self.config.get('file_enabled', True):
return
level = self.config.get('level', 'INFO')
file_max_size = self.config.get('file_max_size', 10485760)
file_backup_count = self.config.get('file_backup_count', 5)
# 主日志文件 - 结构化JSON格式
main_log_file = log_dir / f"{self.component}.log"
logger.add(
str(main_log_file),
level=level,
format=self._create_json_formatter(),
rotation=file_max_size,
retention=file_backup_count,
compression="gz",
serialize=True, # JSON序列化
enqueue=True, # 异步写入
encoding='utf-8'
)
# 错误日志单独记录
error_log_file = log_dir / f"{self.component}_error.log"
logger.add(
str(error_log_file),
level="ERROR",
format=self._create_error_formatter(),
rotation=file_max_size,
retention=file_backup_count,
compression="gz",
serialize=True,
enqueue=True,
encoding='utf-8'
)
def _create_json_formatter(self):
"""创建JSON格式化器"""
def formatter(record):
"""自定义JSON格式化"""
# 基础字段
log_entry = {
"timestamp": record["time"].isoformat(),
"level": record["level"].name,
"logger": record["name"],
"message": record["message"],
"module": record["module"],
"function": record["function"],
"line": record["line"]
}
# 添加额外字段
extra = record.get("extra", {})
for key, value in extra.items():
if key not in log_entry:
log_entry[key] = value
# 添加异常信息
if record["exception"]:
log_entry["exception"] = {
"type": record["exception"].type.__name__,
"value": str(record["exception"].value),
"traceback": record["exception"].traceback
}
return json.dumps(log_entry, ensure_ascii=False, default=str)
return formatter
```
**文件日志特点**:
- **JSON格式**:结构化存储,便于分析
- **自动轮转**:文件大小达到限制时自动轮转
- **压缩存储**:旧日志文件自动压缩节省空间
- **错误分离**:错误日志单独存储便于排查
## 📊 专用日志记录器
### 数据库操作日志
```python
def log_database_operation(operation: str, table: str, **kwargs):
"""
记录数据库操作日志
Args:
operation: 操作类型 (SELECT, INSERT, UPDATE, DELETE)
table: 表名
**kwargs: 额外的上下文信息
"""
logger.debug(
f"数据库操作: {operation} - {table}",
database=True,
operation=operation,
table=table,
**kwargs
)
# 使用示例
def create_user(self, username: str, password: str) -> int:
"""创建用户"""
try:
# 数据库操作
user_id = self._insert_user(username, password)
# 记录成功日志
log_database_operation(
"INSERT", "users",
user_id=user_id,
username=username,
status="success"
)
return user_id
except Exception as e:
# 记录失败日志
log_database_operation(
"INSERT", "users",
username=username,
status="error",
error=str(e)
)
raise
```
### AI操作日志
```python
def log_ai_operation(operation: str, model: str, **kwargs):
"""
记录AI操作日志
Args:
operation: 操作类型 (generate_reply, process_message)
model: AI模型名称
**kwargs: 额外信息(如响应时间、token数量等)
"""
logger.info(
f"AI操作: {operation} using {model}",
ai=True,
operation=operation,
model=model,
**kwargs
)
# 使用示例
def process_ai_request(self, user_message: str) -> str:
"""处理AI请求"""
start_time = time.time()
try:
# AI处理
response = self.ai_client.generate_response(user_message)
# 计算响应时间
response_time = time.time() - start_time
# 记录成功日志
log_ai_operation(
"generate_reply", "glm-4-flash",
response_time=response_time,
input_length=len(user_message),
output_length=len(response),
status="success"
)
return response
except Exception as e:
# 记录失败日志
log_ai_operation(
"generate_reply", "glm-4-flash",
response_time=time.time() - start_time,
input_length=len(user_message),
status="error",
error=str(e)
)
raise
```
### 网络操作日志
```python
def log_network_operation(operation: str, client_info: dict = None, **kwargs):
"""
记录网络操作日志
Args:
operation: 操作类型 (connect, disconnect, send_message)
client_info: 客户端信息 (IP, port, user_id)
**kwargs: 额外信息
"""
logger.info(
f"网络操作: {operation}",
network=True,
operation=operation,
client_info=client_info or {},
**kwargs
)
# 使用示例
def handle_client_connection(self, client_socket, address):
"""处理客户端连接"""
client_info = {"ip": address[0], "port": address[1]}
# 记录连接日志
log_network_operation("client_connect", client_info)
try:
# 处理客户端消息
while True:
message = self.receive_message(client_socket)
if not message:
break
# 记录消息接收日志
log_network_operation(
"message_received",
client_info,
message_type=message.message_type,
message_size=len(str(message))
)
self.process_message(client_socket, message)
except Exception as e:
# 记录错误日志
log_network_operation(
"client_error",
client_info,
error=str(e)
)
finally:
# 记录断开连接日志
log_network_operation("client_disconnect", client_info)
```
## 🎭 高级日志功能
### 性能监控装饰器
```python
def log_performance(event_type: str = None, log_args: bool = False,
log_result: bool = False):
"""
性能监控装饰器
Args:
event_type: 事件类型,默认使用函数名
log_args: 是否记录函数参数
log_result: 是否记录函数返回值
"""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
func_name = func.__name__
event = event_type or func_name
# 记录函数开始
log_data = {"function": func_name}
if log_args:
log_data["args"] = str(args)
log_data["kwargs"] = str(kwargs)
logger.debug(f"函数调用开始: {func_name}", **log_data)
try:
# 执行函数
start_time = datetime.now()
result = func(*args, **kwargs)
end_time = datetime.now()
duration = (end_time - start_time).total_seconds()
# 记录成功日志
success_data = {
"function": func_name,
"duration": duration,
"status": "success"
}
if log_result:
success_data["result"] = str(result)
logger.debug(f"函数调用成功: {func_name}", **success_data)
return result
except Exception as e:
# 记录失败日志
error_data = {
"function": func_name,
"duration": (datetime.now() - start_time).total_seconds(),
"status": "error",
"error": str(e)
}
logger.error(f"函数调用失败: {func_name}", **error_data)
raise
return wrapper
return decorator
# 使用示例
@log_performance("user_authentication", log_args=True)
def authenticate_user(self, username: str, password: str):
"""用户认证"""
# 认证逻辑
pass
@log_performance("message_processing")
def process_chat_message(self, message):
"""处理聊天消息"""
# 消息处理逻辑
pass
```
### 安全事件日志
```python
def log_security_event(event_type: str, **kwargs):
"""
记录安全事件日志
Args:
event_type: 安全事件类型
**kwargs: 事件详细信息
"""
logger.warning(
f"安全事件: {event_type}",
security=True,
event_type=event_type,
timestamp=datetime.now().isoformat(),
**kwargs
)
# 使用示例
def handle_login_attempt(self, username: str, password: str, client_ip: str):
"""处理登录尝试"""
try:
user = self.authenticate_user(username, password)
# 记录成功登录
log_security_event(
"login_success",
username=username,
client_ip=client_ip,
user_id=user['id']
)
return user
except AuthenticationError:
# 记录失败登录
log_security_event(
"login_failed",
username=username,
client_ip=client_ip,
reason="invalid_credentials"
)
raise
def handle_admin_operation(self, admin_id: int, operation: str, target: str):
"""处理管理员操作"""
# 记录管理员操作
log_security_event(
"admin_operation",
admin_id=admin_id,
operation=operation,
target=target
)
# 执行操作
self.execute_admin_operation(operation, target)
```
### 错误聚合和告警
```python
class ErrorAggregator:
"""错误聚合器 - 统计和分析错误模式"""
def __init__(self):
self.error_counts = {}
self.error_threshold = 10 # 错误阈值
self.time_window = 300 # 时间窗口(秒)
def record_error(self, error_type: str, error_message: str):
"""记录错误"""
current_time = time.time()
if error_type not in self.error_counts:
self.error_counts[error_type] = []
# 添加错误记录
self.error_counts[error_type].append({
"timestamp": current_time,
"message": error_message
})
# 清理过期记录
self._cleanup_old_errors(error_type, current_time)
# 检查是否需要告警
if len(self.error_counts[error_type]) >= self.error_threshold:
self._trigger_alert(error_type)
def _cleanup_old_errors(self, error_type: str, current_time: float):
"""清理过期的错误记录"""
cutoff_time = current_time - self.time_window
self.error_counts[error_type] = [
error for error in self.error_counts[error_type]
if error["timestamp"] > cutoff_time
]
def _trigger_alert(self, error_type: str):
"""触发告警"""
logger.critical(
f"错误频率告警: {error_type}",
alert=True,
error_type=error_type,
count=len(self.error_counts[error_type]),
time_window=self.time_window
)
# 全局错误聚合器
error_aggregator = ErrorAggregator()
def log_error_with_aggregation(error_type: str, error_message: str):
"""记录错误并进行聚合分析"""
logger.error(error_message, error_type=error_type)
error_aggregator.record_error(error_type, error_message)
```
## 💡 学习要点
### 现代日志系统设计
1. **结构化日志**:使用JSON格式便于分析和查询
2. **异步写入**:避免日志记录阻塞主线程
3. **智能过滤**:根据环境和需求过滤日志内容
4. **性能监控**:集成性能指标收集
5. **安全审计**:记录安全相关事件
### Loguru高级特性
1. **零配置**:开箱即用,无需复杂配置
2. **自动轮转**:文件大小和时间双重轮转策略
3. **压缩存储**:自动压缩旧日志文件
4. **异常捕获**:自动记录异常堆栈信息
5. **上下文绑定**:为日志记录绑定上下文信息
### 企业级日志实践
1. **分级存储**:不同级别的日志使用不同存储策略
2. **集中收集**:使用ELK Stack等工具集中收集日志
3. **实时监控**:基于日志的实时告警和监控
4. **合规要求**:满足安全和合规的日志保留要求
## 🤔 思考题
1. **如何设计分布式系统的日志追踪?**
- 使用TraceID关联分布式调用
- 实现请求链路追踪
- 集中化日志收集和分析
2. **如何平衡日志详细程度和性能?**
- 动态调整日志级别
- 异步日志写入
- 智能采样策略
3. **如何实现日志的安全和隐私保护?**
- 敏感信息脱敏
- 日志访问权限控制
- 加密存储重要日志
---
**下一步**:学习Socket编程进阶 → [advanced-socket.md](./advanced-socket.md)