簡體   English   中英

logback:如何設置每個線程的日志記錄級別?

[英]logback: how to set logging level per thread?

我有一個多線程Java應用程序,每個線程都是一個擴展基類的類,該基類擴展了Thread。 其中一個線程有時會為基類中的方法提供大量機器生成的數據,而其他線程僅會提供少量的人類類型數據。 我想在比機器數據更高的日志級別上記錄那些人類輸入的消息,但是由於基類是所有線程的一部分,因此我無法在代碼中加以區分。

一種解決方案是通知擴展類中的基類以不同的級別登錄,但是隨后我必須將該知識硬編碼到應用程序中,這很丑陋。

我想做的就是通過我的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的方法,讓“ bye”線程僅登錄信息或更高級別,而“ hi”線程則記錄來自跟蹤或更高級別的信息? 我花了半天的時間在谷歌上搜索並閱讀了logback文檔,並嘗試使用了篩選器和正則表達式過濾器以及許多其他示例,但是顯然它們只是在傳達信息。 這意味着一種解決方案可能是在消息中顯示一個神奇的字符串並過濾掉它,但這也很難看。

那么,是否有一種方法可以從日志配置中控制每個線程的日志級別,而不必在應用程序中注入“專用代碼”?

我認為您可以為此目的使用MDC和TurboFilter。

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

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

如果您想讓“ bye”線程僅登錄信息或更高級別,而“ hi”線程日志來自trace或更高級別,則必須將DynamicThresholdFilter的定義添加到logback.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>

在這種情況下,我認為您需要使用閾值信息聲明另一個appender和logger。 由於appender本身不知道從哪個線程調用它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM