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

logback:如何设置每个线程的日志记录级别?

陆正德
2023-03-14

我有一个多线程Java应用程序,每个线程都是一个扩展基类的类。其中一个线程偶尔会给基类中的一个方法大量机器生成的数据,而其他线程只给出少量的人类类型数据。我想在比机器数据更高的日志级别上记录这些人类类型的消息,但是由于基类是所有线程的一部分,我无法在代码中区分出来。

一种解决方案是通知扩展类中的基类在不同的级别上登录,但是我必须将这些知识硬编码到应用程序中,这很难看。

我想做的是通过我的logback.xml配置来“引导”它。

我写了一个小型复制器:

package x.y.z;
import org.slf4j.*;

public class Quickie {
    static final Logger LOG = LoggerFactory.getLogger(Quickie.class);

    public static void main(String[] args) throws Exception {

        MyThread t1 = new MyThread("hi");
        MyThread t2 = new MyThread("bye"); 

        t1.start(); t2.start();
    }
}

class MyThread extends Thread {
    static final Logger LOG = LoggerFactory.getLogger(MyThread.class);

    public MyThread(final String name) { this.setName(name); }

    public void run() { logSomething(); }

    public void logSomething() {
        LOG.trace(getName()); LOG.error(getName());
    }
}

这是logback配置:

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true">

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%date{HH:mm:ss} %-6level %-10([%thread]) %logger{1}.%method:%line %message%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>TRACE</level>
        </filter>
    </appender>

    <root level="TRACE">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

最重要的是,编码器模式是:

            <pattern>%date{HH:mm:ss} %-6level %-10([%thread]) %logger{1}.%method:%line %message%n</pattern>

因为这清楚地显示了线程:

11:16:09 TRACE  [bye]      c.t.k.t.MyThread.logSomething:24 bye
11:16:09 TRACE  [hi]       c.t.k.t.MyThread.logSomething:24 hi
11:16:09 ERROR  [bye]      c.t.k.t.MyThread.logSomething:24 bye
11:16:09 ERROR  [hi]       c.t.k.t.MyThread.logSomething:24 hi

...我想说,应该有一种方法来配置我的logback.xml让“再见”线程只登录info或更高版本,而“嗨”线程从跟踪或更高版本登录?我花了半天时间在谷歌上搜索和阅读logback留档,我尝试了筛选器和正则表达式过滤器以及许多其他示例,但显然它们都只是继续发送消息。这意味着一种解决方案可能是让一个神奇的字符串出现在消息中并过滤掉它,但那也很难看。

那么,有没有一种方法可以从日志配置中控制每个线程的日志级别,而不必向应用程序中注入“专用代码”?

共有2个答案

沈龙光
2023-03-14

在这种情况下,我想你需要申报另一个附件

单于楚
2023-03-14

我认为可以使用MDC和TurboFilter来实现这一目的。

run()方法中添加MDC. put()的调用,如下所示:

public void run() {
    MDC.put("threadname", this.getName());
    logSomething();
}

如果您希望“bye”线程只登录info或更高版本,而“hi”线程从trace或更高版本登录,则必须在logback中添加DynamicThresholdFilter的定义。xml:

<configuration>
  <turboFilter class="ch.qos.logback.classic.turbo.DynamicThresholdFilter">
    <Key>threadname</Key>
    <!-- You can set default threshold as you like -->
    <DefaultThreshold>TRACE</DefaultThreshold>
    <MDCValueLevelPair>
      <value>bye</value>
      <level>info</level>
    </MDCValueLevelPair>
    <MDCValueLevelPair>
      <value>hi</value>
      <level>trace</level>
    </MDCValueLevelPair>
  </turboFilter>
  ......
</configuration>
 类似资料:
  • 我使用的是WebLogic10.3.6,我不能用给定的logback.xml为2个不同的追加器(com.my&root)控制不同的日志级别,我只希望文件追加器有跟踪级别,而在Weblogic终端下没有任何跟踪级别。问题是我在这两个方面得到相同的输出。

  • 我想更改我的Quarkus应用程序的日志记录级别。 如何从配置文件或运行时执行此操作?

  • 我在我的应用程序中使用Jetty http客户端。我也在使用带有logback的SLF4J。 如何将Jetty的总体日志记录级别设置为Info?

  • 我将pyspark应用程序从我自己的工作站上的pycharm启动到一个8节点集群。这个群集还有编码在spark-defaults.conf和spark-env.sh中的设置 显示未来的信息消息,但到那时已经太晚了。 如何设置spark开始时的默认日志记录级别?

  • 正如logback的文档所说,大多数appender本质上是同步的,但是如果我们将appender包装在异步appender中,那么线程将把数据推送到BlockingQueue中,如果有,比如说X-logback线程将从BlockingQueue获取数据并将其追加。这就是我对它的基本理解。 尝试使用JstackThread转储来测试这个。但是空手返回,没有回退线程的线索。 作为参考,请检查下面lo

  • ,日志记录将进入一个文件; (路径)/service_name/service_name.log 我想用logback复制这种行为,但在logback.xml配置中获取“logger”名称时遇到了真正的困难。它可以在log encoder.pattern中看到,即“%d%-5level%logger{35}-%msg%n”。