stone2083

          讓log4j支持占位符

          目標:讓log4j.xml配置文件中允許使用占位符(${key}).

          使用場景:
          在運行期決定一些動態的配置內容.
          比如在我們項目中,希望一臺物理機同一個應用跑多個實例.
          因為多進程操作同一份log文件存在并發問題(打印,DailyRolling等),所以我希望配置如下:${loggingRoot}/${instance}/project.log
          在運行腳本中,通過加入-Dinstance=instance1參數,來動態指定實例名.讓同一份應用在不同的運行實例下,日志打印到不同的路徑

          Log4j分析:
          我以為,Log4j天生就支持占位符的.請見:org.apache.log4j.helpers.OptionConverter.substVars(String val, Properties props)就有對占位符的處理.
          org.apache.log4j.PropertyConfigurator (log4j.properties文件解析).默認就支持對占位符的處理.
          org.apache.log4j.xml.DOMConfigurator挺怪異的.明明也有對占位符的處理.但是我們就是無法對其屬性props進行賦值.
          (當然,有可能是我誤解了其props的用法--還沒有完整讀過他的源碼)

          處理方案:
          繼承org.apache.log4j.xml.DOMConfigurator,實現自己的DOMConfigurator.
          public class PlaceHolderDOMConfigurator extends org.apache.log4j.xml.DOMConfigurator {

              
          private Properties props;

              
          public PlaceHolderDOMConfigurator(Properties props){
                  
          this.props = props;
              }

              
          public static void configure(String filename, Properties props) {
                  
          new PlaceHolderDOMConfigurator(props).doConfigure(filename, LogManager.getLoggerRepository());
              }

              //主要是覆寫這個方案.傳入properties對象
              
          protected String subst(String value) {
                  
          try {
                      
          return OptionConverter.substVars(value, props);
                  } 
          catch (IllegalArgumentException e) {
                      LogLog.warn(
          "Could not perform variable substitution.", e);
                      
          return value;
                  }
              }
          }

          測試代碼:
          log4j.xml片段:
          <appender name="PROJECT" class="org.apache.log4j.DailyRollingFileAppender">
                  
          <param name="file" value="${loggingRoot}/${instance}/project.log"/>
                  
          <param name="append" value="false"/>
                  
          <param name="encoding" value="GB2312"/>
                  
          <param name="threshold" value="info"/>
                  
          <layout class="org.apache.log4j.PatternLayout">
                      
          <param name="ConversionPattern" value="%d [%X{requestURIWithQueryString}] %-5p %c{2} - %m%n"/>
                  
          </layout>
              
          </appender>
          Run.java:
          public static void main(String[] args) {
                  Properties props 
          = new Properties();
                  props.setProperty(
          "loggingRoot""d:/tmp");
                  props.setProperty(
          "instance""instance1");

                  PlaceHolderDOMConfigurator.configure(LOG4J_PATH, props);
                  Logger rootLogger 
          = LogManager.getRootLogger();
                  FileAppender fileAppender 
          = (FileAppender) rootLogger.getAppender("PROJECT");
                  System.out.println(fileAppender.getFile());
              }

          輸出結果:
          d:/tmp/instance1/project.log

          當然,你也可以通過在啟動參數中加 -DloggingRoot=xxxx  -Dinstance=yyyy動態指定內容.


          特別說明:
          本文:log4j版本為1.2.14
          log4j 1.2.15測試不通過,原因見:https://issues.apache.org/bugzilla/show_bug.cgi?id=43325

          posted on 2010-07-01 08:52 stone2083 閱讀(12680) 評論(2)  編輯  收藏 所屬分類: java

          Feedback

          # re: 讓log4j支持占位符[未登錄] 2012-10-27 13:41 dd

          setParameter  回復  更多評論   

          # re: 讓log4j支持占位符[未登錄] 2012-10-27 13:42 dd

          重載setParameter才兼容所有  回復  更多評論   

          主站蜘蛛池模板: 辽宁省| 平泉县| 公主岭市| 龙州县| 安龙县| 昭平县| 庄河市| 日喀则市| 乐平市| 大足县| 瓦房店市| 泰宁县| 平邑县| 合山市| 射洪县| 息烽县| 岳普湖县| 贵阳市| 宁远县| 庆云县| 永春县| 缙云县| 瓦房店市| 运城市| 保定市| 沁水县| 北海市| 鹤壁市| 富阳市| 时尚| 连州市| 绥滨县| 玉门市| 新泰市| 满城县| 十堰市| 鹤庆县| 贡嘎县| 阿克| 磐石市| 余干县|