java 单机接口限流处理方案
446
2022-10-01
Logback 使用TurboFilter实现日志级别等内容的动态修改操作
目录Logback TurboFilter实现日志级别等内容的动态修改为什么要通过TurboFilter去动态的修改日志级别logback动态设置某个类的日志级别假设一下,现在有这么个情况于是就有了下面的方案
Logback TurboFilter实现日志级别等内容的动态修改
可能看到这个标题,读者会问:要修改日志的级别,不是直接修改log.xxx就好了吗?为何要搞那么复杂呢?所以,先说一下场景
为什么要通过TurboFilter去动态的修改日志级别
我们在使用java开发各种项目的时候必然的会引入很多框架,这些框架通过堆叠的方式完成所要提供的业务服务(一个服务请求在进入后会在这些框架中兜一圈,然后返回结果),当一个比较底层的框架在处理过程中抛出了异常之后,这个异常会不断的向上传递。
这个时候,有的框架直接throw,继续向上抛,而有的在throw之前还会自己打印一下error日志,这就导致了当出现异常的时候,往往会出现一连串类似的错误日志记录。如果对接了错误日志告警,就会出现重复告警的现象。为了解决类似这样的问题,修改源码重新编译最直接,但是不可取。
所以希望可以有更好的手段去控制这些已经被编码固化的日志打印信息。当我们使用Logback的时候,TurboFilter就是解决该问题的工具之一。
TurboFIlter不同于之前在[《Logback中如何自定义灵活的日志过滤规则》]一文中介绍的那些通过ch.qos.logback.core.filter.Filter接口实现的过滤器。ch.qos.logback.core.filter.Filter实现的过滤器是与Appender绑定的,而TurboFIlter是与日志上下文绑定的,它会过滤所有的日志请求,并且TurboFIlter的方法中提供了丰富的可访问信息用来进行控制和改写。
比如下面的实现,通过继承ch.qos.logback.classic.turbo.TurboFilter类,并重写decide方法,将org.springframework.cloud.sleuth.instrument.web.ExceptionLoggingFilter类中原本要打印的ERROR日志DENY掉(过滤掉),同时以WARN级别打印一封相同的内容,这样就实现了对已定义日志的动态修改。
public class ForceWarnFilter extends TurboFilter {
@Override
public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable throwable) {
if (level == Level.ERROR && logger.getName().equals("org.springframework.cloud.sleuth.instrument.web.ExceptionLoggingFilter")) {
logger.warn(marker, format, params);
return FilterReply.DENY;
}
return FilterReply.NEUTRAL;
}
}
为了让上面定义的过滤器生效,需要在logback的配置xml中增加如下配置:
......
或者也可以在应用主类中增加:
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
lc.addTurboFilter(new MyTurboFilter());
更多关于Logback过滤器的内容可参考官方文档
logback动态设置某个类的日志级别
假设一下,现在有这么个情况
你调别人的接口出问题了,但是怎么排查都定位不了原因。只能借助更详细的日志信息,这个时候,又不想把全局的日志级别调低,毕竟调低对并发量大的应用来说,瞬间会涌出很多很多日志信息。
最好的情况就是,只调整出问题的那个类的日志级别。那怎么办呢?
于是就有了下面的方案
定向修改某个class的logger日志级别。
public void testLog(String key, String level, String level2){
LoggerContext loggerContext= (LoggerContext) LoggerFactory.getILoggerFactory();
//设置全局日志级别
ch.qos.logback.classic.Logger logger=loggerContext.getLogger("root");
logger.setLevel(Level.toLevel(level));
if (!StringUtils.isBlank(level2)) {
//设置某个类日志级别-可以实现定向日志级别调整
ch.qos.logback.classic.Logger vLogger = loggerContext.getLogger(key);
if (vLogger!=null)
vLogger.setLevel(Level.toLevel(level2));
}
List
for (chmjthc.qos.logback.classic.Logger logger1 : loggerList){
log.info(logger1.getName());
}
}
比如:
level = ERROR
level2 = INFO
key = "com.duy.soo.web.controller.TestController"
表示把全局日志级别设置为ERROR级别,单独把com.duy.soo.web.controller.TestController类的日志设置为INFO级别。
/**
* @Author changle
* @Time 17/6/30.
* @Desc to do
*/
@Slf4j
@Controller
@RequestMapping(value = "/api/test")
public class TestController {
@RequestMapping("/testDebug")
@ResponseBody
public Response
//打印日志级别
String rtn = "this is a INFO";
log.info(rtn);
rtn = "this is a ERROR";
log.error(rtn);
rtn = "this is a DEBUG";
log.debug(rtn);
Response
return response;
}
}
如此一来,除了com.duy.soo.web.controller.TestController类以外的其他类,都只输出ERROR日志,而TestController类能输出INFO日志信息。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~