symfony项目中需通过monolog配置多环境、多通道日志系统:prod环境用rotating_file_handler按天轮转日志,跳过event/doctrine;为支付告警和订单归档建独立通道;dev环境启用console+firephp调试;控制器中注入指定通道loggerinterface并传结构化上下文。

在 Symfony 项目中搭建可扩展、可分级、可路由的日志系统,需通过 Monolog 配置实现日志写入文件、控制台输出、错误告警等不同通道,且必须区分 dev/test/prod 环境行为。
启用并确认 Monolog 已加载
Symfony 5.4+ 默认已集成 monolog-bundle,无需手动安装。检查 config/bundles.php 中是否存在 MonologBundle::class => ['all' => true] —— 若缺失,手动添加这一行。
运行 php bin/console debug:container --parameter=monolog.logger,若返回参数值,说明 Monolog 已激活。
配置基础日志通道(prod 环境)
编辑 config/packages/prod/monolog.yaml(若不存在则新建):
定义主日志器使用 【rotating_file_handler】,按天轮转、保留 30 天、单文件上限 100MB,避免磁盘被撑爆:
handlers:
main:
type: rotating_file
path: "%kernel.logs_dir%/%kernel.environment%.log"
max_files: 30
max_size: "100MB"
level: info
channels: ["!event", "!doctrine"]
这一步跳过 event 和 doctrine 日志,防止日志爆炸——它们默认级别太高,且已有专用通道。
为关键业务单独建通道
比如支付失败要实时钉钉告警,订单创建需独立归档。在 config/packages/monolog.yaml 中追加:
handlers:
payment_alert:
type: fingers_crossed
action_level: error
handler: slack
buffer_size: 10
order_log:
type: stream
path: "%kernel.logs_dir%/orders.log"
level: info
注意:【fingers_crossed handler 必须配合下游 handler(如 slack)才能生效】,单独写它不会发消息。
然后把通道绑定到服务:loggers:
payment:
type: service
id: Monolog\Logger
arguments: ['payment']
calls:
- [pushHandler, ['@monolog.handler.payment_alert']]
开发环境快速调试配置
在 config/packages/dev/monolog.yaml 中关闭文件写入,改用 console + firephp(若浏览器装了 FirePHP 插件):
handlers:
console:
type: console
process_psr_3_messages: false
verbosity_levels: { VERBOSITY_VERBOSE: debug, VERBOSITY_VERY_VERBOSE: debug }
firephp:
type: firephp
level: debug
这样 $this->logger->debug('user_id: '.$user->getId()) 会直接出现在终端和浏览器控制台,不用翻日志文件。
在控制器中使用自定义日志器
第一步:声明服务依赖,在控制器构造函数中注入:
public function __construct(LoggerInterface $logger, LoggerInterface $orderLogger)
第二步:用类型提示明确指定通道名,Symfony 自动匹配 monolog.logger.order 服务:
#[Autowire('monolog.logger.order')] private LoggerInterface $orderLogger;
第三步:调用时传结构化上下文,别拼字符串:
$this->orderLogger->info('Order created', [
'order_id' => $order->getId(),
'user_id' => $user->getId(),
'amount' => $order->getTotal()
]);
这能让日志解析工具(如 ELK)自动提取字段,而不是在文本里正则匹配。











