symfony2日志充斥404因监听kernel.request过早,应改用kernel.controller事件并校验_controller属性及状态码,或在自定义monolog处理器中过滤notfoundhttpexception和空_controller。

为什么 Symfony2 的日志里全是 404 和无效路径
因为默认的 kernel.request 事件监听器在路由匹配失败前就记录了请求,而 Symfony2 的日志通道(如 request 或 php)不区分“是否命中有效路由”。结果就是 /favicon.ico、/wp-login.php、扫描器试探路径全进了日志,淹没了真实业务流量。
用 kernel.controller 替代 kernel.request 做日志入口
只有成功匹配到控制器的动作,才值得记为“有效访问”。kernel.controller 事件只在路由解析完成、控制器已确定时触发,天然过滤掉所有 404、301 重定向、静态资源请求(只要没配成路由)。
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- 在服务定义中绑定监听器到
kernel.controller,而非kernel.request - 监听器方法签名必须是
onKernelController(ControllerEvent $event)(注意:Symfony2 没有ControllerEvent,需用GetResponseForControllerResultEvent或更稳妥地降级为kernel.response+ 手动检查$event->getRequest()->attributes->has('_controller')) - 从
$event->getRequest()提取路径、方法、IP;从$event->getRequest()->attributes读_controller字符串确认非空,再写日志
手动拦截 404 并跳过日志的兜底方案
如果无法改监听时机(比如已有全局 request 日志逻辑),就在日志处理器里加判断。Symfony2 的 Monolog\Handler\StreamHandler 可包装为自定义处理器,在 write() 方法中过滤:
- 检查
$record['context']['exception']是否为Symfony\Component\HttpKernel\Exception\NotFoundHttpException - 或检查
$record['context']['request']->attributes->get('_controller') === null - 若匹配任一条件,直接
return,不调用父类write() - 注意:该方式依赖日志上下文是否注入了 request 和 exception,需确认你用的
DebugHandlersListener或自定义日志配置已启用上下文传递
别忽略路由层级的静默失败
有些请求看似“有效”,实则只是命中了泛匹配路由(如 @Route("/{path}", requirements={"path" = ".+"})),但控制器内部返回了 404 或空响应。这类请求仍会进 kernel.controller,所以必须在日志前加二次校验:
- 读取
$event->getRequest()->attributes->get('_route'),排除以_wdt、_profiler、_error开头的调试路由 - 检查控制器返回的
Response状态码:$event->getControllerResult() instanceof Response且$response->getStatusCode() - 对 JSON API 路由,可额外判断
Content-Type是否含application/json,避免把前端 404 页面渲染也当有效请求










