在特定类中关闭其他库的日志记录日志

joh*_*ims 17 java logging spring scheduled-tasks logback

我成功地使用Spring的@Scheduled注释每几秒执行一次方法.唯一的问题是,由于这种方法,我从Hibernate和Spring获得了很多关于事务等的日志消息.

我想保持日志记录级别相同,因为我喜欢接收应用程序中其他事务的此信息.

在执行特定方法时,是否有一种方法可以暂时禁止另一个库的日志记录?

dur*_*597 17

是的,这可以在每个线程的基础上完成.

您需要使用FiltersMDC(映射诊断上下文).此解决方案影响正在执行该@Scheduled方法的线程上发生的日志记录.

步骤概述

  1. 在您的@Scheduled方法中,向该线程的MDC添加一个条目.
  2. 创建一个实现ch.qos.logback.core.filter.Filter<ILoggingEvent>,FilterReply.DENY如果在MDC中设置了该条目,它将返回
  3. <appender>条目中添加对该过滤器的引用logback.xml

步骤1

让你的@Scheduled方法看起来像这样:

@Scheduled(fixedRate=30000)
public void scheduledMethod () {
    try{
        MDC.put("scheduled", "true");

        // Your code here
    }finally{
        MDC.remove("scheduled");
    }
}
Run Code Online (Sandbox Code Playgroud)

我应该提到删除密钥很重要,因为Spring可以重用该线程,而MDC会保留该值.

第2步

您的过滤器应如下所示:

package my.domain.application.logging;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.filter.Filter;
import ch.qos.logback.core.spi.FilterReply;

public class MDCFilter extends Filter<ILoggingEvent> {

  @Override
  public FilterReply decide(ILoggingEvent event) {    
    String scheduled = event.getMDCPropertyMap().get("scheduled");
    if ("true".equals(scheduled)) {
      return FilterReply.DENY;
    } else {
      return FilterReply.NEUTRAL;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

第3步

将以下内容添加到您的 logback.xml

<appender name="myAppender" class="ch.qos.logback.core.ConsoleAppender">
    <filter class="my.domain.application.logging.MDCFilter" />
    <!-- the rest of your appender -->
</appender>
Run Code Online (Sandbox Code Playgroud)


War*_*Dew 5

是的:您可以动态设置记录器的日志级别,从而随着时间的推移更改它。

理想情况下,您需要做的就是将记录器置于相关类层次结构的顶部,并将日志级别设置为您想要的任何级别。例如,使用休眠:

import ch.qos.logback.classic.Level
import ch.qos.logback.classic.Logger;
import org.slf4j.LoggerFactory;

// When you want to temporarily change the log level
Logger orgHibernateLogger = LoggerFactory.getLogger("org.hibernate");
Level oldLogLevel = orgHibernateLogger.getLevel();
orgHibernateLogger.setLevel(Level.ERROR); // or whatever level you want

// When you want to return to the old log level
orgHibernateLogger.setLevel(oldLogLevel);
Run Code Online (Sandbox Code Playgroud)

只要相关层次结构中的其他记录器没有明确配置日志级别,这应该可以工作。如果层次结构中的其他记录器已显式配置日志级别,则您必须临时调整所有显式设置的日志级别,然后在最后将它们全部恢复为“正常”。

请注意,这是一种基于时间的方法,而不是基于上下文的方法:如果在使用临时日志级别时其他一些代码同时使用该库,它也会获得该临时日志级别。当您恢复正常时,日志级别只会恢复到“正常”。我认为没有一种简单的方法可以避免在您使用临时日志级别时不阻止其他代码运行。

编辑:请参阅 Durron597 的答案,了解仅允许关闭所需线程中不需要的日志记录的方法。它稍微不那么简单,但看起来它应该可以工作。


gya*_*anu 5

通常,日志记录框架支持程序包级别的日志配置。您可以在logback.xml文件中执行以下操作:

<configuration>
    <logger name="org.hibernate.transaction" level="OFF"/>   // change log level to suppress here
     <logger name="org.springframework.transaction" level="OFF"/>

    <root level="ALL">
        <appender class="ch.qos.logback.core.ConsoleAppender">
            <encoder>
                <pattern>%d{ISO8601} | %-5level | %thread | %logger{1} | %m%n</pattern>
            </encoder>
        </appender>
    </root>
</configuration>
Run Code Online (Sandbox Code Playgroud)

jboss应用程序服务器中,我们之前有同样的问题,并使用程序包级日志配置过滤了不需要的日志,如下所示:

<logger category="com.lftechnology.sbworkbench">
    <level name="DEBUG"/>
</logger>
<logger category="org.quartz">
    <level name="WARN"/>
</logger>
<logger category="com.liferay.portal">
    <level name="INFO"/>
</logger>
<logger category="org.jboss.as.server.deployment">
    <level name="ERROR"/>
</logger> 
Run Code Online (Sandbox Code Playgroud)

因为您有兴趣抑制特定方法的库登录,所以您必须以编程方式进行操作并在退出时恢复。但我不确定是否会影响特定的代码块。

更多内容如果您的应用程序并发运行,则可以使用ThreadLocal,如下所示

public Class A implements Runnable {
    //you can later dynamically configure this variable also
    private static final ThreadLocal<Logger> CLASS_LOGGER = new ThreadLocal<Logger>(){
       Logger LOGGER = LoggerFactory.getLogger(A.class);
         return LOGGER;
       }

     @Override
 public void run() {
   //before calling your function change log level
   //as we declare local variable here this most likely  to affect log here only
   Logger Logger = LoggerFactory.getLogger("org.hibernate.transaction");
   Level oldLogLevel = Logger.getLevel(); 
   Logger.setLevel(Level.OFF); // 

   callYourFunction();

   //restore log level to previous
   Logger.setLevel(oldLogLevel);

 }
Run Code Online (Sandbox Code Playgroud)

在这里有类似的答案