logback自定義appender、policy實現日誌列印的邏輯處理

  • 2019 年 10 月 5 日
  • 筆記

以下只貼出核心程式碼,運行程式碼詳見 https://github.com/GloryXu

背景

目前所在的一個組為api介面平台,需要對註冊上的介面進行相應的性能監控。因為是中途接手的項目,對於介面性能的監控比較好奇,就花了點時間了解下,又學了一手,寫了個例子,記錄下。

程式碼結構概覽

文件名

說明

LogbackMain

應用main啟動類

LogPrint

業務類(需要列印日誌的類)

HandleAppender

logback中自定義的appender處理類

MyPolicy

自定義處理策略

HandleAppender類說明

// 注意:這邊的屬性名一定要與logback.xml中的標籤名一致      private MyPolicy myPolicy;      // 同上      private Layout<E> layout;        public void start() {          super.start();          if (this.layout == null) {              this.addStatus(new ErrorStatus("No layout set for the appender named "" + this.name + "".", this));          }      }        @Override      protected void append(E eventObject) {          if (this.myPolicy != null) {              this.myPolicy.handler(this.layout.doLayout(eventObject));          }      }
  • 類屬性名與xml配置的標籤名相同是一個注意點,否則appender類中的屬性值為 null

LogPrint類說明

protected static final Logger mylogger = LoggerFactory.getLogger("myLogger");        private AtomicInteger count;        public LogPrint(AtomicInteger count) {          this.count = count;      }        private ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(1);        public void printInfo () {          pool.scheduleAtFixedRate(() -> {              mylogger.info("print count " + count.incrementAndGet());                mylogger.debug("print debug level log!");          }, 1000, 5000, TimeUnit.MILLISECONDS);      }

以上使用一個定時執行緒池固定頻率模擬業務系統列印日誌,觸發日誌訂製化處理功能

MyPolicy類說明

該類比較簡單,不再說明 詳細可查閱 Github程式碼

logback.xml配置說明

<appender name="myLog" class="com.redsun.logback.HandleAppender">          <!--A.根據設置過濾日誌,此處設置的是info-->          <filter class="ch.qos.logback.classic.filter.ThresholdFilter">              <level>INFO</level>          </filter>          <!--B.自定義設置處理策略-->          <myPolicy class="com.redsun.logback.MyPolicy">              <appName>monitor</appName>          </myPolicy>          <!--日誌列印格式,m:message-->          <layout class="ch.qos.logback.classic.PatternLayout">              <pattern>%m</pattern>          </layout>      </appender>      <!--C.設置日誌級別為info-->      <!--additivity=true,表示將日誌輸出出來,false則不會輸出日誌,但是appender仍可接收到輸出的日誌message-->      <logger name="myLogger" level="info" additivity="true">          <!--指定自定義的appender來處理-->          <appender-ref ref="myLog"/>      </logger>

需要注意的點都已在xml注釋中說明,此處不再贅述

運行情況

在列印日誌前都會將需要列印的日誌發送至 MyPolicy來的 handle中處理一下,此時的邏輯就可以自定義了

缺點

我們項目的運用是在 handle中將列印的日誌(介面的運行耗時,成功率等等)發送至 redis中,然後會有另外的項目去定時任務的獲取數據並作計算,最終算出這個介面的運行情況。

那麼有什麼缺點呢,通過上面列印可以發現,列印的執行緒和真實跑業務的執行緒是同一個,如果自定義的日誌處理邏輯沒有任何的阻塞操作就還好,但是一旦有了耗時比較長的操作就會影響介面的性能了,遇到這種問題不熟悉的人往往很難定位到問題是如何產生的。可以根據業務需求,或者真實場景實現非同步化處理也未嘗不可,當然也要注意資源的分配和控制,不然因為次要功能影響了主要的業務功能就得不償失了。