IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope: Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  WebSphere | Open source  >

WebSphere Application Server Community Edition 中的应用程序日志记录

使用 java.util.logging、Log4j 和 SLF4j

developerWorks
前一页第 4 页,共 10 页后一页

文档选项

样例代码


对本教程的评价

帮助我们改进这些内容


Community Edition 独特性及充分利用 Log4j

Log4j 是来自 Apache Software Foundation 的日志记录服务开源库。Log4j 在开源社区中广泛使用,包括一些重要的项目,如 Apache Geronimo、JBoss 等。Log4j 的体系结构围绕三个主要概念发展:Logger、AppenderLayout

应用程序首先调用 Logger 对象发起消息的日志记录。记录给定消息时,Logger 将生成 LogEvent 对象来包装给定消息。Logger 然后将 LogEvent 对象传递到关联的 Appender。Appender 将 LogEvent 包含的信息发送到指定的输出目的地。例如,ConsoleAppender 将信息写入 System.out,FileApppender 将其写入日志文件。将信息发送到目的地之前,Appender 可以使用 Layout 创建信息所需格式的表示形式。例如,Appender 可以将设置日志消息的格式的 XMLLayout 作为 XML 字符串使用。

将向 LoggingEvent 分配指示其优先级的级别。缺省级别为(从最高到最低):

  • OFF
  • FATAL
  • ERROR
  • WARN
  • INFO
  • DEBUG
  • ALL

Logger 和 Appender 会被分配一个级别。如果 LogEvent 的日志级别为 WARN,而 Appender 的日志级别是 ERROR,Appender 将不会写入 LogEvent。通过这样,您可以控制日志输出的量。

Log4j 中的所有 Logger 都有一个名称。Log4j 根据名称将 Logger 实例组织为分层的树形结构,就像 Java 语言中的打包命名空间。Log4j 文档中的说明如下

“如果一个 Logger 的名称中点号后面是另一个 Logger 的名称,则称这个 Logger 是后代 Logger 的祖先。如果一个 Logger 与其后代 Logger 之间没有其他祖先,则称第一个 Logger 为第二个 Logger 的父项,第二个 Logger 为第一个 Logger 的子项。”

例如,名为 com.ibm 的 Logger 为 com Logger 的子项。com.ibm.wasce Logger 是 com.ibm Logger 的子项,同时是 com Logger 的二级子项。如果未给 Logger 显式分配级别,则使用其分配了级别的最近祖先的级别。Logger 从其祖先继承 Appender,不过也可以配置为仅使用直接向其分配的 Appender。

您可以在 log4j.propertieslog4j.xml 文件中配置所有 Logger、Appender 和 Layout。配置日志记录服务时,Log4j 库将首先在类路径中查找 log4j.xml 文件,然后查找 log4j.properties

通过上面的讨论,您一定认为 Log4j 与 java.util.logging 类似。当然,它们在概念上是相同的,但 Log4j 比 java.util 更强大。java.util.logging 中的 Handler 执行与 Log4j 中的 Appender 相同的任务。java.util.logging 中的 Formatter 执行与 Log4j 中的 Layout 相同的任务。不过,java.util.logging 只有四个 Handler,而 Log4j 有十多个 Appender。此外,Log4j 提供了很多 Layout,而 java.util.logging 仅仅提供 SimpleFormatter 和 XMLFormatter。Log4j 提供的 Appender 包括:

  • FileAppender:将日志事件追加到文件。
  • RollingFileAppender:扩展 FileAppender,从而在日志文件达到特定大小时进行备份。
  • ConsoleAppender:使用用户指定的布局将日志事件追加到 System.out 或 System.err。缺省的目标是 System.out
  • SocketAppender:将 LoggingEvent 对象发送到远程日志服务器上(通常是一个 SocketNode)。
  • JMSAppender:将事件发布到 JMS 主题的简单 Appender。事件序列化为 JMS 消息类型 ObjectMessage 并使用此格式传输。
  • NTEventLogAppender:追加到 NT 事件日志系统。

Log4j 包括 XMLLayout、SimpleLayout、TTCCLayout、HTMLLayout。有关各个 Appender 和 Layout 的介绍,请参见 Log4j 文档。

