首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

WebSphere Application Server 日志记录开发人员指南(3)

WebSphere Application Server 日志记录开发人员指南(3)

使用 JUL 检测代码
  • 记录器在需要日志记录和跟踪的代码中使用。记录器通常基于所在的 Java 类或包分配名称(例如,com.acme.birdtrap.PurchaseOrder)。记录器由独立日志管理器存储采用层次结构方式存储,允许记录器从其父级记录器继承特征。每个记录器的名称确定记录器所属的层次结构,每个记录器的父项具有与子项相同的名称,不过减少了子项名称中最后一个英文句点之后的部分(例如,com.acme 是 com.acme.birdtrap 的父级记录器,而后者是 com.acme.birdtrap.PurchaseOrder 的父级记录器)。每个记录器都具有对应的级别,这是一个可设置的阈值,控制必须记录的事件(称为日志记录)的严重级别,以免被丢弃。如果不明确设置记录器级别,则该记录器将从其父项继承级别。记录器可以具有筛选器,筛选器是记录器用于根据日志记录的内容决定是否丢弃日志记录请求的类。
  • 处理器是记录器用于将日志记录写入输出设备的类。处理器可以自行设置日志记录的格式,或使用格式设置器来将日志记录转换为字符串。处理器还具有级别设置,级别的用途与记录器中的级别相同。处理器也可以具有筛选器,其用途与记录器的筛选器相同。处理器通常将日志记录的格式化结果写入日志文件,但可以设计为输出到内存内的缓冲区、套接字、即时消息传递目的地或任何其他认为有用的位置。JUL 以标准形式提供,包含一系列处理器和格式设置器来满足您的基本需求。
    图 1. JUL 日志请求处理中的关键组件
清单 1 包含演示使用 JUL 时的编码最佳实践的代码示例。将在示例后对这些最佳实践进行说明。
清单 1. 演示 JUL 使用的示例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
1  package com.acme;

2  import java.util.logging.Level;
3  import java.util.logging.Logger;

4  public class JULExample {

5   // define a Logger for use by this class
6   static String className = JULExample.class.getName();
7   public static Logger logger = Logger.getLogger(className);

8   public String lookupContactPhoneNumber(String contactName) {
9       String methodName = "lookupContactPhoneNumber";
10          logger.entering(className, methodName);

11          // connect to contact repository
12          ContactRepository cr = ContactRepository.connect();

13          if (cr == null) {
14              // LOGGING
15              logger.logp(Level.WARNING, className, methodName,
16                          "Contact repository not available");
17              return "";
18          }

19          // lookup the contact phone number
20          String contactPhoneNumber = cr.getContactPhoneNumber(contactName);

21          // TRACE
22          if (logger.isLoggable(Level.FINEST)) {
23              // use isLoggable so we don't concatenate strings
24              // below unless trace is enabled
25              String traceString = "name    " + contactName + "number: "
26                      + contactPhoneNumber;

27              logger.logp(Level.FINEST, className, methodName,      
28                          traceString);
29      }

30      logger.exiting(className, methodName, contactPhoneNumber);
31      return contactPhoneNumber;
32  }

33  public String getSomeString() {
34      return "SomeString";
35  }

36  }




