codeigniter原生log_message()不支持graylog,因其仅限文件/syslog输出,缺乏gelf序列化、udp/tcp发送及host/port/facility等必需字段控制能力,且硬改核心文件破坏升级兼容性;推荐使用monolog+graylog2/gelf-php组合实现标准对接。

CodeIgniter 本身不内置 Graylog 支持,必须通过自定义 Logger 类 + GELF 协议发送日志,直接用 monolog/monolog 是最稳妥的路径。
为什么不能直接用 CodeIgniter 原生 log_message() 推送到 Graylog
CodeIgniter 的 log_message() 只支持写文件、错误日志或 Syslog,底层没有 GELF(Graylog Extended Log Format)序列化和 UDP/TCP 发送能力。硬改 system/core/Log.php 会破坏升级兼容性,且无法控制 host、port、facility、structured extra fields 等 Graylog 必需字段。
- 原生日志通道不支持自定义 handler,扩展性差
- 缺失 GELF 封包逻辑(如
_version,_host,_timestamp字段) - UDP 发送无重试、无队列,高并发下丢日志风险高
推荐方案:用 Monolog + graylog2/gelf-php 驱动
Monolog 是 PSR-3 兼容日志库,graylog2/gelf-php 提供标准 GELF Handler,两者组合可无缝对接 Graylog。CodeIgniter 3/4 均适用,只需在启动阶段替换默认 Logger。
- 安装依赖:
composer require monolog/monolog graylog2/gelf-php - 初始化时创建 GELF Handler,指定 Graylog UDP 地址(如
udp://192.168.1.100:12201) - 把
Gelf\Handler注入到Monolog\Logger,再绑定到 CI 的$this->logger或全局log辅助函数 - 注意设置
chunk_size(建议Gelf\Transport\UdpTransport::CHUNK_SIZE_WAN),避免 UDP 包被截断
$transport = new Gelf\Transport\UdpTransport('192.168.1.100', 12201, Gelf\Transport\UdpTransport::CHUNK_SIZE_WAN);
$handler = new Gelf\Handler($transport);
$logger = new Monolog\Logger('ci-app');
$logger->pushHandler($handler);
// 后续调用 $logger->info('user login', ['user_id' => 123]); 即发往 Graylog
关键配置项与易错点
Graylog 接收端对 GELF 格式敏感,几个参数稍有偏差就会导致日志不显示或字段丢失。
-
short_message和full_message必须非空——Monolog 默认用 message 填short_message,但若只传空字符串或null,Graylog 会拒收 - 时间戳必须为 float 秒级 Unix 时间(非毫秒),
Gelf\Message内部会自动处理,但自定义setTimestamp()时别传错类型 - UDP firewall:确认 Graylog 服务器的
12201端口对 CI 应用服务器开放(不是本地 127.0.0.1) - CI 3 中若使用 HMVC,需确保每个模块加载前已初始化 Monolog 实例,避免重复连接或 handler 冲突
调试日志是否真正到达 Graylog
不要只看 PHP 是否报错——GELF UDP 发送失败通常静默丢弃。必须从 Graylog 侧验证。
- 在 Graylog Web UI 的
System / Inputs页面确认对应 UDP Input 处于Running状态,并记下Bound to地址 - 用
tcpdump抓包验证:运行tcpdump -i any udp port 12201 -w gelf.pcap,再触发一次日志,检查 pcap 是否含 payload - 临时改用
Gelf\Transport\HttpTransport(需 Graylog 开启 HTTP GELF input),HTTP 错误码(如 400/500)比 UDP 更易定位问题 - Graylog 的
System / Overview / Statistics里看Inputs / Messages received曲线是否跳变
真正麻烦的不是接入,而是字段映射一致性——比如把 CodeIgniter 的 $this->session->userdata('user_id') 显式塞进 GELF 的 _user_id 字段,否则查日志时只能靠全文检索。这需要在每次 logger->info() 调用时手动传 context 数组,没法全自动。