在此部分,我们将说明如何在部署 Community Edition 上的应用程序中使用 Log4j。Community Edition 在缺省情况下使用以下 log4j 配置文件:

  • < wasce_home >/var/log/server-log4j.properties :此文件配置服务器组件和在服务器上部署的应用程序的 Appender 和 Layout。此文件配置 ConsoleAppender 和 RollingFileAppender。ConsoleAppender 记录到 System.out,RollingFileAppender 记录到 < wasce_home >/var/log/server.log 文件。缺省日志记录级别为 WARN。它同时会覆盖属性文件中的各个 Logger 的日志级别。
  • < wasce_home >/var/log/deployer-log4j.properties :此文件配置部署器的日志记录服务。部署器组件在使用命令行部署器部署任何应用程序时使用。
  • < wasce_home >/var/log/client-log4.properties :此文件配置 Java EE 应用程序客户端的日志记录服务。

在此部分,我们将按以下方式配置 Log4j

  1. 使用缺省服务器 Log4j 配置
  2. 在应用程序级别设置 Log4j

使用缺省服务器 Log4j 配置

正如前面所述,服务器组件以及在 Community Edition 部署的应用程序都使用 < wasce_home >/var/log/server-log4j.properties 中的配置。我们将使用经过修改、采用 Log4j 进行日志记录的 EMPDemo 示例。另外,它还使用 Community Edition 提供的缺省配置。示例包含相同的 EMPDemo Servlet,不过已修改为使用 Log4j API 进行日志记录。清单 9 显示了修改后的 EMPDemo,其中的日志记录语句使用粗体进行标记。Servlet 获取 Logger 并将日志级别设置为 ALL


清单 9. 修改后使用 Log4j API 的 EMPDemo
					
Logger logger = Logger.getLogger(EMPDemo.class.getName());
logger.setLevel(Level.ALL);
Connection con = null;
Statement stmt = null;
		
PrintWriter out = response.getWriter();
		
logger.info("Created the PrintWriter on the Response object");
		
