Symfony默认日志不自动记录GET/POST方法和完整路径,因其Monolog仅在异常等场景打日志,HTTP请求由Web Server或kernel.request触发但未接入主日志流;dev.log中“Matched route”属debug级别且仅限开发环境。

Symfony 默认记录的请求日志(如 dev.log 或 prod.log)本身不自动区分 GET/POST,也不会在每条日志里显式标注请求方法和完整路径。想精准查看“哪个 URL 用什么方法被谁访问了”,必须主动埋点或调整日志通道配置。
为什么默认日志看不到 GET/POST 和完整路径
Symfony 的 Monolog 默认只在异常、命令执行、事件调度等场景打日志;HTTP 请求本身由 Web Server(如 Nginx/Apache)或 Symfony 的 kernel.request 事件触发,但不会自动写入主日志流。你看到的 Matched route "app_homepage" 这类信息来自 debug 日志级别,且仅出现在 dev.log 中,prod.log 默认不记录路由匹配细节。
用 KernelEvents::REQUEST 埋点记录方法+路径
最直接可控的方式是在请求进入时手动记录。推荐在自定义事件监听器中处理:
- 监听
kernel.request事件(注意:早于控制器执行,可捕获所有请求) - 从
$event->getRequest()中提取$request->getMethod()和$request->getUri() - 避免在
dev环境下全量记录(易刷爆日志),建议加条件过滤,例如只记录非 200 响应、特定路径或 POST 请求
示例代码片段:
public function onKernelRequest(RequestEvent $event): void
{
if (!$event->isMainRequest()) {
return;
}
$request = $event->getRequest();
$method = $request->getMethod(); // GET / POST / PUT 等
$uri = $request->getUri();
// 只记录 POST 或含敏感路径的请求
if ('POST' === $method || str_starts_with($request->getPathInfo(), '/api/')) {
$this->logger->info('HTTP request', [
'method' => $method,
'uri' => $uri,
'client_ip' => $request->getClientIp(),
'user_agent' => $request->headers->get('User-Agent'),
]);
}
}
用 monolog 配置按 method 分通道写日志
如果你需要长期归档、或配合 ELK 做分析,可以为不同请求方法创建独立日志通道:
- 在
config/packages/monolog.yaml中新增 handler,比如post_requests - 用
channels将该 handler 绑定到自定义 channel 名(如post) - 在监听器或中间件中,用
$this->logger->channel('post')->info(...)写入 - 注意:不能靠 Monolog 自动识别 HTTP 方法——它没有请求上下文,必须人工传入
配置示意:
monolog:
channels: ['post', 'get']
handlers:
post_requests:
type: stream
path: '%kernel.logs_dir%/post_requests.log'
level: info
channels: ['post']
别依赖 $_SERVER['REQUEST_METHOD'] 或 raw URI 字符串
在 Symfony 中,直接读 $_SERVER['REQUEST_METHOD'] 或 $_SERVER['REQUEST_URI'] 是危险的:
- 它们可能被反向代理污染(如 Nginx 设置了
proxy_set_header X-Forwarded-Method但未启用trusted_proxies) -
$_SERVER['REQUEST_URI']不包含 query string 解码后的语义(比如%20还是空格),而$request->getUri()返回的是标准化后的完整 URI - 真正可靠的来源只有
Request对象实例,它是 Symfony 经过规范化、信任链校验后构建的
所以始终优先调用 $request->getMethod() 和 $request->getFullUrl()(或 $request->getUri())。
真正难的不是“怎么记”,而是“记多少”和“记到哪”。生产环境全量记录每个 GET 请求会迅速撑爆磁盘,也失去重点;但完全不记又无法排查重放攻击或爬虫行为。折中方案是:只对非幂等方法(POST/PUT/DELETE)、带认证的请求、或匹配特定路由前缀的请求做结构化记录,并确保字段含 method、path、IP、时间戳、响应状态码(需监听 kernel.response 补充)。


















