如何在Kubernetes集群中实现Symfony应用向Graylog发送日志
解决Symfony应用日志转发到Graylog的问题
你的环境是Kubernetes集群,运行着PHP、Nginx、MySQL、Redis等Docker容器,Graylog 3负责采集所有容器的stdout和stderr日志。但PHP容器内的Symfony应用使用Monolog默认将日志写入容器内部文件,Graylog无法读取这些文件,现在需要把Symfony的所有日志(错误、警告、通知、信息等)都发送到Graylog。
先梳理你已经尝试过的方案及问题:
- 配置Monolog输出到控制台:修改
/config/packages/prod/monolog.yaml添加console和syslog_handler,但日志未输出到stdout; - 使用
error_log():可输出到控制台,但无法利用Monolog的日志捕获能力,还会导致Nginx与PHP容器重复输出日志,产生冗余; - 链接日志文件到stdout:执行
ln -sf /dev/stdout /var/www/docroot/var/log/my-log-file.log时出现文件无法打开的错误,且操作繁琐; - 通过Graylog API发送日志:是理想方案,但希望有更简便的实现方式。
接下来给出两个可行的解决方案:
方案1:修复Monolog Console Handler配置,输出到stdout
之前的配置可能存在优先级或参数错误,正确的生产环境Monolog配置应确保Console Handler正确指向stdout,并覆盖默认的文件写入逻辑。
修改config/packages/prod/monolog.yaml:
monolog: handlers: main: type: console process_psr_3_messages: true channels: ["!event"] level: debug # 设置为debug即可覆盖所有日志级别 formatter: monolog.formatter.json # 可选,用JSON格式方便Graylog解析结构化日志 # 注释或删除原有的file handler,避免重复写入文件 # file: # type: stream # path: "%kernel.logs_dir%/%kernel.environment%.log" # level: debug
注意事项:
- 确保Symfony运行在
prod环境(通过容器环境变量APP_ENV=prod设置),否则会加载其他环境的配置; - 检查Docker容器启动命令是否未重定向stdout/stderr;
- 开启
process_psr_3_messages确保所有符合PSR-3标准的日志都能被处理; - JSON格式的日志能让Graylog更方便地解析日志中的上下文数据。
方案2:使用Monolog的Gelf Handler直接发送到Graylog(推荐)
Graylog原生支持GELF(Graylog扩展日志格式)协议,通过Monolog的Gelf Handler可以直接将日志发送到Graylog的GELF输入端口,比API更简便,还能完整保留Monolog的日志上下文信息。
步骤1:安装依赖
在PHP容器内执行以下命令:
composer require monolog/monolog graylog2/gelf-php
步骤2:配置Monolog的Gelf Handler
修改config/packages/prod/monolog.yaml:
monolog: handlers: graylog: type: gelf publisher: hostname: "%env(GRAYLOG_HOST)%" # 替换为你的Graylog服务地址,比如Kubernetes内部服务名graylog-service.default.svc.cluster.local port: 12201 # Graylog默认的GELF UDP输入端口 level: debug formatter: monolog.formatter.gelf_message # 可选:添加自定义上下文字段,方便Graylog筛选 context: app_name: "symfony-app" pod_name: "%env(HOSTNAME)%" # Kubernetes容器的HOSTNAME即为Pod名称 # 可选保留console handler,同时输出到stdout和Graylog main: type: console level: debug
步骤3:在Graylog中配置GELF输入
登录Graylog后台,创建一个GELF UDP输入(也可选择TCP,需与配置一致),端口设置为12201,绑定到合适的网络接口即可。
该方案优势:
- 直接将日志发送到Graylog,无需依赖容器stdout采集,避免与Nginx日志混淆;
- 完整保留Monolog的结构化日志数据(上下文、额外字段、日志级别等);
- 配置简单,无需修改容器启动命令或文件链接。
为什么之前的Console Handler未生效?
大概率是以下原因:
- 配置优先级问题:如果同时存在file handler和console handler,file handler可能先捕获了日志,导致console无输出;
- 环境配置覆盖:检查
config/packages/monolog.yaml等全局配置是否覆盖了prod环境的配置; - 日志级别设置过高:比如设置为
error时,info、notice级别的日志不会被输出。
内容的提问来源于stack exchange,提问作者Zeth
相关产品推荐
相关产品推荐

