本文目录导读:

- 基础信息(黄金三要素)
- 定位上下文(Where & Who)
- 技术环境信息(How)
- 业务与请求上下文(核心数据)
- 异常与堆栈(Why)
- 结构化上下文(Context)
- 强烈推荐的日志结构示例(JSON 格式)
- 最后:绝对不能记录的信息(安全红线)
- 实战建议
在 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 项目最常用的选项,利用
Monolog的Processor自动生成 UUID 或从 HTTP Header 中提取,用于贯穿整个请求链路(Nginx -> PHP -> MySQL)。 - 用户身份(Who):如果是 Web 应用,记录登录用户的
user_id或用户名;如果是 CLI,记录执行脚本的操作系统用户。 - 来源 IP 地址:客户端 IP(注意反代情况下需读取
X-Forwarded-For),用于安全审计。
技术环境信息(How)
这部分通常由日志库的 Processor 自动附加,无需手动写入。
- PHP 版本:
PHP 8.3.1. - 运行模式:
FPM、CLI、Worker。 - 服务器环境:
production、staging、development。 - 内存占用峰值:
memory_get_peak_usage(true),用于排查内存泄漏。 - 执行耗时:该请求或脚本的总执行时间(毫秒)。
业务与请求上下文(核心数据)
这是排查业务逻辑错误的重中之重。
- 请求参数:
$_GET、$_POST、$_FILES(注意:必须过滤掉password、token、credit_card等敏感字段)。 - 请求路由:
GET /api/users/123或php artisan migrate。 - 请求头:关键的
User-Agent、Referer、Accept-Language(非必需,按需记录)。 - Session ID(脱敏后)。
异常与堆栈(Why)
当发生异常时,绝不只记录 $e->getMessage(),必须包含完整堆栈。
- 异常类名:
RuntimeException、PDOException等。 - 错误码: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 相关个人隐私数据(除非脱敏并加密)。
实战建议
- 使用库:优先用
Monolog或Laravel自带的 Log 门面,避免手写file_put_contents。 - 环境区分:生产环境禁止记录
DEBUG级别日志,但完整记录ERROR及以上级别。 - 多通道:错误日志写入
error.log,业务日志写入business.log,安全审计日志独立存放audit.log。 - 异步化:对于高并发项目,使用
Redis队列异步写入日志,避免日志 I/O 阻塞业务线程。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播