必须在kernel.request事件中提取客户端IP和路由名并注入日志上下文,通过RequestStack获取请求对象,再由IpAndRouteProcessor塞入$record['context'],确保每条日志自动携带;异常时在onKernelException中调用getCurrentRequest()补全上下文,避免序列化异常对象。

直接在日志中记录客户端 IP 并关联到具体路由和异常路径,不是靠改日志格式就能实现的——必须把 $request 的信息主动注入到日志上下文里,否则 Monolog 默认不带 IP,kernel.exception 事件里也拿不到完整请求路径。
如何让每条日志都自动带上 client IP 和当前匹配的路由名
Monolog 本身不解析请求,也不会自动绑定路由信息。得靠自定义处理器或上下文填充器:
- 在
src/EventListener/RequestContextListener.php中监听kernel.request事件,从$event->getRequest()提取$request->getClientIp()和$request->attributes->get('_route') - 把这两个值存进
RequestStack或写入RequestContext(推荐用RequestStack::getCurrentRequest()安全获取) - 再通过
Processor注入到所有日志:创建类src/Log/IpAndRouteProcessor.php,__invoke()方法里调用$this->requestStack->getCurrentRequest()拿数据,塞进$record['context'] - 在
config/packages/dev/monolog.yaml中注册该 processor:processors: ['App\Log\IpAndRouteProcessor']
注意:如果请求没走到内核(比如 404 被 Web 服务器直接拦截),kernel.request 不会触发,IP 和路由就为空——这不是代码问题,是请求生命周期决定的。
当代理已经知道网站路由或内容URL,并且在启动前需要有效的sitemap XML、sitemap索引或robots.txt引用时,请使用sitemap。这是一个发布构件技能,而不是爬虫或SEO平台。
为什么 router:match /xxx 显示匹配成功,但日志里看不到对应路由名
因为 router:match 是 CLI 命令,在独立 HTTP 上下文中运行,不走完整请求栈;而日志里的 _route 来自实际 HTTP 请求的 Request 对象属性。两者环境隔离:
-
php bin/console router:match /login只模拟路由匹配,不触发kernel.request事件,也不设置RequestStack - 真实访问时若出现 404,说明路由没匹配上,
_route属性根本不会被设值,日志上下文里自然为空 - 想验证路由是否真被加载,用
php bin/console debug:router | grep login看输出是否存在,比router:match更可靠
捕获异常时如何确保 IP 和原始请求路径不丢失
在 kernel.exception 监听器中,$event->getRequest() 是可用的,但要注意时机:
- 不要在监听器构造函数里提前依赖
RequestStack,它可能还没初始化;应在onKernelException()方法体内调用$this->requestStack->getCurrentRequest() - 若异常发生在路由匹配前(如 Host 不匹配、HTTPS 强制跳转失败),
$request->attributes->get('_route')为null,但$request->getPathInfo()和$request->getClientIp()依然有效 - 记录时显式拼装上下文:
$logger->error('Exception on {path} from {ip}', ['path' => $request->getPathInfo(), 'ip' => $request->getClientIp(), 'exception' => $e]) - 避免直接传
$e进 context 数组——Monolog 会尝试序列化,可能抛新异常;改用$e->getMessage()和$e->getTraceAsString()
真正难处理的是那些连 kernel.request 都没进来的请求,比如 Nginx 返回的 499(client closed request)或 PHP-FPM 超时。这些压根不会触发 Symfony 日志,得去查 Web 服务器 access log 和 error log 对齐时间戳。


















