基於log4j的消息流的實現之一消息獲取

需求:html

目前的程序中都是基於log4j來實現日誌的管理,想要獲取日誌中的一部分消息,展現給用戶。java

約束:apache

因爲程序中除了本身開發的代碼,還會有層層依賴的第三方jar中的日誌輸出。須要展現給用戶的消息,也有部分包括在第三方的包中。不可能去修改第三方jar來得到消息,因此只能從Log4j自己的消息入手,獲取log4j的消息來進行處理。api

方案:session

第一步,增長新的loggerapp

 1 log4j.rootLogger=INFO, console
 2 
 3 log4j.appender.console=org.apache.log4j.ConsoleAppender
 4 log4j.appender.console.layout=org.apache.log4j.PatternLayout
 5 log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %-20c %X{key}  %x - %m%n
 6 
 7 log4j.logger.hermes=INFO, hermes
 8 log4j.appender.hermes=org.apache.log4j.ConsoleAppender
 9 log4j.appender.hermes.layout=org.apache.log4j.PatternLayout
10 log4j.appender.hermes.layout.ConversionPattern=%X{key} %x  %m%n
11 
12 log4j.logger.org.apache.flink.yarn=INFO, hermes

如上,第1行定義了一個全局的logger,這個沒有疑義,全部的日誌都會輸出到這個logger。ide

關鍵是第7行,又定義了一個叫hermes的logger,它有一個同名的appender叫hermes,簡化了他的layout,只是拿出必須的輸出日誌便可。注意這裏有一個%X{key}的配置項,這裏是爲了拿到MDC的值,好區分這條消息是哪一個session打印出來的。函數

第12行也很關鍵,將包org.apache.flink.yarn的日誌都按照hermes是標準輸出,這裏是包名,固然也能夠指定到具體的類名。ui

如此這樣,對於包org.apache.flink.yarn中的日誌,會打印兩份,一份是以console的形式輸出,一份是以hermes的形式輸出。this

固然,咱們不但願在日誌中見到兩行實質上同樣的內容,這就是第二步要作到事情。

第二步:截取消息

這裏有兩個方案:一個方案是自定義appender,獲取消息;一個方案是獲取指定的logger,獲取消息。

方案1:自定義appender

 1 import org.apache.log4j.AppenderSkeleton;
 2 import org.apache.log4j.LogManager;
 3 import org.apache.log4j.spi.LoggingEvent;
 4 import org.slf4j.Logger;
 5 import org.slf4j.LoggerFactory;
 6 
 7 public class AdapterAppender extends AppenderSkeleton {
 8     @Override
 9     protected void append(LoggingEvent loggingEvent) {
10         String message = this.layout.format(loggingEvent);
11         System.out.println("<<<<<<<<<<***********"+message+"***********>>>>>>>>>>");
12     }
13 
14     @Override
15     public void close() {
16 
17     }
18 
19     @Override
20     public boolean requiresLayout() {
21         return true;
22     }
23 }

自定義appender仍是很簡單的,只要繼承AppenderSkeleton便可。其中的append方法就能夠拿到日誌消息,標準化以後就能夠拿來用了。

固然,上面log4j的配置也就須要改下了:

log4j.appender.hermes=cn.123.flink.log.AdapterAppender

方案2:獲取logger來獲取消息

 1 import java.io.IOException;
 2 import java.io.PipedReader;
 3 import java.io.PipedWriter;
 4 import java.io.Writer;
 5 import java.util.Scanner;
 6 
 7 import org.apache.log4j.*;
 8 
 9 public class LogAppender extends Thread{
10 
11     private PipedReader reader;
12 
13     public LogAppender(String appenderName) {
14         try {
15             Logger root = Logger.getLogger(appenderName);
16             // 獲取子記錄器的輸出源
17             Appender appender = root.getAppender(appenderName);
18             // 定義一個未鏈接的輸入流管道
19             reader = new PipedReader();
20             // 定義一個已鏈接的輸出流管理,並鏈接到reader
21             Writer writer = new PipedWriter(reader);
22             // 設置 appender 輸出流
23             ((WriterAppender) appender).setWriter(writer);
24         }catch (IOException ioe){
25             ioe.printStackTrace();
26         }
27     }
28 
29     @Override
30     public void run() {
31         // 不間斷地掃描輸入流
32         Scanner scanner = new Scanner(reader);
33         // 將掃描到的字符流顯示在指定的JLabel上
34         while (scanner.hasNextLine()) {
35             try {
36                 String line = scanner.nextLine();
37                 System.out.println("*****************************"+line);
38                 //睡眠
39                 Thread.sleep(100);
40             } catch (Exception ex) {
41                 System.out.println("Exception from LogAppender:"+ex.getMessage());
42             }
43         }
44     }
45 }

 

對比上面的日誌的配置,13行的構造函數就能夠傳入hermes來獲取hermes這個logger。

 

參考了下面的文檔:

http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html

http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/MDC.html

http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/NDC.html

https://logging.apache.org/log4j/2.x/manual/thread-context.html

http://yshjava.iteye.com/blog/1325036

https://stackoverflow.com/questions/2763740/log4j-log-output-of-a-specific-class-to-a-specific-appender

https://stackoverflow.com/questions/5549838/get-live-log4j-messages

https://sysgears.com/articles/how-to-redirect-stdout-and-stderr-writing-to-a-log4j-appender/

相關文章
相關標籤/搜索