如何解决Erlang中Lager与OTP Logger的日志冲突问题?
解决Erlang原生logger与Lager日志冲突的思路
这问题我之前帮不少开发者排查过,核心原因确实是Lager的默认行为会接管Erlang VM的日志处理管道——它启动时会把原生logger的默认处理器给替换掉,导致你自己用logger打的日志没地方输出。下面给你几个可行的解决思路:
1. 配置Lager与原生logger共存
Lager从较新版本开始支持兼容Erlang原生logger,你只需要在项目的sys.config(或者启动参数)里添加针对性配置,让Lager不要完全接管日志管道,而是和原生logger和平共处:
[{lager, [ {handlers, [ {lager_console_backend, [{level, info}]}, % 这里可以添加你需要的其他Lager后端,比如文件后端 ]}, {logger_compat_mode, true}, % 关键:开启原生logger兼容模式 {error_logger_redirect, false} % 避免把error_logger的日志全部转向Lager ]}, {logger, [ {handlers, [ {default, logger_std_h, #{level => info}} % 保留原生logger的默认控制台处理器 ]} ]}].
配置完成后,Lager会处理自身及amqp_client的日志,而你用原生logger输出的内容也能通过默认处理器正常打印。
2. 手动恢复原生logger处理器
如果Lager已经启动并替换了原生处理器,你可以在项目应用的初始化代码里强制恢复原生logger的处理器。比如在你的应用启动模块(如my_app.erl)的start/2函数中添加这段逻辑:
start(_StartType, _StartArgs) -> % 检查原生logger的默认处理器是否存在,不存在则添加 case logger:get_handler(default) of {error, not_found} -> logger:add_handler(default, logger_std_h, #{level => info}); _ -> ok end, % 启动应用监督树 MyAppSup:start_link().
这种方法比较直接,不管Lager的默认行为如何,都能确保原生logger的输出通道正常。
3. 调整amqp_client的日志后端
如果你的项目不需要Lager的日志功能,只是因为amqp_client依赖才引入它,那可以尝试让amqp_client直接使用原生logger输出日志。在sys.config里添加如下配置:
[{amqp_client, [ {log_backend, logger} % 指定amqp_client使用原生logger作为日志后端 ]}].
如果这个配置不生效,还可以在rebar.config里调整依赖顺序,让你的应用先初始化原生logger,再启动Lager;或者把Lager标记为可选依赖,避免它自动启动接管日志。
额外注意点
- 确认你使用的Lager版本,部分旧版本可能没有
logger_compat_mode这个配置项,建议升级到较新的稳定版。 - 测试时可以分别用
logger:info("Test native logger")和lager:info("Test Lager")打印日志,验证两者都能正常输出。
内容的提问来源于stack exchange,提问作者J.J.J
相关产品推荐
相关产品推荐

