logback自定義Appender和Layout

logback自定義Appender和Layout

@Date 2017.05.09

  • Appender是logback中最重要的組件之一,它委託encoder組件來完成LoggingEvent的格式化和記錄,具體源碼分析網上有很多, 本文主要是應用實踐.
  • Layout組件來將LoggingEvent進行格式化,返回一個String,然後通過OutputStream.write()方法,把格式化之後的日誌信息寫到目的地.

繼承RollingFileAppender,重寫輸出文件格式

  1. 場景

工程中期望輸出到日誌中的是JSON格式, 但是在業務中log.info(變量),此變量會有帶引號的情況下, 會影響最終輸出結構,因爲重寫file appender.

  1. logback.xml
<encoder>-->
    <charset>UTF-8</charset>
    <pattern>{"time":"${bySecond}","level":"%-5level","msg":"%msg"} %n</pattern>-->
</encoder>

%msg是logback輸出的日誌內容,此字符串如果本身帶引號,則造成輸出到日誌文件裏的JSON格式無法解析.

  1. 解決辦法
  • 集成logback默認的RollingFileAppender,獲取msg內容並做格式化替換
  • 在logback.xml中<appender class="替換自定義的Appender"/>
public class UserFileAppender extends RollingFileAppender<ILoggingEvent> {
    @Override
    protected void subAppend(ILoggingEvent event){
        // 獲取event中的message內容
        event.getFormattedMessage().replace("\"","\\\"");
        start();
        super.subAppend(event);
    }
}

進階:異步處理log.xxxx()日誌

  1. 場景

當在程序中輸出了一些日誌,並期望對這些日誌內容做特定處理(存儲DB/解析發送消息等)

  1. 集成UnsynchronizedAppenderBase
public class TransportDBLoggerAppender extends UnsynchronizedAppenderBase<ILoggingEvent> {
    
    @Override
    public void append(ILoggingEvent event) {
        try {
            String content = event.getFormattedMessage();
            Map<String, String> map = new HashMap<>();
            map.put("LOG_LEVEL", event.getLevel().levelStr);
            map.put("CONTENT", content.replace("'", "''"));
            // 處理邏輯
        } catch (Exception e) {
            System.err.println(e);
        }
    }
}
  • 上述代碼繼承了UnsynchronizedAppenderBase,重寫了append方法,裏面可以根據event對象獲取log中的內容和默認的系統提供的參數(level等),可以在此做各種業務邏輯, 此內容是異步操作,節省我們在工程上自己構建異步日誌收集等工作量,適合小應用的場景.

Layout:自定義日誌輸出格式

  1. 場景

在上述場景中發現只輸出msg還不夠滿足業務的需求,業務裏有需要把MDC存儲的上下文也加到輸出的JSON日誌中,因此使用了layout自定義輸出.

  1. logback.xml
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
    <layout class="自定義layout類" />
</encoder>
  1. Java
public class LoggingConsoleLayout extends LayoutBase<ILoggingEvent> {

    @Override
    public String doLayout(ILoggingEvent event) {
        StringBuilder sbuf = new StringBuilder();
        if (null != event && null != event.getMDCPropertyMap()) {
            sbuf.append("{");

            sbuf.append("\"time\":\"");
            sbuf.append(System.currentTimeMillis());
            sbuf.append("\",");

            sbuf.append("\"level\":\"");
            sbuf.append(event.getLevel());
            sbuf.append("\",");

            sbuf.append("\"tag\":\"");
            sbuf.append(event.getMDCPropertyMap().get("tag"));
            sbuf.append("\",");

            sbuf.append("\"msg\":\"");
            sbuf.append(event.getFormattedMessage().replace("\"", "\\\""));
            sbuf.append("\",");

            sbuf.append("\"source\":\"dialog\"} \n");
        }

        return sbuf.toString();
    }
}
  • 利用自定義的encoder layout,輸出程序中存在的各種變量,輸出不同需求自定義的日誌格式
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章