Symfony日志配置以Monolog内置处理器为主,90%场景无需手写类;通过YAML配置rotating_file、fingers_crossed等处理器及web、token等Processor即可满足需求;自定义Handler仅在对接Kafka等特殊场景下才需继承AbstractProcessingHandler并注册服务。

Symfony日志处理器不是靠“手写类”起步的,而是先配好 Monolog 的 Handler(处理器)和 Processor(预处理组件),再按需定制。默认已集成大量开箱即用的处理器,90% 场景无需自己写代码。
直接配置现成处理器最常用
Monolog Bundle 提供了十几种内置 Handler,比如 rotating_file、stream、fingers_crossed、syslog、deduplication 等。你只需在 YAML 里声明类型和参数:
-
按天轮转写文件:用
rotating_file,路径自动加日期后缀(如app-2026-05-12.log),超max_files自删旧文件 -
错误触发才落盘:用
fingers_crossed+nested组合,避免 INFO 日志刷爆磁盘 -
过滤重复告警:加
deduplicationHandler,相同错误 5 分钟内只记一次 -
发邮件告警:配
swift_mailerHandler(需装 Symfony Mailer)
加 Processor 补充上下文信息
Processor 不是“写日志”,而是在日志写入前给每条记录动态加字段,比如用户 ID、请求 ID、内存用量。Symfony 已带多个实用 Processor:
-
TokenProcessor:自动附加当前登录用户 token(含用户名、角色) -
SwitchUserTokenProcessor:管理员切换用户时,同时记下原始管理员身份 -
WebProcessor:补上客户端 IP、URL、HTTP 方法等请求信息 -
IntrospectionProcessor:加文件名、行号、函数名,方便定位代码位置
启用方式很简单,在 handler 配置里加 processors 列表即可:
Miller (mlr) 是一个命令行工具,用于查询、整形和重新格式化名称索引数据,如 CSV、TSV、JSON 和 JSON Lines。它将 awk、sed、cut、join 和 sort 的功能整合到一个专为结构化数据处理而构建的单一工具中。
handlers:
file:
type: rotating_file
path: '%kernel.logs_dir%/app.log'
level: debug
processors: ['web', 'token', 'introspection']
真要自定义 Handler?继承并注册
只有当内置 Handler 完全不满足需求时(例如:把日志推到 Kafka、写进 Redis Stream、对接内部审计平台),才需要写自己的 Handler 类:
- 类必须实现
Monolog\Handler\HandlerInterface或继承AbstractProcessingHandler - 重写
write()方法,定义怎么处理单条日志记录 - 在
config/services.yaml中注册为服务,并打上monolog.handler标签 - 再在
monolog.yaml的handlers下引用该服务 ID
注意:不要试图在 Handler 里做耗时操作(如远程 HTTP 请求),否则会拖慢整个请求;高频场景建议用异步队列中转。
常见配置陷阱要避开
很多“写了没日志”问题其实出在配置逻辑上,不是代码错:
-
channels写在 handler 下,意思是“这个 handler 接收哪些 channel 的日志”,不是“它属于哪个 channel”——漏写['main']就等于主日志流被切断 -
kernel.debug: false(生产环境)时,debug级别日志会被内核全局拦截,即使 handler 设了level: debug也无效 - 路径必须用
'%kernel.logs_dir%/xxx.log',写logs/app.log会落到项目根目录,不是var/log/ - Symfony 6+ 要求每个 handler 显式声明
channels,不能再用老式handlers: [console, file]简写

















