当前位置: 首页 > 知识库问答 >
问题:

如何仅为具有日志返回的当前线程更改日志级别

王涵育
2023-03-14

在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(),则日志级别的更改将影响其他线程中使用的其他记录器。在这种情况下,我认为您将在其他线程上获得decifient日志。

共有1个答案

郎睿
2023-03-14

我找到了解决办法。您可以为此使用MDC和TurboFilter。MDC是线程本地的,对MDC的更改不会影响其他线程。

例如,如果要停止所有日志记录活动,必须向logback.xml添加MDCFilter的定义(请注意, 标记不能是 标记的子级,而应该是 标记的子级):

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

您可以通过将键和值放入/移除到MDC来打开/关闭日志记录,如下所示(注意,您应该考虑实际使用中的异常):

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");
    }
}
<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>
 类似资料:
  • 我一直在尝试更改用户日志的日志级别,即出现在

  • 以编程方式更改我的附加程序的日志级别,或者受到其他来源的影响。 亲爱的社区。 Log4J2版本为:2.12。0 我的应用程序正在使用log4j2。xml,日志级别设置为INFO。我的应用程序也在读取另一个配置文件,我想在其中为我的用户设置日志级别,例如DEBUG。 当应用程序初始化时(从log4j2.xml),我想将all的级别更改为DEBUG from second source作为示例。所以我

  • 我目前正在尝试降低我在java项目中使用的PDFBox 1.8.6库的日志记录级别,但失败了。基于前面的问题,我在 /src/目录中有以下log4j.properties文件。 我不确定我还遗漏了什么,因为我仍然在控制台中收到类似以下消息的垃圾邮件。 如果有一种方法可以通过编程方式更改日志级别,那么我根本不会附加到属性文件,因为我在其他任何地方都不使用log4j。我不知道它是否使用log4j。属性

  • 问题内容: 现在,我的构建过程使用MS Build从源进行构建,并在构建过程中执行自定义程序。我在程序中写入控制台的所有内容都记录在控制台输出中。 但是,我也想在用户界面的“更改”和/或“状态”部分中记录一些条目(类似于SVN所做的事情)。 如何才能做到这一点? 问题答案: // This is a deliciously convoluted and fragile hack to force

  • 我们正在开发几个部署到Azure Function Apps的Quarkus(在撰写本文时为2.5.4)应用程序。 我们注意到,我们所有的日志,无论代码的严重性如何,都在应用洞察中显示为信息。 我们已将 jboss 日志管理器添加到依赖项中: 当我检查日志时,它显示为这样。 2022-02-24T07:58:14.325[Information] 2022-02-24T07:58:14.308[I

  • 在我的Java应用程序中,我使用SLF4J+Logback进行日志记录。我在开发环境中使用调试级日志记录,在生产环境中使用错误级日志记录。但是有一些消息我无论如何都想要记录下来,无论日志级别如何(类似于,但使用的是logger)。 有什么切实可行的方法可以实现这一点吗?我可以使用error或更低的级别,但我想做的是给出一些信息,所以在语义上是错误的,它不是错误。 我可以在我的中为我的类定义另一个记