FrankenPHP默认日志非JSON,需由PHP应用层通过error_log(json_encode($logData), 0)输出单行JSON到stdout;$logData须含timestamp、level等字段,Logstash等须配置JSON解析模式,且不可依赖access.log做业务日志。

FrankenPHP 默认日志不是 JSON,得自己接管输出
FrankenPHP 本身不提供内置的 JSON 日志格式选项,它的默认日志(如访问日志、错误日志)是纯文本格式,无法被 Logstash 或 ELK 直接结构化解析。要让日志能被 JSON 提取模式正确采集,必须把日志内容控制权交还给 PHP 应用层,让每条日志都是一行合法 JSON 字符串。
用 error_log() + json_encode() 写 stdout 是最稳的方案
FrankenPHP 容器或二进制模式下,stdout 会被直接捕获为应用日志(类似 Docker 的 logs 流),这是结构化日志采集的黄金路径。别碰 error_log($msg, 3, $file) 写文件——那会绕过日志驱动,也难统一管理。
- 确保所有关键日志都走
error_log(json_encode($logData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), 0) -
$logData必须是关联数组,含timestamp、level、message、context等字段,例如:['timestamp' => date('c'), 'level' => 'info', 'message' => 'user login', 'context' => ['uid' => 123, 'ip' => $_SERVER['REMOTE_ADDR']]] - 不要在
context里塞$_POST全量或资源句柄,json_encode()会失败或卡住 - 如果用了 FrankenPHP 的 worker 模式,注意
date()在协程中可能不准,改用(new DateTime())->format('c')更可靠
Logstash 或日志服务端必须按单行 JSON 解析
即使 PHP 输出了合法 JSON,Logstash、阿里云 SLS、腾讯云 CLS 等工具仍需明确配置“JSON 提取模式”,否则会当成普通文本切分。
- 确认日志采集器开启
json解析模式(不是regex或fulltext) - 每条日志必须严格单行:不能有换行符、不能嵌套多层 JSON、不能用
JSON_PRETTY_PRINT - 若用 Logstash,
filter段必须加json { source => "message" },且确保输入插件没做额外换行拼接 - 测试方法:手动
echo '{"level":"info","msg":"test"}' | curl -X POST http://logstash:5044,看 Kibana 是否能提取出level字段
别依赖 FrankenPHP 的 access.log 做业务日志
FrankenPHP 的 access.log 只记录 HTTP 请求基础信息(状态码、路径、耗时等),它由 Caddy 层生成,格式固定、不可扩展,也不包含业务上下文(如用户 ID、订单号)。想做可观测性,这部分必须由 PHP 应用自己打点。
立即学习“PHP免费学习笔记(深入)”;
- 在中间件或全局异常处理器里统一注入 trace_id、request_id、server_name 等字段
- 接口入口处记录
start_time,响应前计算duration_ms并写入日志 - 错误日志务必包含
exception和trace字段,但记得先strip_tags()或substr()截断过长堆栈,避免撑爆日志系统 - 如果项目已用 Monolog,可配
StreamHandler+JsonFormatter,并把 stream 设为php://stdout
uid:123 就永远为空。



