使用 JUL API 将日志记录和跟踪代码添加到应用程序,将极大地改进您应用程序的服务能力。以下是一些建议的原则,可帮助您获得极佳的结果:
  • 存储记录器实例,而不要重复调用 Logger.getLogger。  
    在清单 1 中,Logger.getLogger() 仅仅调用了一次,以获得类的记录器。记录器是线程安全的,因此可以安全地将其存储在静态变量中,以供任何类实例使用。这样您就能够在类中的任何位置使用记录器,而且不必再次调用 Logger.getLogger(),从而提高您代码的性能。
  • 使用完全限定类名称作为记录器名称。  
    记录器名称在需要更改记录器级别时用于标识记录器(例如,在管理控制台中)。通过为记录器分配完全限定类名称,可方便地指定需要调整哪个记录器的级别来从用户获得所需的跟踪。
  • 确保日志和跟踪条目易于链接回代码。  
    通过在日志和跟踪条目中指定类名称和方法名称,将能够立即指出事件在代码中的生成位置。
    您还需要使用 entering() 方法调用来标记方法的开始位置,但要记住 entering() 方法调用将生成 Level.FINER 事件,而在 WebSphere Application Server 中缺省禁止 Level.FINER 事件。
    有些 JUL 实现将尝试在未指定这些参数的情况下计算哪个方法和类生成了事件,但这可能会产生不希望的性能影响——在 JIT 删除了堆栈框架的情况下甚至可能会不正确。在 WebSphere Application Server 中,不会尝试计算代表调用方的方法和类名称(这项功能是可选的,而且被视为非常低效的功能)。在能够提供自己的类和方法名称的情况下,使用 JUL 记录器方法更好。
    表 2. 允许指定类和方法名称的记录器方法记录器方法entering(String sourceClass, String sourceMethod) entering(String sourceClass, String sourceMethod, Object param1) entering(String sourceClass, String sourceMethod, Object[] params) exiting(String sourceClass, String sourceMethod) exiting(String sourceClass, String sourceMethod, Object result) Logp(Level level, String sourceClass, String sourceMethod, String msg) Logp(Level level, String sourceClass, String sourceMethod, String msg, Object param1) logp(Level level, String sourceClass, String sourceMethod, String msg, Object[] params) logp(Level level, String sourceClass, String sourceMethod, String msg, Throwable thrown) throwing(String sourceClass, String sourceMethod, Throwable thrown)
  • 遵循应用服务器的日志和跟踪级别约定。  
    WebSphere Application Server 缺省配置在缺省情况下支持 Level.INFO 和更高的 JUL 级别。应用服务器将从 Level.CONFIG 到 Level.SEVERE 的所有 JUL 级别作为日志事件级别对待,旨在供管理员使用。
    表 3. 日志记录级别日志记录级别Level.SEVERELevel.WARNING Level.INFOLevel.CONFIG
    应用服务器将从 Level.FINE 到 Level.FINEST 的级别作为跟踪级别对待(这些级别用于旨在帮助代码的作者进行调试的事件)。
    表 4. 跟踪级别跟踪级别Level.FINE Level.FINER Level.FINEST
    通过在代码中遵循这些约定,就将能够在缺省情况下记录正确的事件集。
  • 不要在代码中设置日志记录级别。每个 JUL 记录器都具有关联的级别。此级别控制忽略哪些事件和记录哪些事件。记录器级别在应用服务器启动时使用应用服务器配置文件中存储的数据设置。管理员可以利用脚本(使用 wsadmin)或以编程方式(使用 JMX Mbean 客户端)通过管理控制台更改记录器级别。应用服务器控制记录器级别。
    通过直接调用 logger setLevel() 方法对记录器级别设置的更改并不更改应用服务器的中央日志记录配置,因此,通过 setLevel() 设置的记录器级别将不会反映在管理控制台中,而且可能在日志记录基础设施基于管理员更改应用新日志记录设置时被忽略。所以请避免使用此方法:setLevel(Level newLevel)。更改服务器的中央记录器配置时,会将这些更改推送到所有受影响的记录器。这意味着,对记录器 getLevel() 方法的调用将按照预期的方式工作。
  • 请仅将记录器 entering() 和 exiting() 方法用于重要方法。  
    JUL 提供了建议在方法的开始和结束时使用的 Logger.entering() 和 Logger.exiting() 方法。将这些跟踪点添加到代码中的每个方法所涉及工作量将非常大,而且并不会提高应用程序的服务能力。通常,对于特定方法的内部不重要的情况(如简单的 getter 或 setter 方法),请避免使用 entering() 和 exiting() 方法。
  • 最好将应用程序日志和跟踪写入到应用服务器日志。  
    虽然 JUL 提供了只需最少代码或配置来添加新日志文件的能力(处理器),但通常这样做没有什么优势。在调试时让日志和跟踪信息与应用服务器日志和跟踪交织在一起的做法很好。对于不能将日志写入相同的日志文件的情况,或者涉及多个系统时,Log Analyzer(作为 IBM Support Assistant 的插件提供)之类的工具可以帮助您合并日志文件。
  • 在合适的情况使用 Logger.isLoggable()。  
    因为 WebSphere Application Server 缺省情况下禁用跟踪,因此务必尽可能高效地禁用跟踪语句。为了避免计算跟踪方法参数的性能成本,JUL 提供了 Logger.isLoggable() 方法,此方法将进行检查,确定记录器的设置是否等于或高于您所指定的级别。请记住,记录器将执行相同的检查,因此,在计算日志和跟踪参数将带来一定性能成本的情况下,并没有必要将日志或跟踪语句与 Logger.isLoggable() 检查包装在一起。
返回列表