如何仅使用Logback更改当前线程的日志级别

时间:2017-08-31 16:18:51

标签: java logging logback

在Logback中,可以使用setLevel()方法更改记录器的日志级别。 但是在Logback中,因为记录器是单例,所以setLevel()方法的调用将影响使用相同记录器的所有其他线程。

现在我在这样的Web应用程序中使用了一个类:

class FooService {
    private void insertRecord(Foo foo) {
        // insert one record to DB
    }

    public void insertOne(Foo foo) {
        insertRecord(foo);
    }

    public void insertMany(List<Foo> foos) {
        // I want to stop logging here
        for (Foo foo: foos) {
            insertRecord(foo);
        }
        // I want to resume logging here
    }
}

在Spring ApplicationConfig.xml中:

<bean id="traceAdvice"
  class="org.springframework.aop.interceptor.CustomizableTraceInterceptor">
  <property name="enterMessage" 
    value="Entering $[targetClassShortName].$[methodName]($[argumentTypes])[$[arguments]]" />
  <property name="exitMessage" 
    value="Exiting  $[targetClassShortName].$[methodName] : return = $[returnValue] : time = $[invocationTime]ms" />
  <property name="exceptionMessage" 
    value="Exception thrown in $[targetClassShortName].$[methodName] : $[exception]" />
</bean>

<aop:config>
  <aop:pointcut id="pointcut-service" 
    expression="execution(* my.app.service..*Service.*(..))" />
  <aop:advisor advice-ref="traceAdvice" pointcut-ref="pointcut-service" />
</aop:config>

我想从insertOne方法记录insertRecord的调用。另一方面,在insertMany方法中,我想在循环之前停止记录(因为它可能输出大量的日志),并在循环之后继续记录。 但是如果在循环之前调用setLevel(),则日志级别的更改将影响其他线程中使用的其他记录器。在这种情况下,我认为你会在其他线程上获得有效的日志。

我的问题是:如何仅为当前线程中使用的记录器更改日志级别?

1 个答案:

答案 0 :(得分:2)

我找到了解决方案。您可以使用MDC和TurboFilter来实现此目的。 MDC是线程本地的,更改为MDC不会影响其他线程。

例如,如果要停止所有日志记录活动,则必须将MDCFilter的定义添加到logback.xml(请注意,<turboFilter>标记不能是<appender>的子标记标记,应该是<configuration>标记的子项:

<configuration>
    <turboFilter class="ch.qos.logback.classic.turbo.MDCFilter">
      <MDCKey>tracing</MDCKey>
      <Value>off</Value>
      <OnMatch>DENY</OnMatch>
    </turboFilter>
    ......
</configuration>

你可以通过将一个键和一个值放到/删除日志来打开/关闭日志记录(注意你应该考虑实际使用中的异常):

class FooService {
    private void insertRecord(Foo foo) {
        // insert one record to DB
    }

    public void insertOne(Foo foo) {
        insertRecord(foo);
    }

    public void insertMany(List<Foo> foos) {
        // I want to stop logging here
        MDC.put("tracing", "off");
        for (Foo foo: foos) {
            insertRecord(foo);
        }
        // I want to resume logging here
        MDC.remove("tracing");
    }
}

或者,如果要停止TRACE / DEBUG / INFO / WARN日志但保留ERROR日志,则可以使用DynamicThresholdFilter:

<configuration>
    <turboFilter class="ch.qos.logback.classic.turbo.DynamicThresholdFilter">
      <Key>tracing</Key>
      <DefaultThreshold>TRACE</DefaultThreshold>
      <MDCValueLevelPair>
        <value>off</value>
        <level>ERROR</level>
      </MDCValueLevelPair>
    </turboFilter>
    ......
</configuration>