# API接口日志记录功能使用指南 ## 功能概述 本功能实现了对所有API接口的完整日志记录,包括: - **入参密文**: 原始请求体(加密数据) - **入参明文**: 解密后的请求参数 - **出参明文**: 业务响应数据 - **出参密文**: 加密后的响应数据 日志文件按天滚动,每天生成一个日志文件,保存在 `logs/api/` 目录下。 ## 文件结构 ``` backend-client/ ├── app/ │ ├── middleware/ │ │ ├── logging.py # 增强的API日志中间件(已更新) │ │ └── enhanced_logging.py # 独立的增强日志中间件(可选使用) │ ├── utils/ │ │ ├── api_context.py # 请求上下文管理 │ │ ├── api_logger.py # API日志记录器 │ │ └── __init__.py # 导出工具函数 │ ├── api/ │ │ └── v1/ │ │ └── router.py # 示例API路由 │ └── main.py # 应用入口(已添加中间件) └── logs/ └── api/ └── api_2026-02-02.log # 按天滚动的日志文件 ``` ## 日志格式 每条日志记录包含以下字段: ```json { "timestamp": "2026-02-02 18:30:45.123", // 时间戳(精确到毫秒) "endpoint": "http://localhost:9000/api/v1/auth/login", // 接口路径 "method": "POST", // HTTP方法 "user_id": 1, // 用户ID(可为null) "client_ip": "192.168.1.100", // 客户端IP "processing_time_ms": 105, // 处理时间(毫秒) "status_code": 200, // HTTP状态码 "error": null, // 错误信息(可为null) "request": { "encrypted": "base64编码的加密请求数据...", "decrypted": { "username": "test", "password": "****", // 已脱敏 "machine_code": "****" // 已脱敏 } }, "response": { "encrypted": "base64编码的加密响应数据...", "decrypted": { "code": 200, "msg": "登录成功", "data": {...} } } } ``` ## 敏感字段脱敏 以下字段会被自动脱敏: - `password`, `card_code` - 密码和卡密 - `shared_secret`, `identity_secret` - Steam密钥 - `aes_key`, `encrypted_aes_key` - AES密钥 - `signature` - 签名 - `access_token`, `refresh_token`, `session_token` - Token - `steamLoginSecure` - Steam登录令牌 - `machine_code` - 机器码 ## 使用方法 ### 方式1: 自动记录(中间件自动处理) 中间件会自动记录: - 入参密文(原始请求体) - 出参密文(加密响应数据) 无需额外代码,只需确保中间件已添加到应用中。 ### 方式2: 手动记录明文(在业务代码中) 在API处理函数中,使用提供的工具函数记录明文数据: ```python from fastapi import APIRouter from app.utils.api_context import ( get_decrypted_request, # 获取解密后的请求数据 log_decrypted_request, # 记录入参明文 log_decrypted_response, # 记录出参明文 ) router = APIRouter() @router.post("/auth/login") async def login(request_data: LoginRequest): """ 用户登录接口示例 """ # 方法1: 获取解密后的请求数据 decrypted_request = get_decrypted_request() if decrypted_request: # 记录入参明文 log_decrypted_request(decrypted_request) else: # 如果没有解密数据,直接记录请求体 log_decrypted_request(request_data.model_dump()) # 业务处理... # 构建响应数据 response_data = {"code": 200, "msg": "成功", "data": {...}} # 记录出参明文 log_decrypted_response(response_data) return response_data ``` ### 方式3: 完整记录(包含所有数据) 使用 `log_complete` 函数记录完整的API调用信息: ```python from app.utils.api_context import log_complete @router.post("/auth/login") async def login(request_data: LoginRequest): # 业务处理... response_data = {"code": 200, "msg": "成功"} # 完整记录(包含明文和密文) log_complete( decrypted_request=request_data.model_dump(), decrypted_response=response_data, processing_time_ms=105, status_code=200 ) return response_data ``` ## 配置说明 ### 日志文件配置 在 `app/utils/api_logger.py` 中可以配置: ```python # 日志目录 API_LOG_DIR = Path("logs/api") # 敏感字段脱敏 REDACTED_FIELDS = { "password", "card_code", # ... 其他字段 } # 数据截断长度 MAX_DATA_LENGTH = 10000 ``` ### 日志轮转 日志文件按天自动轮转,保留最近30天的日志: ```python loguru_logger.add( str(self._log_path), rotation="00:00", # 每天午夜轮转 retention="30 days", # 保留30天 ... ) ``` ## 示例API路由 已创建示例接口,演示如何使用日志功能: - `POST /api/v1/auth/login` - 用户登录 - `GET /api/v1/announcements` - 获取公告列表 - `POST /api/v1/heartbeat` - 心跳检测 ## 与现有系统的集成 ### 1. 数据库日志记录 原有的 `APILoggingASGIMiddleware` 仍然会将日志写入 `api_logs` 表,记录请求和响应的密文(截断后)。 ### 2. 控制台日志 控制台会同时输出简化的日志信息: ``` [API请求] POST http://localhost:9000/api/v1/auth/login - 请求数据(密文): eyJ... [API响应] POST http://localhost:9000/api/v1/auth/login - 响应数据(密文): eyJ... - 执行时间: 105ms ``` ### 3. 文件日志 增强的日志会同时写入: - `logs/api/api_YYYY-MM-DD.log` - 完整的入参出参日志 - `logs/client_YYYYMMDD.log` - 原有控制台日志 ## 故障排除 ### 问题1: 看不到入参明文 原因:业务代码中没有调用 `log_decrypted_request` 函数。 解决方案: ```python # 在API处理函数中添加 decrypted_request = get_decrypted_request() if decrypted_request: log_decrypted_request(decrypted_request) ``` ### 问题2: 日志文件没有生成 原因:日志目录权限问题或日志器配置错误。 解决方案: 1. 确保 `logs/api` 目录存在且有写入权限 2. 检查 `app/utils/api_logger.py` 中的日志路径配置 ### 问题3: 敏感字段没有脱敏 原因:字段名不在脱敏列表中。 解决方案:在 `REDACTED_FIELDS` 集合中添加字段名。 ## 最佳实践 1. **在每个API处理函数中记录明文**:确保调用 `log_decrypted_request` 和 `log_decrypted_response` 2. **不要记录完整的敏感数据**:依赖自动脱敏机制 3. **监控日志文件大小**:避免单个日志文件过大 4. **定期清理旧日志**:日志保留策略已设置为30天 ## 性能考虑 1. **异步记录**:日志记录不会阻塞API响应 2. **数据截断**:过长的数据会被自动截断 3. **批量处理**:日志写入采用批量方式,提高IO效率