要记录 Symfony 2 的路由访问需手动注册 kernel.request 监听器,使用 GetResponseEvent,注入 LoggerInterface,在 onKernelRequest 中获取路径与路由名(fallback 至控制器),过滤非业务请求、CLI 和子请求,并在 services.yml 中显式声明事件标签及匹配 Monolog channel。

Symfony 2 默认不会记录每次路由匹配或请求进入内核的详细过程,kernel.request 事件本身是触发了,但没配置监听器写日志,所以你看不到“谁访问了哪个路由”。要补上这层访问记录,得手动加监听器,并注意 Symfony 2 的容器注册方式和事件签名与新版差异较大。
监听 kernel.request 事件并记录请求路径和路由名
Symfony 2 的 kernel.request 监听器接收的是 GetResponseEvent(不是 3.3+ 的 RequestEvent),且需手动在 services.yml 中注册,不能靠自动发现。
- 创建监听器类,例如
src/Acme/Bundle/LoggerBundle/EventListener/RouteAccessLogger.php - 构造函数注入
LoggerInterface,确保你已配好主日志服务(如monolog.logger) - 在
onKernelRequest方法中获取当前请求和路由名:$request->attributes->get('_route'),注意它可能为null(如匹配失败或前置中间件未设路由) - 用
$logger->info(sprintf('Access: %s → %s', $request->getPathInfo(), $routeName ?: 'N/A'))记录
避免日志刷爆:过滤非业务请求和重复记录
直接监听 kernel.request 会捕获所有请求,包括 favicon.ico、assets、健康检查等,容易让日志文件迅速膨胀。
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- 在监听器开头加白名单判断:
if (in_array($request->getPathInfo(), ['/favicon.ico', '/robots.txt', '/health'])) { return; } - 排除 CLI 请求:
if (php_sapi_name() === 'cli') { return; } - 避免重复记录重定向或子请求:
if ($event->isMasterRequest() === false) { return; }(Symfony 2.3+ 支持) - 不要在
kernel.controller或kernel.response再记一次相同路径,否则一条请求可能写两条
服务注册必须显式声明标签,且 channel 要匹配
Symfony 2 不支持自动配置,监听器必须通过 tags 绑定到事件总线,且日志 channel 名称要和 Monolog 配置里的 channels 一致,否则日志不落地。
- 在
src/Acme/Bundle/LoggerBundle/Resources/config/services.yml中写:
acme.logger.route_listener:
class: Acme\Bundle\LoggerBundle\EventListener\RouteAccessLogger
arguments: ['@logger']
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: 0 }
- 确认你的
config.yml或monolog.yml里有对应 handler 匹配main或自定义 channel,比如:channels: ['main'],否则即使$logger->info()调用了,也不会写进文件 - 开发环境默认只输出到 console,若想写入
var/logs/dev.log,需确保 handler 的type: stream和path: "%kernel.logs_dir%/%kernel.environment%.log"已启用
路由名为空时别硬 throw,优先 fallback 到控制器+动作
很多 Symfony 2 项目用的是 controller: [Class, method] 风格路由,或者动态生成路由,_route 属性压根没设。这时候直接取会返回 null,导致日志内容断层。
- 安全写法是分层 fallback:
$route = $request->attributes->get('_route') ?: ($request->attributes->get('_controller') ?: 'unknown') - 若需更细粒度(如区分 REST 资源操作),可解析
_controller字符串,提取类名和方法,但注意性能开销 - 不要在监听器里做 DB 查询或远程调用——
kernel.request是最早期钩子,阻塞会影响所有请求
真正难调试的不是“怎么加监听器”,而是当 var/logs/dev.log 依然空着时,你得一层层查:Monolog handler 是否绑定了正确的 channel?服务标签是否拼错?arguments: ['@logger'] 对应的 service 是否存在?这些地方漏一个,日志就静默消失。


















