PHP项目日志记录应该包含哪些信息

wen PHP项目 10

本文目录导读:

PHP项目日志记录应该包含哪些信息

  1. 基础信息(黄金三要素)
  2. 定位上下文(Where & Who)
  3. 技术环境信息(How)
  4. 业务与请求上下文(核心数据)
  5. 异常与堆栈(Why)
  6. 结构化上下文(Context)
  7. 强烈推荐的日志结构示例(JSON 格式)
  8. 最后:绝对不能记录的信息(安全红线)
  9. 实战建议

在 PHP 项目中,完善的日志记录是调试问题、监控系统健康、审计安全事件以及优化性能的基础,一个规范的日志条目应该遵循“5W + 1H”原则(Who, When, Where, What, Why, How),并辅以必要的上下文。

以下是 PHP 项目日志记录应该包含的核心信息清单,按重要性分层:

基础信息(黄金三要素)

这是定位问题的首要线索,必须包含

  • 时间戳(When):精确到毫秒Y-m-d H:i:s.u),时区统一为 UTC 或服务器本地时区,并明确标注,在分布式系统中,建议记录 ISO 8601 格式。
  • 日志级别(Severity)DEBUG(调试)、INFO(信息)、NOTICE(提示)、WARNING(警告)、ERROR(错误)、CRITICAL(严重)、ALERT(警报)、EMERGENCY(紧急),这是过滤海量日志的第一道门槛。
  • 消息(Message)人类可读的、具体的描述。避免使用“Error occurred”这种废话,应写“Failed to connect to Redis at 127.0.0.1:6379 (Connection refused)”。

定位上下文(Where & Who)

帮助快速还原问题发生的现场。

  • 文件路径与行号(Where)/var/www/html/app/Http/Controllers/UserController.php:45,虽然堆栈跟踪里有,但在单条日志中直接记录能极大缩短检索时间。
  • 请求 ID / 追踪 ID(Trace ID)PHP 项目最常用的选项,利用 MonologProcessor 自动生成 UUID 或从 HTTP Header 中提取,用于贯穿整个请求链路(Nginx -> PHP -> MySQL)。
  • 用户身份(Who):如果是 Web 应用,记录登录用户的 user_id 或用户名;如果是 CLI,记录执行脚本的操作系统用户。
  • 来源 IP 地址:客户端 IP(注意反代情况下需读取 X-Forwarded-For),用于安全审计。

技术环境信息(How)

这部分通常由日志库的 Processor 自动附加,无需手动写入。

  • PHP 版本PHP 8.3.1.
  • 运行模式FPMCLIWorker
  • 服务器环境productionstagingdevelopment
  • 内存占用峰值memory_get_peak_usage(true),用于排查内存泄漏。
  • 执行耗时:该请求或脚本的总执行时间(毫秒)。

业务与请求上下文(核心数据)

这是排查业务逻辑错误的重中之重。

  • 请求参数$_GET$_POST$_FILES注意:必须过滤掉 passwordtokencredit_card 等敏感字段)。
  • 请求路由GET /api/users/123php artisan migrate
  • 请求头:关键的 User-AgentRefererAccept-Language(非必需,按需记录)。
  • Session ID(脱敏后)。

异常与堆栈(Why)

当发生异常时,绝不只记录 $e->getMessage(),必须包含完整堆栈。

  • 异常类名RuntimeExceptionPDOException 等。
  • 错误码:HTTP 状态码(如 500, 422)或 PHP 错误码(如 E_WARNING)。
  • 异常消息:与第 1 点的 Message 区分,这里保存原始异常文本。
  • 完整堆栈跟踪(Stack Trace):记录 $e->getTraceAsString(),但建议按行展开并缩进,以便阅读。
  • 前因后果:链式异常(getPrevious())也应递归记录。

结构化上下文(Context)

现代日志推荐使用结构化日志(如 JSON 格式),便于机器读取和 ELK 日志分析。

  • 业务对象 ID:如 order_id: 12345, product_sku: "ABC-123"
  • 外部服务响应:调用第三方 API 失败时,记录对方的 HTTP 状态码和响应体摘要。
  • 数据库查询:记录导致失败的 SQL 语句(不包含绑定参数值中的敏感信息)。

强烈推荐的日志结构示例(JSON 格式)

使用 PHP 的 Monolog 库时,一个完美的结构化日志长这样:

{
  "datetime": "2024-05-20T14:33:26.083144+08:00",
  "level": "ERROR",
  "channel": "app",
  "message": "创建订单失败:库存不足",
  "context": {
    "user_id": "U12345",
    "order_id": "",
    "product_sku": "PHONE-X",
    "request_id": "a1b2c3d4-5678-9abc-def0-123456789abc",
    "route": "POST /api/v1/orders",
    "input": {
      "product_sku": "PHONE-X",
      "quantity": 10
    },
    "exception": {
      "class": "App\\Exceptions\\InsufficientStockException",
      "code": 422,
      "message": "Only 5 items available in stock",
      "file": "/var/www/app/Services/OrderService.php",
      "line": 88,
      "trace_string": "#0 /var/www/app/Http/Controllers/OrderController.php(77): ..."
    }
  },
  "extra": {
    "server_ip": "172.17.0.2",
    "php_version": "8.2.12",
    "memory_peak_usage": 10485760,
    "execution_time_ms": 452.3
  }
}

绝对不能记录的信息(安全红线)

  • 明文密码支付卡号CVV
  • 会话令牌(Session Token) 的完整值。
  • API 密钥数据库密码的真实值
  • 完整的 GDPR/HIPAA 相关个人隐私数据(除非脱敏并加密)。

实战建议

  1. 使用库:优先用 MonologLaravel 自带的 Log 门面,避免手写 file_put_contents
  2. 环境区分:生产环境禁止记录 DEBUG 级别日志,但完整记录 ERROR 及以上级别。
  3. 多通道:错误日志写入 error.log,业务日志写入 business.log,安全审计日志独立存放 audit.log
  4. 异步化:对于高并发项目,使用 Redis 队列异步写入日志,避免日志 I/O 阻塞业务线程。

抱歉,评论功能暂时关闭!