当前位置: 首页 > news >正文

记录一次日志告警随着nacos文件动态刷新而失效的问题

           事情是这样的:我把告警的配置修改成了随着nacos动态更新的,但是更新后日志异常告警却不打印了。刚开始怀疑是不是网络或者nacos配置的问题,经过复现发现是因为我每次修改完nacos动态配置后,我的日志组件TurboFilter 是基于日志logback,他不是spring的bean的方式加载的,而nacos的动态更新需要bean是spring的,当我在nacos更新后,日志组件没有动态加载导致失效了。

 

   我的原来的代码:

      

/*** 异常日志堆栈-用于非运行时异常的告警提示* @author fanht* @date 2022-03-21  17:28* @versio 1.0*/
@Component
public class MarketingLogFilter extends TurboFilter {/**rocketmq异常信息打印*/private static final String ROCKETMQ_ERROR = "rocketmq";@Resourceprivate SimpleBufferTriggerUtils simpleBufferTriggerUtils;@Resourceprivate OptionalAlarmUriUtils optionalAlarmUriUtils;@Resourceprivate DingdingAlarmUtil dingdingAlarmUtil;@Overridepublic FilterReply decide(Marker marker, Logger logger, Level level, String s, Object[] objects, Throwable throwable) {if(logger.getName().contains("rocketmq")){System.out.println("mq error:" + (Optional.of(logger).map(l->l.getName()).orElse(null))+ ",throwable:" + Optional.ofNullable(throwable).map(t->t.getMessage()).orElse(null));}if(dingdingAlarmUtil==null){dingdingAlarmUtil = ApplicationContext.getBean(DingdingAlarmUtil.class);}//todo 如果是非运行时异常 发送钉钉告警。排除运行时异常if(throwable != null && StringUtils.isNotEmpty(throwable.getMessage()) && level.equals(Level.ERROR)){if(optionalAlarmUriUtils == null){optionalAlarmUriUtils = ApplicationContext.getBean(OptionalAlarmUriUtils.class);}if(!optionalAlarmUriUtils.isExistUri(logger.getName())){if(simpleBufferTriggerUtils == null){simpleBufferTriggerUtils =  ApplicationContext.getBean(SimpleBufferTriggerUtils.class);}simpleBufferTriggerUtils.proceErrorAlarm(Tag.builder().applicationName(dingdingAlarmUtil.getApplicationName()).env(dingdingAlarmUtil.getEnv()).ip(IpUtil.initIp()).traceId(MDC.get(TraceUtils.TRACE_ID)).requestUri(logger.getName()).exMessage(JSONObject.toJSON(throwable.getMessage().length() >500 ?throwable.getMessage().substring(0,500).toString():throwable.getMessage()).toString()).build());}}else if(Level.ERROR.equals(level) && logger.getName().contains(ROCKETMQ_ERROR)){//如果是mq的异常 也要进行告警if(!optionalAlarmUriUtils.isExistUri(logger.getName())){String exMessage = Optional.ofNullable(s).orElse("") + Optional.ofNullable(objects).map(t->t[0]).orElse(null);simpleBufferTriggerUtils.proceErrorAlarm(Tag.builder().applicationName(dingdingAlarmUtil.getApplicationName()).env(dingdingAlarmUtil.getEnv()).ip(IpUtil.initIp()).requestUri(logger.getName()).traceId(MDC.get(TraceUtils.TRACE_ID)).exMessage(Optional.ofNullable(exMessage).map(t->t.length()>500?t.substring(0,500):t).orElse("")).build());}}//todo 如果接入kafka,则此处需要需要改为NEUTRAL,以防止kakfa的多次打印return FilterReply.NEUTRAL;}
}

 

         

 

 

      

Spring Cloud 的 Logging Refresh 会重建 Logback 上下文

当你调用 /actuator/refresh(或 Nacos 自动触发 refresh)时,Spring Cloud 会刷新 logging 相关配置(如 logging.level.*logging.file.name 等)。

而 Logback 的实现方式是:重建整个 LoggerContext

这意味着:

  • 原有的 LoggerContext 被关闭
  • 所有已注册的 AppenderTurboFilterLogger 都被清除
  • 创建一个新的 LoggerContext
  • 重新加载 logback-spring.xml

 

         

这就是为什么刷新后 decide() 完全不执行 —— filter 根本不在新上下文中。


✅ 解决方案:监听 LoggerContext 重建事件,自动重新注册

Logback 提供了 LoggerContextListener 机制,但更简单的方式是:监听 Spring 的 ApplicationEnvironmentPreparedEventContextRefreshedEvent 不行,因为 logging refresh 是独立的。

正确做法:监听 Logback 自身的 ContextResetEvent

但 Spring Boot 封装了 Logback,我们可以通过 监听 Spring 的 LoggingApplicationListener 行为 来间接处理。

不过最可靠、最通用的方法是:

每次 Logback 初始化时自动注册你的 TurboFilter

✅ 推荐方案:自定义 LoggerContextListener

创建一个 Logback 的 listener,在每次上下文初始化时注册 filter:

  

