point / docs /IP_LOGGING_GUIDE.md
eithney
code ref
e74eb63
|
Raw
History Blame Contribute Delete
6.74 kB
# 📋 客户端 IP 地址日志指南
## ✅ 已完成的功能
现在 Flask 应用已经配置为在日志中记录客户端的真实 IP 地址。
## 🔍 日志格式
### Flask 应用日志
```
[2025-10-16 18:58:23] INFO in app: [203.0.113.1] GET /api/health | UA: Mozilla/5.0 (Windows NT 10.0)
^^^^^^^^^^^^
客户端真实 IP
```
**日志包含:**
- 时间戳
- 日志级别
- 客户端 IP 地址
- HTTP 方法和路径
- User-Agent(浏览器信息)
### Gunicorn 访问日志
```
[16/Oct/2025:18:58:23 +0000] Client: 203.0.113.1 (Remote: 172.17.0.1) GET /api/health Status: 200 Size: 123 bytes Time: 5234 μs UA: "Mozilla/5.0..."
^^^^^^^^^^^^
真实客户端 IP
```
**日志包含:**
- 时间戳
- 客户端真实 IP(从 X-Forwarded-For 获取)
- 远程地址(可能是代理服务器)
- 请求信息
- 响应状态码和大小
- 处理时间
- User-Agent
## 🎯 IP 获取逻辑
应用会按以下优先级检查 HTTP 头部来获取真实 IP:
1. **X-Forwarded-For** - 最常见的代理头部
2. **X-Real-IP** - Nginx 等使用
3. **CF-Connecting-IP** - Cloudflare 使用
4. **True-Client-IP** - 某些 CDN 使用
5. **X-Client-IP** - 其他代理使用
6. **request.remote_addr** - 直连时的 IP
### 代码实现
```python
def get_client_ip():
"""获取客户端真实 IP 地址"""
headers_to_check = [
'X-Forwarded-For',
'X-Real-IP',
'CF-Connecting-IP',
'True-Client-IP',
'X-Client-IP',
]
for header in headers_to_check:
ip = request.headers.get(header)
if ip:
# X-Forwarded-For 可能包含多个 IP,取第一个
return ip.split(',')[0].strip()
return request.remote_addr or 'Unknown'
```
## 📁 日志文件位置
### 本地开发环境
- **控制台输出**: 实时显示
- **文件日志**: `logs/app.log`(自动滚动,保留10个备份)
### Hugging Face Spaces
- **控制台输出**: Space 页面的 "Logs" 标签
- **文件日志**: 不持久化(容器重启后丢失)
## 🔍 查看日志
### 查看实时日志(本地)
```bash
# 启动应用(控制台输出)
python3.12 app.py
# 或使用 Gunicorn
gunicorn -c gunicorn_config.py app:app
# 实时监控日志文件
tail -f logs/app.log
```
### 查看历史日志
```bash
# 查看最近 100 条日志
tail -n 100 logs/app.log
# 搜索特定 IP 的访问记录
grep "203.0.113.1" logs/app.log
# 统计各 IP 的访问次数
grep -oP '\[\K[0-9.]+(?=\])' logs/app.log | sort | uniq -c | sort -rn
```
### Hugging Face Spaces
1. 进入你的 Space 页面
2. 点击 "Logs" 标签
3. 查看实时日志输出
4. 可以搜索特定 IP 或时间段
## 📊 日志分析示例
### 统计最活跃的 IP 地址
```bash
# 提取所有 IP 并统计
grep -oP '\[\K[0-9.]+(?=\])' logs/app.log | sort | uniq -c | sort -rn | head -10
```
输出示例:
```
245 203.0.113.1
156 198.51.100.1
89 192.0.2.1
45 203.0.113.50
```
### 查看特定 IP 的访问历史
```bash
grep "\[203.0.113.1\]" logs/app.log
```
输出示例:
```
[2025-10-16 18:58:23] INFO in app: [203.0.113.1] GET /api/health | UA: Mozilla/5.0
[2025-10-16 18:58:24] INFO in app: [203.0.113.1] GET /api/book/info | UA: Mozilla/5.0
[2025-10-16 18:58:25] INFO in app: [203.0.113.1] POST /api/search | UA: Mozilla/5.0
```
### 分析访问时间分布
```bash
# 按小时统计访问量
grep -oP '\[.*?\s+\K\d{2}' logs/app.log | sort | uniq -c
```
### 统计不同浏览器的使用情况
```bash
grep "UA:" logs/app.log | grep -oP 'UA: \K[^/]+' | sort | uniq -c | sort -rn
```
## 🧪 测试 IP 记录
### 运行测试脚本
```bash
# 确保应用正在运行
python3.12 app.py
# 在另一个终端运行测试
python3.12 test_ip_logging.py
```
### 手动测试
```bash
# 普通请求
curl http://localhost:7860/api/health
# 模拟代理请求(带 X-Forwarded-For)
curl -H "X-Forwarded-For: 203.0.113.1" http://localhost:7860/api/health
# 查看日志中记录的 IP
tail logs/app.log
```
## 🔒 隐私和安全
### IP 地址处理
- IP 地址仅用于日志记录和调试
- 不会永久存储在数据库中
- 日志文件会自动滚动(最多保留10个备份)
### 隐私保护建议
如果需要遵守 GDPR 等隐私法规:
1. **匿名化 IP**: 可以只记录 IP 的前缀
```python
# 例如:203.0.113.1 -> 203.0.113.0
ip_parts = ip.split('.')
anonymized_ip = '.'.join(ip_parts[:3]) + '.0'
```
2. **定期清理日志**: 设置日志保留期限
```python
# 在 gunicorn_config.py 中
max_log_age_days = 30 # 保留30天
```
3. **限制日志访问**: 确保只有授权人员可以访问日志
## 📈 日志性能影响
### 性能考虑
- IP 获取:几乎无性能影响(只是读取 HTTP 头部)
- 日志写入:异步处理,不影响请求响应时间
- 文件大小:每个日志文件最大 10MB,自动滚动
### 优化建议
如果日志量很大:
1. **减少日志级别**(只记录重要信息)
```python
app.logger.setLevel(logging.WARNING) # 只记录警告和错误
```
2. **只记录 API 请求**(跳过静态资源)
```python
# 已在 before_request 中实现
if request.path.startswith('/api/'):
app.logger.info(...)
```
3. **使用日志聚合服务**(如 ELK、Datadog)
## 🛠️ 自定义日志格式
### 修改 Flask 日志格式
编辑 `app.py` 中的 `setup_logging()` 函数:
```python
file_handler.setFormatter(logging.Formatter(
'[%(asctime)s] [%(levelname)s] [IP:%(client_ip)s] %(message)s'
))
```
### 修改 Gunicorn 日志格式
编辑 `gunicorn_config.py` 中的 `access_log_format`:
```python
access_log_format = (
'%(h)s - %({X-Forwarded-For}i)s '
'[%(t)s] "%(r)s" %(s)s %(b)s '
'"%(f)s" "%(a)s"'
)
```
## 📚 相关文档
- [Flask 日志文档](https://flask.palletsprojects.com/en/latest/logging/)
- [Gunicorn 配置文档](https://docs.gunicorn.org/en/stable/settings.html)
- [HTTP 头部参考](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers)
## 🎉 总结
现在您的 Flask 应用已经可以:
✅ 记录客户端真实 IP 地址
✅ 支持多种代理环境(Hugging Face Spaces、Cloudflare 等)
✅ 提供详细的访问日志
✅ 支持日志分析和统计
查看日志的快速命令:
```bash
# 实时监控
tail -f logs/app.log
# 搜索特定 IP
grep "203.0.113.1" logs/app.log
# 统计访问量
grep -c "GET /api/" logs/app.log
```
---
**最后更新**: 2025-10-16
**相关文件**: `app.py`, `gunicorn_config.py`, `test_ip_logging.py`