File size: 6,741 Bytes
16fa939
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
# 📋 客户端 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`