如何在logback.xml中自定義動態屬性

原文地址:http://blog.jboost.cn/trick-logback-prop.htmlhtml

當使用logback來記錄Web應用的日誌時,咱們經過在logback.xml中配置appender來指定日誌輸出格式及輸出文件路徑,這在一臺主機或一個文件系統上部署單個實例沒有問題,可是若是部署多個實例(好比經過容器的方式),多個實例同時往同一文件寫日誌可能就會引發問題。這時能夠將每一個實例的日誌文件加以區分,如IP或UUID,或二者結合的形式。這其實就涉及如何在logback.xml中自定義動態屬性的問題。java

能夠有4種方式來實現logback.xml中獲取自定義變量值:微信

  1. 經過設置環境變量或傳遞系統屬性(好比在程序啓動時經過-D傳遞)的方式,二者是能夠直接在logback.xml中經過 ${變量名} 獲取的。
  2. 自定義logback.xml的加載時機,在其加載前將須要設置的屬性注入到logback的context中,這種方式相對複雜,本文不討論。
  3. 經過實現PropertyDefiner接口來提供屬性值設置
  4. 經過實現LoggerContextListener接口來設置屬性值

第一種方式簡單,但不能經過程序生成屬性值,第二種方式稍顯複雜,本文主要介紹後兩種方式。app

PropertyDefiner方式

首先定義一個類,實現PropertyDefiner接口,能夠經過繼承PropertyDefinerBase會更方便dom

import ch.qos.logback.core.PropertyDefinerBase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.UUID;
/***
 * 將本地IP拼接到日誌文件名中,以區分不一樣實例,避免存儲到同一位置時的覆蓋衝突問題
 * @Author ronwxy
 * @Date 2019/8/20 16:17   
 */
public class IPLogDefiner extends PropertyDefinerBase {

    private static final Logger LOG = LoggerFactory.getLogger(IPLogDefiner.class);

    private String getUniqName() {
        String localIp = null;
        try {
            localIp = InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            LOG.error("fail to get ip...", e);
        }
        String uniqName = UUID.randomUUID().toString().replace("-", "");
        if (localIp != null) {
            uniqName = localIp + "-" + uniqName;
        }
        return uniqName;
    }


    @Override
    public String getPropertyValue() {
        return getUniqName();
    }
}

 

而後在logback.xml中,添加 <define> 配置,指定屬性名(本例中爲localIP)及獲取屬性值的實現類,這樣就能夠在配置中經過 ${localIP}來引用該屬性值了。在實現方法 getPropertyValue 中返回你須要生成的值,本例中是返回 本地IP-UUID 的形式。ide

<configuration>
    <define name="localIP" class="cn.jboost.common.IPLogDefiner"/>
    <appender name="interfaceLogFile"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoding>UTF-8</encoding>
        <File>D:\\logs\\elk\\interface-${localIP}.log</File>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
# 省略了其它配置

 

LoggerContextListener方式 函數

定義一個實現LoggerContextListener接口的類,在start方法中,將須要設置的屬性設置到logback的Context中,spa

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.LoggerContextListener;
import ch.qos.logback.core.Context;
import ch.qos.logback.core.spi.ContextAwareBase;
import ch.qos.logback.core.spi.LifeCycle;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.UUID;

/***
 * 第二種實現方式
 * @Author ronwxy
 * @Date 2019/8/20 18:45   
 */
public class LoggerStartupListener extends ContextAwareBase 
    implements LoggerContextListener, LifeCycle {

    private boolean started = false;

    @Override
    public void start() {
        if (started) {
            return;
        }
        Context context = getContext();
        context.putProperty("localIP", getUniqName());
        started = true;
    }

    private String getUniqName() {
        String localIp = null;
        try {
            localIp = InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            //LOG.error("fail to get ip...", e);
        }
        String uniqName = UUID.randomUUID().toString().replace("-", "");
        if (localIp != null) {
            uniqName = localIp + "-" + uniqName;
        }
        return uniqName;
    }
//省略了其它函數

 

 而後在logback.xml中,配置如上監聽器類,這樣就能夠經過 ${localIP} 獲取到上面 context.putProperty("localIP", getUniqName()); 設置的值了。.net

<configuration>

    <!--<define name="localIP" class="com.cnbot.common.IPLogDefiner"/>-->
    <contextListener class="cn.jboost.common.LoggerStartupListener"/>
    <define name="localIP" class="com.cnbot.common.IPLogDefiner"/>
    <appender name="interfaceLogFile"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoding>UTF-8</encoding>
        <File>D:\\logs\\elk\\interface-${localIP}.log</File>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
# 省略了其它配置

 

這種方式能設置任意個數的屬性值,比前一種方式靈活。日誌

總結

在logback.xml中獲取自定義屬性值,主要是須要在加載前將對應的屬性值進行設置,這樣加載時纔能有效獲取。本文雖是自定義日誌文件名稱,但不侷限於此,全部須要動態獲取的變量均可以按這種方式實現。



若是以爲有幫助,請幫忙轉發、推薦。歡迎關注個人微信公衆號:jboost-ksxy
———————————————————————————————————————————————————————————————
微信公衆號

相關文章
相關標籤/搜索