2015年9月29日星期二

EAP_033:EAP 6 功能演示 3:日志管理

环境:JBoss EAP 6.4

日志由 Logging Subsystem 负责管理和定义。

1. 日志的3个组件
(1)Handlers: 定义事件将在哪里以及如何被记录。
    默认情况下,定义了两个Handlers:
    CONSOLE: 记录事件到控制台窗口
    FILE: 记录事件到文件:server.log.
(2)Loggers: 日志记录器,按不同目录划分事件。
(3)Root Logger: 根日志记录器,所有日志记录器的根。

2. 日志级别
(1)FATAL: a fatal event means the service cannot continue.
(2)ERROR: a problem that may or may not cause the service to continue running.
(3)WARN: a potentially harmful event has occurred.
(4)INFO: nothing went wrong - just an informational event. 默认的日志级别
(5)DEBUG: extra information useful for debugging errors.
(6)TRACE: allows for deep probing of the JBoss server behavior.

3. 日志文件的位置 

3.1 Standalone Mode:[eap_install_dir]/standalone/log
(1)gc.log.0.current 关于这个文件的具体配置在 standalone.sh中。
(2)server.log 可以按时间或大小滚动该日志文件,关于这个文件的具体配置在standalone.xml中的logging subsystem 中。

3.2 Domain Mode
(1)domain/log/host-controller.log 记录 Host Controller(Domain Controller) 启动时的事件。
(2)domain/log/process-controller.log 记录 启动和停止本机进程时的事件。
(3)domain/servers//log/server.log 记录每个server的事件。

3.3 日志的环境变量:jboss.server.log.dir
jboss.server.log.dir 的位置相对于 jboss.server.base.dir,一般来说只需修改后者即可。


4. 内置的6个Handlers 
注意:Handler 自身不能激活,需要定义在<logger>或<root-logger>中才能激活。

(1)Console handler

写到控制台的handler,定义在 <console-handler> 中。
    <console-handler name="CONSOLE" autoflush="true">
           <level name="INFO"/>
           <formatter>
             <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
           </formatter>
    </console-handler>

(2)File handler
 
写到文件的handler,定义在 <file- handler> 中。

(3)Periodic-rotating file handler
  按时间滚动的文件handler,定义在 <periodic-rotating-file-handler> 中。
<periodic-rotating-file-handler name="FILE" autoflush="true">
    <level name="INFO"/>
    <formatter>
        <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
    </formatter>
    <file relative-to="jboss.server.log.dir" path="server.log"/>
    <suffix value=".yyyy-MM-dd"/>
</periodic-rotating-file-handler>
其中,suffix 定义多长时间滚动一次日志,yyy-MM-dd表示一天滚动一次,yyy-MM-dd.HH表示一小时滚动一次,yyy-MM表示一个月滚动一次。

(4)Size-rotating file handler

按大小滚动的文件handler,定义在 <size-rotating-file-handler> 中。
<size-rotating-file-handler name="FILE_BY_SIZE" autoflush="true">
    <level name="INFO"/>
    <encoding value="UTF-8"/>
    <formatter>
        <pattern-formatter pattern="%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%E%n"/>
    </formatter>
    <file relative-to="jboss.server.log.dir" path="production-server.log"/>
    <rotate-size value="2048"/>
    <max-backup-index value="3"/>
</size-rotating-file-handler>
其中,滚动大小 2048K,即2M。最多保留3个备份日志,加上一个当前的日志。


(5)Async handler
异步记录handler,
它不是一个独立的handler,它只是给现有的handler添加上异步的特性。
定义在 <async-handler> 中。
<async-handler name="ASYNC">
    <level name="INFO"/>
    <queue-length value="1024"/>
    <overflow-action value="BLOCK"/>
    <subhandlers>
        <handler name="FILE"/>
    </subhandlers>
</async-handler>
在 <subhandlers></subhandlers>之间可以增加很多handler。
overflow-action 定义当日志队列满的情况下,如何处理新来的事件,BLOCK 阻止直到有了新的空间,DISCARD,丢弃。 


(6)Syslog handler
允许多个应用发送事件信息到远程日志服务器,具体怎么使用还有待实验验证。

定义在 <syslog-handler> 中。
<syslog-handler name="SYSLOG">
    <level name="INFO"/>
    <server-address value="172.25.2.9"/>
    <hostname value="student2"/>
    <port value="514"/>
    <app-name value="MY_APP"/>
</syslog-handler>
 

