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

代码实现

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" 标签
  • 文件日志: 不持久化(容器重启后丢失)

🔍 查看日志

查看实时日志(本地)

# 启动应用(控制台输出)
python3.12 app.py

# 或使用 Gunicorn
gunicorn -c gunicorn_config.py app:app

# 实时监控日志文件
tail -f logs/app.log

查看历史日志

# 查看最近 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 地址

# 提取所有 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 的访问历史

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

分析访问时间分布

# 按小时统计访问量
grep -oP '\[.*?\s+\K\d{2}' logs/app.log | sort | uniq -c

统计不同浏览器的使用情况

grep "UA:" logs/app.log | grep -oP 'UA: \K[^/]+' | sort | uniq -c | sort -rn

🧪 测试 IP 记录

运行测试脚本

# 确保应用正在运行
python3.12 app.py

# 在另一个终端运行测试
python3.12 test_ip_logging.py

手动测试

# 普通请求
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 的前缀

    # 例如:203.0.113.1 -> 203.0.113.0
    ip_parts = ip.split('.')
    anonymized_ip = '.'.join(ip_parts[:3]) + '.0'
    
  2. 定期清理日志: 设置日志保留期限

    # 在 gunicorn_config.py 中
    max_log_age_days = 30  # 保留30天
    
  3. 限制日志访问: 确保只有授权人员可以访问日志

📈 日志性能影响

性能考虑

  • IP 获取:几乎无性能影响(只是读取 HTTP 头部)
  • 日志写入:异步处理,不影响请求响应时间
  • 文件大小:每个日志文件最大 10MB,自动滚动

优化建议

如果日志量很大:

  1. 减少日志级别(只记录重要信息)

    app.logger.setLevel(logging.WARNING)  # 只记录警告和错误
    
  2. 只记录 API 请求(跳过静态资源)

    # 已在 before_request 中实现
    if request.path.startswith('/api/'):
        app.logger.info(...)
    
  3. 使用日志聚合服务(如 ELK、Datadog)

🛠️ 自定义日志格式

修改 Flask 日志格式

编辑 app.py 中的 setup_logging() 函数:

file_handler.setFormatter(logging.Formatter(
    '[%(asctime)s] [%(levelname)s] [IP:%(client_ip)s] %(message)s'
))

修改 Gunicorn 日志格式

编辑 gunicorn_config.py 中的 access_log_format

access_log_format = (
    '%(h)s - %({X-Forwarded-For}i)s '
    '[%(t)s] "%(r)s" %(s)s %(b)s '
    '"%(f)s" "%(a)s"'
)

📚 相关文档

🎉 总结

现在您的 Flask 应用已经可以:

✅ 记录客户端真实 IP 地址
✅ 支持多种代理环境(Hugging Face Spaces、Cloudflare 等)
✅ 提供详细的访问日志
✅ 支持日志分析和统计

查看日志的快速命令:

# 实时监控
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