 最佳方案(不改 XML):

监听 RefreshScopeRefreshedEvent,并在新 LoggerContext 初始化后重新注册 TurboFilter

关键点:

  • Spring Cloud 在 /actuator/refresh 后会发布 RefreshScopeRefreshedEvent
  • 此时 Logback 的 LoggerContext 可能已经被重建
  • 我们可以在事件监听器中 重新获取当前 LoggerContext 并注册 filter

 

 

Component
public class TurboFilterReRegistrar {private final MarketingLogFilter marketingLogFilter;public TurboFilterReRegistrar(MarketingLogFilter marketingLogFilter) {this.marketingLogFilter = marketingLogFilter;}/*** 监听 Refresh 完成事件(包括 Nacos 配置刷新)*/@EventListenerpublic void handleRefresh(RefreshScopeRefreshedEvent event) {reRegisterTurboFilter();}/*** 也监听 Context Refreshed(兜底,确保启动时也注册)*/@EventListenerpublic void handleContextRefreshed(ContextRefreshedEvent event) {reRegisterTurboFilter();}private void reRegisterTurboFilter() {try {ILoggerFactory factory = LoggerFactory.getILoggerFactory();if (factory instanceof LoggerContext) {LoggerContext context = (LoggerContext) factory;// 检查是否已存在,避免重复注册(TurboFilter 没有 equals/hashCode,简单用类型判断)boolean alreadyRegistered = context.getTurboFilterList().stream().anyMatch(f -> f.getClass() == MarketingLogFilter.class);if (!alreadyRegistered) {context.addTurboFilter(marketingLogFilter);System.out.println("✅ Re-registered MarketingLogFilter after refresh");} else {// 如果已存在,可能是同一个实例,无需操作System.out.println("ℹ️ MarketingLogFilter already registered");}}} catch (Exception e) {System.err.println("❌ Failed to re-register TurboFilter: " + e.getMessage());e.printStackTrace();}}
}

 

http://www.zskr.cn/news/175636.html

相关文章:

  • Safeguard Global名义雇主EOR:2026助力出海企业快速合规雇佣加拿大员工 - 品牌2025
  • 防脱发洗发水哪个牌子好?十大防脱发洗发水推荐,解决脱发困扰 - 博客万
  • langchain4j 构建agent工作流
  • 普通人能进军网络安全行业吗?过来人手把手支招,帮你躲开这 5 个误区!
  • 2025年质量好的复合井盖公司推荐:双层井盖、变电站室外电缆沟盖板、复合井盖、复合树脂井盖、复合盖板、成品复合电缆沟盖板选择指南 - 优质品牌商家
  • 0335-Tetris-渲染方块
  • 计算机专业大学生必读:CTF 比赛值得打吗?一文讲透参赛要求与获奖好处!
  • 深入浅出解析具身智能:技术栈、实践案例与代码实现
  • 【Java毕设全套源码+文档】基于springboot的个性化推荐影院网站设计与实现(丰富项目+远程调试+讲解+定制)
  • 【Java毕设全套源码+文档】基于springboot的小型民营加油站管理系统设计与实现(丰富项目+远程调试+讲解+定制)
  • YOLOv11模型权重文件下载地址汇总
  • SSH X11转发显示PyTorch可视化图形
  • 我惊了!别再吹人类独有创造力了!Nature子刊:在这项测试中,LLM已经碾压人类!
  • SDET vs 测试开发工程师:数字化时代的测试角色进化论
  • 分龄护肤,以专业水光技术与光电保养,为肌肤注入冬日“热水” - 速递信息
  • 2025智能清洁设备TOP5权威测评:智然达智能清洁设备可以信任吗? - 工业推荐榜
  • 观Ace Studio定价争议一事有感而发,随便聊聊
  • 李易泽
  • Transformer自注意力机制可视化工具推荐
  • 红日靶场1
  • 多GPU训练踩坑总结:NCCL timeout错误规避方法
  • 2025年油压机厂家权威推荐榜:单臂/二梁四柱/伺服/C型/龙门油压机源头厂家精选 - 品牌推荐官
  • 为什么PyTorch-CUDA镜像更适合生产环境部署?
  • 国产操作系统课程实战:Vim 编辑器从入门到高效编程
  • 帅邦油烟机满意度怎么样?烟机实力及创新能力评测排名 - 工业品牌热点
  • 2026北京房山区继承律师事务所口碑排名白皮书——权威解析靠谱律所选择指南 - 苏木2025
  • 2025年重庆三角洲升级陪玩服务商推荐榜:重庆哈基桃文化传媒,三角洲陪练俱乐部/三角洲陪玩/三角洲陪练升级/三角洲行动陪玩/三角洲陪玩俱乐部服务商精选 - 品牌推荐官
  • Docker 部署 OpenVidu
  • 华美食品性价比好不好?专业度/规模年度排名,5大烘焙品牌深度测评推荐 - mypinpai
  • PyTorch官方发布v2.7更新亮点及对CUDA的支持改进