访问日志
OxPHP 为每个 HTTP 请求输出结构化的 JSON 访问日志,写入 stdout。日志记录是异步的,因此绝不会阻塞请求处理。
工作原理
设置 ACCESS_LOG 后,OxPHP 会在每个请求完成后向 stdout 写入一行 JSON。这些写入操作会在一个后台写入线程中缓冲,因此日志记录绝不会阻塞请求流水线。
模式决定了记录哪些内容。ACCESS_LOG=all 记录每个请求;ACCESS_LOG=error 只记录状态码为 400 或更高的响应。
每一行日志都带有一个 request_id 字段,用于将访问日志条目与你的应用日志关联起来。当启用 W3C Trace Context 传播时,日志条目还会包含 trace_id 和 span_id 字段。
配置
| 变量 | 默认值 | 说明 |
|---|---|---|
ACCESS_LOG |
(未设置) | 访问日志模式。all 记录每个请求;error 只记录 4xx 和 5xx 响应。留空或不设置则禁用 |
唯一接受的值是 all 和 error。设置无法识别的值会记录一条警告并禁用访问日志。
日志格式
每条访问日志条目都是写入 stdout 的一行 JSON:
{
"timestamp": "2026-02-11T12:34:56.789012Z",
"level": "INFO",
"fields": {
"request_id": "67890abc12341a2b0042",
"method": "GET",
"path": "/api/users",
"status": 200,
"duration_us": 1234,
"remote_ip": "10.0.0.1",
"message": "request completed"
}
}当 W3C Trace Context 处于活动状态时,trace_id 和 span_id 会与标准字段一同包含在内:
{
"timestamp": "2026-02-11T12:34:56.789012Z",
"level": "INFO",
"fields": {
"request_id": "67890abc12341a2b0042",
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"span_id": "00f067aa0ba902b7",
"method": "POST",
"path": "/api/orders",
"status": 201,
"duration_us": 8421,
"remote_ip": "10.0.0.1",
"message": "request completed"
}
}字段
| 字段 | 类型 | 说明 |
|---|---|---|
request_id |
string | 唯一请求标识符。参见 请求 ID |
method |
string | HTTP 方法(GET、POST 等) |
path |
string | 请求 URI 路径 |
status |
number | HTTP 响应状态码 |
duration_us |
number | 请求处理总时间,单位为微秒 |
remote_ip |
string | 客户端 IP 地址(不含端口)。当配置了 TRUSTED_PROXIES 时,显示从转发头中提取的真实客户端 IP,而非代理的 IP |
trace_id |
string | W3C 追踪 ID(仅当 TRACE_CONTEXT=true 时存在) |
span_id |
string | W3C span ID(仅当 TRACE_CONTEXT=true 时存在) |
细粒度过滤
OxPHP 使用内部的 access_log 日志目标来记录访问日志条目。使用 RUST_LOG 变量可以将访问日志与其他日志输出独立开来进行过滤:
# 抑制常规 info 消息,保留访问日志
RUST_LOG=warn,access_log=infoaccess_log 目标用于 RUST_LOG 过滤,但不会包含在 JSON 输出中。要在下游系统中识别访问日志条目,请使用 "message": "request completed" 字段以及其特有的字段集合(method、path、status、duration_us)。
故障排查
没有出现任何访问日志条目
当 ACCESS_LOG 未设置或为空时,访问日志处于禁用状态。
修复方法: 将变量设置为 all 或 error:
ACCESS_LOG=all访问日志显示为 `error` 模式,但缺少成功的请求
ACCESS_LOG=error 只记录状态码为 400 或更高的响应。这是设计使然——请检查该值,如果你需要记录所有请求,请切换为 all。
检查方法: 确认当前生效的设置:
curl -s http://localhost:9090/config | jq '.access_log'日志条目出现,但没有 `trace_id` 和 `span_id`
只有在启用 W3C Trace Context 传播时才会存在追踪上下文字段。
修复方法: 通过以下方式启用它:
TRACE_CONTEXT=true并确保你的上游客户端或负载均衡器在请求上发送 traceparent 头。
Docker 示例
services:
app:
image: ghcr.io/oxphp/oxphp:0.10.0
ports:
- "80:80"
- "9090:9090"
volumes:
- ./src:/var/www/html:ro
environment:
ACCESS_LOG: "all"
ENTRY_FILE: "index.php"
INTERNAL_ADDR: "0.0.0.0:9090"最佳实践
- 在生产环境中使用
ACCESS_LOG=error,以减少日志量,同时仍能捕获所有失败的请求。成功的请求不会被记录,但任何状态码为 400+ 的错误始终会被捕获。 - 通过
oxphp_request_id()在你的应用日志中包含请求 ID,这样你就可以将 PHP 层面的日志条目与访问日志条目关联起来。 - 使用诸如 Elasticsearch、Loki 或 Datadog 之类的结构化日志聚合工具,以高效地查询和过滤 JSON 日志行。
集成
由于日志是 stdout 上的 JSON 行,它们可以直接与容器日志驱动和聚合工具集成:
- Docker —— 通过容器日志驱动自动收集(json-file、fluentd 等)
- Kubernetes —— 由节点的日志代理拾取(Fluentd、Fluent Bit、Filebeat 等)
- systemd —— 当作为 systemd 服务运行并通过 journald 记录 stdout 时被捕获
无需 sidecar 或基于文件的日志转发。