try {
    Context initContext = new InitialContext();
    Context envContext  = (Context)initContext.lookup("java:comp/env");
    logger.info("Got environment context: " +envContext);
    DataSource ds = (DataSource)envContext.lookup("jdbc/DataSource");
    logger.info("Got DataSource: " +ds.toString());
    con = ds.getConnection();
    logger.info("Got Connection: " +con.toString() +"\n");

    stmt = con.createStatement();	
    logger.info("Created the statement: " +stmt);
    ResultSet rs = stmt.executeQuery("SELECT * FROM EMPLOYEE");
    logger.info("Gto the result set: " +rs);
    logger.info("Table EMP after SELECT:");
	
out.println("Your EMP table contains the following entries:<BR>");
		
out.println("<table>");
out.println("<tr>");
out.println("<th>Empno</th>");
out.println("<th>Name</th>");
out.println("<th>Job</th>");
out.println("<th>Manager</th>");
out.println("<th>Salary</th>");
    out.println("<th>Commission</th>");
    out.println("<th>Deptno</th>");
    out.println("</tr>");

    while (rs.next()) {
        String emp = rs.getString("EMPNO");
        String name  = rs.getString("ENAME");
        String job = rs.getString("JOB");
        String mgr = rs.getString("MGR");
        String sal = rs.getString("SAL");
        String comm = rs.getString("COMM");
        String dept = rs.getString("DEPTNO");

        out.println("<tr>");
        out.println("<td>"+emp+"</td>");
        out.println("<td>"+name+"</td>");
        out.println("<td>"+job+"</td>");
        out.println("<td>"+mgr+"</td>");
        out.println("<td>"+sal+"</td>");
        out.println("<td>"+comm+"</td>");
        out.println("<td>"+dept+"</td>");
        out.println("</tr>");
				
        logger.info(emp + "   " + name + "   " + job);
					logger.info("   " + mgr + "   " + dept);

    out.println("</table>");
			
    rs.close();
    stmt.close();
    con.close();
	
    logger.debug("Debug");
					logger.info("Info");
					logger.warn("Warn");
					logger.error("Error");
					logger.fatal("Fatal");

}
catch(java.lang.Exception e) {
			
    e.printStackTrace();
    logger.fatal(e.getClass().getName());
					logger.fatal(e.getMessage());

}

请遵循以下步骤操作,以部署和运行应用程序:

  1. 下载的示例中,将 EMPDemo 解压缩到目录中。war 文件名为 EMPdemo-Log4jLogging1.war
  2. 部署应用程序。
    < wasce_home >/bin>deploy --user system --password manager deploy Log4jLogging1.war.
  3. 将浏览器指向 http://localhost:8080/EMPdemo-log4j1/EMPDemo,以访问 EMPDemo Servlet。Servlet 将在浏览器窗口中显示来自 employee 表的行。

查看控制台窗口,可以看到仅仅记录了清单 10 中所示的日志消息。这是因为 ConsoleAppender 的日志级别缺省为 WARN(在 server-log4j.properties 中)。因此,日志级别为 WARN 或更高的消息记录在控制台中。


清单 10 控制台中的日志消息
					14:13:31,687 WARN  [EMPDemo] Warn
14:13:31,687 ERROR [EMPDemo] Error
14:13:31,687 FATAL [EMPDemo] Fatal

打开 < wasce_home >/var/log/server.log 文件,以查看已经记录的所有日志消息。这是因为 FileAppender 的日志级别缺省为 TRACE 。因此记录了所有的消息。清单 11 显示了所记录的消息:


清单 11. server.log 文件
					
14:13:31,687 INFO  [EMPDemo] 
 Created the PrintWriter on the Response object
14:13:31,687 INFO  [EMPDemo] 
 Got environment context: 
 org.apache.xbean.naming.context.ImmutableContext$NestedImmutableContext@5b9e5b9e
14:13:31,687 INFO  [EMPDemo] 
 Got DataSource: org.tranql.connector.jdbc.DataSource@8660866
14:13:31,687 INFO  [EMPDemo] 
 Got Connection: org.tranql.connector.jdbc.ConnectionHandle@a1e0a1e
14:13:31,687 INFO  [EMPDemo] 
 Created the statement: org.tranql.connector.jdbc.StatementHandle@c980c98
14:13:31,687 INFO  [EMPDemo] 
 Got the result set: org.tranql.connector.jdbc.ResultSetHandle@11221122

14:13:31,687 INFO  [EMPDemo] Table EMP after SELECT:
14:13:31,687 INFO  [EMPDemo] 1   PHANI   SSE
14:13:31,687 INFO  [EMPDemo]    NIKHIL   100
14:13:31,687 INFO  [EMPDemo] 2   JOE   SSE
14:13:31,687 INFO  [EMPDemo]    NIKHIL   100
14:13:31,687 INFO  [EMPDemo] 3   JOHN   SSE
14:13:31,687 INFO  [EMPDemo]    BOB   200
14:13:31,687 DEBUG [EMPDemo] Debug
14:13:31,687 INFO  [EMPDemo] Info
14:13:31,687 WARN  [EMPDemo] Warn
14:13:31,687 ERROR [EMPDemo] Error
14:13:31,687 FATAL [EMPDemo] Fatal 





回页首


在应用程序级别设置 Log4j

有时候,您可能希望在应用程序级别配置 Log4j,而忽略服务器级别的配置。您可以将 Log4j 库和 log4j.properties 配置与应用程序本身打包在一起,然后部署应用程序,从而实现此目标。不过,这里有点小问题——Community Edition 使用“父项优先”类加载器策略。这意味着,如果类在父类加载器中可用,则将会从父类加载器进行加载。由于 Log4j 由服务器组件使用,并由类加载器加载(位于类加载器层次结构中较高的位置),因此将始终使用服务器级别配置的 Log4j,即使 Log4j 库和 log4.properties 文件与应用程序打包在一起也是如此。

为了解决这个问题,我们需要将 Log4j 从父类加载器中隐藏,使其始终从应用程序类加载器进行加载。要隐藏 Log4j,请在 Community Edition 应用程序部署计划中为 Log4j 类指定 <hidden-classes>。有关 Community Edition 提供的其他各种类加载器策略,请参见此技术说明
此部分将说明如何在应用程序级别配置 Log4j。我们使用与之前部分相同的示例。不过,我们将对 Community Edition 应用程序部署计划 (geronimo-web.xml) 进行修改,以隐藏 Log4j 类。清单 12 显示了经过修改的 Geronimo 部署计划,计划中的相关部分以粗体显示。


清单 12. 修改后的 geronimo-web.xml 部署计划
					
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<web:web-app xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.2" 
    xmlns:conn="http://geronimo.apache.org/xml/ns/j2ee/connector-1.2" 
    xmlns:name="http://geronimo.apache.org/xml/ns/naming-1.2" 
    xmlns:ejb="http://openejb.apache.org/xml/ns/openejb-jar-2.2" 
    xmlns:pkgen="http://openejb.apache.org/xml/ns/pkgen-2.1" 
    xmlns:app="http://geronimo.apache.org/xml/ns/j2ee/application-2.0" 
    xmlns:sec="http://geronimo.apache.org/xml/ns/security-2.0" 
    xmlns:web="http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1"
    xmlns:pers="http://java.sun.com/xml/ns/persistence" 
    xmlns:client="http://geronimo.apache.org/xml/ns/j2ee/application-client-2.0">
    <dep:environment>
        <dep:moduleId>
            <dep:groupId>com.ibm.wasce.samples</dep:groupId>
            <dep:artifactId>EMPdemo-log4j-2</dep:artifactId>
            <dep:version>2.1.0.0</dep:version>
            <dep:type>war</dep:type>
        </dep:moduleId>
        <dependencies>
            <dependency>
                <groupId>console.dbpool</groupId>
                <artifactId>EMPLOYEE_DS</artifactId>
            </dependency>
        </dependencies>
        <hidden-classes>
  	<filter>org.apache.log4j</filter>
       </hidden-classes>
    </dep:environment>
    <web:context-root>/EMPdemo-log4j2</web:context-root>
    <name:resource-ref>
        <name:ref-name>jdbc/DataSource</name:ref-name>
        <name:resource-link>EMPLOYEE_DS</name:resource-link>
    </name:resource-ref>
</web:web-app>

另外,我们将 log4j.properties 文件复制到 EMPDemo 应用程序的 WEB-INF/classes 目录,并将 log4j-1.2.14.jar 复制到 WEB-INF/lib 目录。清单 13 显示了 log4j.properties 文件:


清单 13. log4j.properties 文件
					
log4j.logger.com.ibm.sample=debug,applog

log4j.appender.applog=org.apache.log4j.DailyRollingFileAppender
log4j.appender.applog.File=C:/temp/applevellogging/Log4J/applog1.log
log4j.appender.applog.layout=org.apache.log4j.PatternLayout

log4j.appender.applog.layout.ConversionPattern=%d{ABSOLUTE} %-5p [%c{1}] %m%n

此属性文件定义 Servlet 的 Logger,并将日志级别设置为 DEBUG。但是 Servlet 将此值覆盖,更改为 ALL。另外,还定义了一个 DailyRollingFileAppender,将消息记录到 C:/temp/applevellogging/Log4J/applog1.log 文件。此 Appender 所使用的 Layout 是 the server-log4j.properties 文件中使用的标准 Community Edition 布局。请遵循以下步骤来部署此应用程序。

  1. 下载的示例中,解压缩经过修改的 Web 应用程序。WAR 文件名为 EMPdemo-Log4jLogging2.war
  2. 部署应用程序。
    <wasce_home>/bin>deploy --user system --password manager deploy EMPdemo-Log4jLogging2.war
  3. 将浏览器指向 http://localhost:8080/EMPdemo-log4j2/EMPDemo,以访问 EMPDemo Servlet。Servlet 将在浏览器中显示来自 employee 表的行。

请注意,服务器控制台或 server.log 文件中并不会记录任何消息,因为我们覆盖了服务器级别的 Log4j 配置,而在应用程序级别进行配置。另外,应用程序会创建 C:/temp/applevellogging/Log4J/applog1.log 文件,并在此文件中记录消息。清单 14 显示了文件中记录的消息:


清单 14. applog1.log 文件中的消息
					
15:18:36,078 INFO  [EMPDemo] 
 Created the PrintWriter on the Response object
15:18:36,093 INFO  [EMPDemo] 
 Got environment context: 
 org.apache.xbean.naming.context.ImmutableContext$NestedImmutableContext@d760d76
15:18:36,093 INFO  [EMPDemo]
 Got DataSource: org.tranql.connector.jdbc.DataSource@32a232a2
15:18:36,109 INFO  [EMPDemo]
 Got Connection: org.tranql.connector.jdbc.ConnectionHandle@61e461e4
15:18:36,109 INFO  [EMPDemo]
 Created the statement: org.tranql.connector.jdbc.StatementHandle@67206720
15:18:36,109 INFO  [EMPDemo]
 Got the result set: org.tranql.connector.jdbc.ResultSetHandle@6f9a6f9a

15:18:36,109 INFO  [EMPDemo] Table EMP after SELECT:
15:18:36,109 INFO  [EMPDemo] 1   PHANI   SSE
15:18:36,109 INFO  [EMPDemo]    NIKHIL   100
15:18:36,109 INFO  [EMPDemo] 2   JOE   SSE
15:18:36,109 INFO  [EMPDemo]    NIKHIL   100
15:18:36,109 INFO  [EMPDemo] 3   JOHN   SSE
15:18:36,109 INFO  [EMPDemo]    BOB   200
15:18:36,109 DEBUG [EMPDemo] Debug
15:18:36,109 INFO  [EMPDemo] Info
15:18:36,109 WARN  [EMPDemo] Warn
15:18:36,109 ERROR [EMPDemo] Error
15:18:36,109 FATAL [EMPDemo] Fatal






回页首



前一页第 4 页,共 10 页后一页
    关于 IBM 隐私条约 联系 IBM 使用条款