5. Loggers
Handlers 定义“在哪”和“如何”记录一个事件,Loggers定义“内容
(日志分类)”和“何时(日志级别)”记录一个事件。

(1)例子1
<logger category="org.jboss.seam">
    <level name="INFO"/>
    <handlers>
        <handler name="FILE"/>
    </handlers>
</logger>

(2)例子2
<logger category="org.apache">
    <level name="WARN"/>
</logger>
<logger category="org.apache.naming">
    <level name="ERROR"/>
</logger>
默认情况下,在Sub Logger中发生的事件,在Parent Logger中也会记录一遍,如果不想在Parent Logger中记录的话,可以在Sub Logger中设置use-parent-handlers = false。

(3)Root Logger
默认情况下,所有的Logger定义,都继承root logger的定义。
没有被Logger定义涉及的事件,都将按照以 root logger的定义来作用。
<root-logger>
    <level name="INFO"/>
    <handlers>
        <handler name="CONSOLE"/>
        <handler name="FILE"/>
    </handlers>
</root-logger>


在生产环境中,Root Logger 建议如下设置:
<root-logger>
    <level name="ERROR"/>
    <handlers>
        <handler name="FILE"/>
    </handlers>
</root-logger>
 

6. 演示

6.1 定义 

(1)cp standalone.xml standalone-logger.xml
(2)vim standalone-logger.xml

 <size-rotating-file-handler name="FILE_BY_SIZE_ROTATING" autoflush="true">
                <level name="ERROR"/>
                <file relative-to="jboss.server.log.dir" path="production-server.log"/>
                <rotate-size value="1m"/>
                <max-backup-index value="3"/>
                <append value="true"/>
  </size-rotating-file-handler>

  <logger category="com.jboss.logtest" use-parent-handlers="false" >
                <level name="INFO"/>
                <handlers>
                    <handler name="FILE_BY_SIZE_ROTATING"/>
                </handlers>
  </logger>


  <async-handler name="ASYNC">
                <level name="INFO"/>                 
                <queue-length value="1024"/>
                <overflow-action value="block"/>
                <subhandlers>
                    <handler name="FILE_BY_SIZE_ROTATING"/>
                </subhandlers>
 </async-handler> 


6.2. 启动EAP,部署LogTest.war

./standalone.sh -Djboss.server.base.dir=/Users/maping/Redhat/eap/demo/myeap -c standalone-logger.xml -Djboss.socket.binding.port-offset=10000
 

6.3 访问:http://localhost:18080/LogTest/run
(1) 观察Console,发现没有任何应用的日志输出
这是因为use-parent-handlers = false,如果=true,Console中也会有应用日志信息,并且是INFO级别的,因为Root Logger是INFO级别的。
(2) 观察product-server.log,发现有如下输出:
10:27:30,282 FATAL [com.jboss.logtest.LogTester] (http-/127.0.0.1:18080-1) This is fatal event number 1
10:27:30,282 ERROR [com.jboss.logtest.LogTester] (http-/127.0.0.1:18080-1) This is error event number 1
10:27:30,283 FATAL [com.jboss.logtest.LogTester] (http-/127.0.0.1:18080-1) This is fatal event number 2
10:27:30,283 ERROR [com.jboss.logtest.LogTester] (http-/127.0.0.1:18080-1) This is error event number 2
这是FILE_BY_SIZE_ROTATING handler定义的日志级别是ERROR,而com.jboss.logtest logger 使用的就是这个handler。
也就是说,为每个应用定义自己的日志文件在JBoss EAP 中非常简单。
 (3)以异步的方式写文件

6.4. LogTester.java

package com.jboss.logtest;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.logging.Logger;

/**
 * Servlet implementation class LogTester
 */
public class LogTester extends HttpServlet {
    private static final long serialVersionUID = 1L;
    //private static final Log log = LogFactory.getLog(LogTester.class);
    private static final Logger log = Logger.getLogger(LogTester.class);


    /**
     * Default constructor.
     */
    public LogTester() {
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        out.write("

LogTester Application Version 1.0

");
        out.write("Loading this page generates multiple log events for the com.jboss.logtest category.
");
        out.write("Simply reload this page to generate all the log events again.
");
        out.close();
        for(int i = 1; i <= 20; i++) {
            log.debug("This is debug event number " + i);
            log.fatal("This is fatal event number " + i);
            log.info("This is info event number " + i);
            log.error("This is error event number " + i);
            log.trace("This is trace event number " + i);
            log.warn("This is warn event number " + i);
        }
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
    }

}


没有评论: