zoukankan      html  css  js  c++  java
  • 如何自建appender扩展Log4j框架

    1log4j 概述

    log4j 环境包括三个主要组件:
    logger(日志记录器):控制要启用或禁用哪些日志记录语句。可以对日志记录器指定如下级别: ALL 、 DEBUG 、 INFO 、 WARN 、 ERROR , FATAL 。
    layout(布局):根据用户的愿望格式化日志记录请求。
    appender:向目的地发送格式化的输出。
    2.理解 appender
    log4j 框架允许向任何日志记录器附加多个 appender。可以在任何时候对某个日子记录器添加(或删除)appender。附随 log4j 分发的 appender 有多个,包括:
    ConsoleAppender;FileAppender;SMTPAppender ;JDBCAppender;JMSAppender;NTEventLogAppender;SyslogAppender。
    也可以创建自己的自定义 appender。
    3.本工程设计的目标
    通过自建appender类,来实现:
    [1]在控制台输出日志;
    [2]在log文件输出日志;
    [3]在应用程序中建立日志模块(在UI层表现为建立一个日志面板),输出日志;
    [4]对于不同包路径下的日志独立输出(在UI层表现为分不同的面板输出)。
    4.预备知识
    你可以在下面2篇文章中找到Log4j的相关基础介绍。
    5.项目文件分布与效果
    文件分布如图一所示。我们对于com.log.one包下的所有java文件中的日志信息输出到log one模块(图二);对于com.log.two包下的所有java文件中的日志信息输出到log two模块(图四)。本文只象征性的建立了两个测试文件,分别放在两个包下。
    com.log.one.LogTestOne.java
    public class LogTestOne {
        private final static Logger log = Logger.getLogger(LogTestOne.class);
        public void doLog(){
           log.debug("TestOne debug");
           log.info("TestOne info");
           log.warn("TestOne warn");
           log.error("TestOne error");
           log.fatal("TestOne fatal");
        }
    }
     
    com.log.two.LogTestTwo.java
    public class LogTestTwo {
        private final static Logger log = Logger.getLogger(LogTestTwo.class);
        public void doLog() {
           log.debug("TestTwo debug");
           log.info("TestTwo info");
           log.warn("TestTwo warn");
           log.error("TestTwo error");
           log.fatal("TestTwo fatal");
        }
    }
     
     
     
    图一
     
    对于应用程序中的日志模块,提供一些UI层的基本操作,包括清空(图二,图四);变灰(图三);复制到粘贴板。
    The Main Text象征性的表示主应用程序的所有操作。
     
     
    图二
     
     
     
    图三
     
     
     
    图四
     
    同时在控制台输出所有日志信息。(图五)
     
     
    图五
     
        同时在文本文件中输出所有日志信息。(图六)
     
     
    图六
    6log4j.xml
    本项目使用如下日志配置文件,将其放在项目的classpath下。
    <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
    <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false"> 
       <!-- =================== -->
       <!-- Appenders           -->
       <!-- =================== -->
       <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
          <errorHandler class="org.apache.log4j.helpers.OnlyOnceErrorHandler"/>
          <param name="Target" value="System.out"/>
          <param name="Threshold" value="DEBUG"/>
          <layout class="org.apache.log4j.PatternLayout">
             <!-- The default pattern: Date Priority [Category] Message -->
             <param name="ConversionPattern" value="%-5p %l%m%n"/>
          </layout>
       </appender>
     
       <appender name="FILE" class="org.apache.log4j.RollingFileAppender">
         <errorHandler class="org.apache.log4j.helpers.OnlyOnceErrorHandler"/>
         <param name="File" value="logui.log"/>
         <param name="Threshold" value="INFO"/>
         <param name="Append" value="false"/>
         <param name="MaxFileSize" value="5000KB"/>
         <param name="MaxBackupIndex" value="50"/>
         <layout class="org.apache.log4j.PatternLayout">
           <param name="ConversionPattern" value="%d %-5p [%c{1}] %m%n"/>
         </layout>    
       </appender>
         
       <appender name="ONE" class="com.log.utils.LogOneAppender">
          <errorHandler class="org.apache.log4j.helpers.OnlyOnceErrorHandler"/>
       </appender>
      
        <appender name="TWO" class="com.log.utils.LogTwoAppender">
          <errorHandler class="org.apache.log4j.helpers.OnlyOnceErrorHandler"/>
       </appender>
      
       <!-- =============== -->
       <!-- Loggers         -->
       <!-- =============== -->
       <logger name="com.log.one">
         <level value="DEBUG" />
         <appender-ref ref="ONE"/>
         <appender-ref ref="CONSOLE"/>
       </logger>
      
        <logger name="com.log.two">
         <level value="DEBUG" />
         <appender-ref ref="TWO"/>
         <appender-ref ref="CONSOLE"/>
       </logger>
      
       <root>
          <priority value="INFO" />
          <appender-ref ref="FILE"/>
       </root>
    </log4j:configuration>
    这里除常规的CONSOLE和FILE appender,增加两个appender,ONE和TWO,分别通过自建类LogOneAppender和LogTwoAppender定义。
    public class LogOneAppender extends AppenderSkeleton{
        public LogOneAppender() {}
        protected void append(LoggingEvent event) {
           LogUI.log(event);
        }
        public void close() {}
        public boolean requiresLayout() {
           return false;
        }
    }
     
    public class LogTwoAppender extends AppenderSkeleton{
        public LogTwoAppender() {}
        protected void append(LoggingEvent event) {
           LogUI.log(event);
        }
        public void close() {}
        public boolean requiresLayout() {
           return false;
        }
    }
    在logger中通过logger name,com.log.one和com.log.two指定到上述的appender。
    7.主界面设计LogUI.java
    主面板为frame,其中嵌入LogPanel。log类的实体是一个Log4Jmonitor类的实例,通过它的addLogArea方法可以添加日志模块,其中的第二个参数对应log4j配置文件中的logger name。这里还提供一个Cache功能,即如果在主类(LogUI)或日志类(Log4Jmonitor)还没有实例化之前,已经有日志信息,则进行缓存。
    public class LogUI {
        private static LogUI instance;
        private static JFrame frame;
        private Log4JMonitor logMonitor;
        private static List<Object> logCache = new ArrayList<Object>();
        public LogUI() {
           instance = this;
        }
        ///////////////////////UI
        private void buildUI() {
           frame.addWindowListener(new WindowAdapter() {
               public void windowClosing(WindowEvent e) {
                  System.exit(0);
               }
           });
           frame.getContentPane().add(buildContentPanel(), BorderLayout.CENTER);
           frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
           frame.setSize(100, 75);
        }
     
        private Component buildContentPanel() {
           JSplitPane contentSplit = new JSplitPane();
           contentSplit.setTopComponent(new JTextArea("The Main Text"));
           contentSplit.setBottomComponent(buildLogPanel());
           contentSplit.setDividerLocation(550);
           contentSplit.setResizeWeight(1);
           return contentSplit;
        }
     
        private Component buildLogPanel() {
           logMonitor = new Log4JMonitor();
           logMonitor.addLogArea("log one", "com.log.one", true).setLevel(
                  Level.DEBUG);
           logMonitor.addLogArea("log two", "com.log.two", true).setLevel(
                  Level.DEBUG);
           for (Object message : logCache) {
               logMonitor.logEvent(message);
           }
           return logMonitor;
        }
     
        public void show() {
           buildUI();
           frame.setVisible(true);
        }
        ////////////////////Log
        public static synchronized void log(final Object msg) {
           if (instance == null || instance.logMonitor == null) {
               logCache.add(msg);
               return;
           }
           if (SwingUtilities.isEventDispatchThread()) {
               instance.logMonitor.logEvent(msg);
           } else {
               SwingUtilities.invokeLater(new Runnable() {
                  public void run() {
                      instance.logMonitor.logEvent(msg);
                  }
               });
           }
        }
        //////////////////Test Cases
        public void doTests(){
           LogTestOne one=new LogTestOne();
           one.doLog();
           LogTestTwo two=new LogTestTwo();
           two.doLog();
        }
       
        public static void main(String[] args) throws Exception {
           frame = new JFrame("LogUI ");
           LogUI logUi = new LogUI();
           logUi.show();
           logUi.doTests();
        }
    }
    8log类的实体Log4Jmonitor
    通过此类来建立日志模块。其中用到的JlogList.java(见附件)提供对日志模块的所有基本功能。addLogArea方法增加日志模块。logEvent方法对输出的日志事件类型做出判断,对该日志所属的日志模块(本实例为com.log.one和com.log.two)做出判断。
    public class Log4JMonitor extends JTabbedPane {
        private JLogList defaultLogArea;
        public Log4JMonitor() {
           super(JTabbedPane.BOTTOM, JTabbedPane.SCROLL_TAB_LAYOUT);
        }
        public JLogList addLogArea(String title, String loggerName,
               boolean isDefault) {
           JLogList logArea = new JLogList(title);
           logArea.addLogger(loggerName, !isDefault);
           addTab(title, logArea);
           if (isDefault)
               defaultLogArea = logArea;
           return logArea;
        }
        public void logEvent(Object msg) {
           if (msg instanceof LoggingEvent) {
               LoggingEvent event = (LoggingEvent) msg;
               String loggerName = event.getLoggerName();
               for (int c = 0; c < getTabCount(); c++) {
                  Component tabComponent = getComponentAt(c);
                  if (tabComponent instanceof JLogList) {
                      JLogList logArea = (JLogList) tabComponent;
                      if (logArea.monitors(loggerName)) {
                         logArea.addLine(msg);
                      }
                  }
               }
           } else if (defaultLogArea != null) {
               defaultLogArea.addLine(msg);
           }
        }
        public boolean hasLogArea(String loggerName) {
           for (int c = 0; c < getTabCount(); c++) {
               Component tabComponent = getComponentAt(c);
               if (tabComponent instanceof JLogList) {
                  JLogList logArea = (JLogList) tabComponent;
                  if (logArea.monitors(loggerName)) {
                      return true;
                  }
               }
           }
           return false;
        }
    }
     
  • 相关阅读:
    异常响应配置
    用户模块自定义
    数据库配置
    虚拟环境搭建
    SDK Manager failed to install 'java.exe' locking directory
    AndroidUI自动化测试工具-UIautomator
    Android自动化压力测试快速入门教程(图解)——MonkeyRunner
    adb 常用命令
    Android压力测试快速入门教程(图解)——Monkey工具
    测试用例的优先级别划分
  • 原文地址:https://www.cnblogs.com/qingyuuu/p/4791112.html
Copyright © 2011-2022 走看看