深探java.util.logging包

 

 

 

 

 

 

 

 

1.0   JavaTM Logging Overview

Logging APISJ2SE API Specification.已经被详细描述。这个文档的目标是提供关键元素的概要。

 

 

 

 

 

 

 

 

1.1 Overview of Control Flow 控制流概要

应用程序调用Logger对象来记录日志。(1.1) Loggers被以一种层次命名形式来组织起来,并且子Logger可能自它们的父Logger中继承一些属性。(1.2)

 

 

 

 

 

 

 

 

应用程序调用Logger对象来记录日志。这些Logger对象定位LogRecord对象,这是一些被传送到Handler对象发布的对象(1.3)LoggersHandlers都使用日志级,和(可选)过滤器来决定是否它们对某个特定记录感兴趣(1.4)。当需要发布一个记录,一个Handler可以使用一个Formatter来局部化和格式化这条信息,对发布到I/O流之前(1.5)

每个Logger保持跟踪一些输出Handlers。默认情况下所有Loggers也发送它们的输出到它们的父Logger(1.5)。但Logger也可能被配置成忽略上层的Handlers.(1.6)

 

 

 

 

 

 

 

 

一些Handlers可能直接输出到其它Handlers. 例如,MemoryHandler维护一个LogRecord的内部环缓冲,并在触发事件它发布它的LogRecords通过一个目标Handler.在这种情况,任何信息都被链的最后Handler处理。

这些APIS都是有结构的,所以即使logging被禁用Logger APIS也是轻量级的。如果Logging在给出的日志级别被禁用,Logger会执行一个轻量的比较测试和返回。如果logging在指定的级别被启用,Logger仍然小心地把化费尽可能减少,在传LogRecord进入Handlers的时候。 特别地,本地化和格式化是延时的,当Handler请求它们的时候。例如,一个MemoryHandler可以维护一个LogRecords的通知缓冲,在没有化费格式化的时间。

 

 

 

 

 

 

 

 

1.       2Log Levels

每个日志信息都有一个相关的日志级。 这个级别粗糙指导日志信息的重要性和紧急性。Log Level 对象封装成一个整数,较高的数值代表较高的优先级。

 

 

 

 

 

 

 

 

Level类定义了七个标准日志级。范围从FINEST(最低优先级,最小数值)到SERVER(最高优先组,最大数值)

 

 

 

 

 

 

 

 

1.       3Loggers

正如前面规定的,客户代码发送一个日志请求到Logger对象。每个Logger保持跟踪它感兴趣的日志级,并丢弃小于这个级别的日志。

 

 

 

 

 

 

 

 

Loggers通常以实体命名,使用点分隔符命名,例如”java.awt”.这个命名空间是层次的,并于LogManager管理. 这个命名空间通常应该由JAVA包名字空间组织. 但不一定要跟随..例如,一个Logger名叫”java.awt”有可能处理一个java.awt包的日志请求,但也可能处理一个在sun.awt中的一个类的日志请求.

 

 

 

 

 

 

 

 

别外,也可以创建一个匿名Logger, 一个不出现在共享命名空间的Logger. 具体看1.14.

 

 

 

 

 

 

 

 

Logger跟踪它们的父Logger在日志命名空间. 一个Logger的父是它最近的祖先,在日志命名空间. Logger(名叫 ””)没有父. Anonymous logger are all given the root logger as their parent. Logger可能继承多个属性从它们的父(Logger命名空间). 特别的,一个logger可能继承:

       *日志级别. 如果一个Logger的级别是设置为null,那么这个日志会从父日志中继承第一个非null级别.

       *Handlers.默认一个Logger会记录任何输出信息到它的父Handlers.,并在树中递归.

       *资源包名. 如果一个日志有一个null资源包名,那么它会继承任何定义给它的父日志的资源包,并在树中递归.

 

 

 

 

 

 

 

 

1.4   Logging Methods

Logger类提供大量方便的方法来产生日志信息. 为了方便,有针对每个级别的方法,以日志级别命名. 例如叫”loger.log(Constants.WARING,…” 开发者可以调用方便的方法”:logger.warning(…”

 

 

 

 

 

 

 

 

有两种日志风格,适应不同风格的用户.

 

 

 

 

 

 

 

 

第一,有直接取得源类和源方法名的方法.这些方法是用来给开发者用的, 一些想快速定位日志信息的源的人. 这个风格的例子是:

       void warning(String source Class, String Source Method, String msg);

第二, 有许多方法不直接取得源类和源方法名. 这些方法是用来给开发者用的, 一些想容易使用logging和不需要详细源信息的开发者.

第二种法方,Logging框架会尽力检测那个类和方法调用logging,并会添加这些信息到LogRecord.. 然而,很重要的是自动检测可能只是大约.

1.5   Handlers

StreamHandler

ConsoleHandler

FileHandler

SocketHandler

MemoryHandler

1.6   Formatters

SimpleFormatter

XMLFormatter

1.       7 logManager

有一个全局LogManager对象跟踪全局日志信息.这包含:

Logger的层次命名空间.

用配置文件读取的Logging控制属性

有一个并只有一个LogManager对像可以通过使用静态LogManager.getLogManager方法取得..

1.8   Configuration File

Logging配置可以使用一个logging配置文件(会在启动是被读取)来初始化.这个配置文件是以java.util.Properties的标准格式实现的.

该默认配置文件的位置和使用方法如下:

c:/program files/java/jdk1.5.0/jre/lib/logging.properties

D:/java>java -Djava.util.logging.config.file=d:/java/logging.properties testLogg

er

另一种选择,logging配置可以通过一个类(可以用来读取初始化信息的类)来初始化.这个机制充许配置数据从多种源读取,例如LDAP,JDBC等等.具体看LogManager API Specification.

有一些全局配置信息.,这些信息在LogManager描述中已详细说明,并包含一系列在启动是安装的root-level Handlers

初始化配置可以指定级别针对特定的loggers. 这些级别衩应用来已命令的logger 和任何在它的命令层次以下的logger. 各种级别以它们在配置文件中定义的顺序来应用.

 

 

 

 

 

 

 

 

初始配置可以包含任意的属性,Handlers或运行日志子系统的使用. 为了方便,这些属性应该以handler类或主Logger的句子作为开头.

 

 

 

 

 

 

 

 

例如,MemoryHandler使用一个属性”java.util.logging.MemoryHandler.size”来决定默认ring缓冲大小.

1.9   default configuration

JRE上的默认配置只是一个默认,它可以被ISVs, 系统管理员, 和最终用户改变.

默认配置只限制磁盘空间. 这不提供给用户洪水般的信息,但保证捕获关键错误信息.

默认配置封装一个单独handlerroot logger, 用来发送信息到控制台.

1.10  dynamic configuration updates

程序可以更新logging配置在运行时刻,使用以下的任意一种方法:

FileHandlers, MemoryHandlers and PrintHandlers 都可以以多种属性创建.

Handlers可以添加,并旧的可以删除.

Logger可以被创建并被特定Handlers支持.

级别可以在Handlers上设置.

1.       11私有方法

logging没有私有方法

1.12XML       DTD

       XML DTD是被XMLFormatter使用的.

DTD是设计来以”<log>”元素作为顶层文档,单独log记录被以”<record>”元素记录.

注意, JVM崩溃的事件中,它有可能没有被以</log>属性清楚终止一个XMLFormatter.. 因此分析log记录的工具应该要准备没有终结的流.

1.13  Unique Message IDS

JAVA API不提供该功能,因此程序必需自己实现,并在信息字串中包含.

1.       14Security

主要的安装需求是不信任的代码不能改变日志配置,. 特别地,如果日志配置已经被设置为记录一系统日志信息到一个Handler.,这些的话,不信息代码不可能阻止或中断日志.

 

 

 

 

 

 

 

 

一个新的安装权限LoggingPermission被定义来控制更来到日志配置.

 

 

 

 

 

 

 

 

信任的程序可以调用任何日志配置API.不信任的applets则是另一回事. 不信任applets可以正常创建和使用已命名的Loggers.,但它们不允许改变日志控制设置.例如添加和删除Handlers.或改变日志级别.然而,不信任applets可以创建它们自己的匿名日志.并使用它. 匿名日志不注册在全局命名空间,并它们没有访问检查,允许即使不信任的代码改变它们的日志控制设置.

 

 

 

 

 

 

 

 

日志框架不尝试防止洪水攻击. 日志产生源的可靠性不能被检测.,因为当一个来自特定源类和源方法的日志记录被要求发布,它可能是伪造的! 同样,如果XMLFormatter之类的formatter,不尝试防止嵌套日志信息在信息字串. 这样, 一个欺骗日志记录可能包含欺骗XML记录在里面, 它字串使它看两来像另一个XML记录.

 

 

 

 

 

 

 

 

另外,日志框架不尝试保护自己来防止洪口攻击.任何客户都可以对日志框架以无义意信息隐藏重要信息的方法, 实施洪攻击..

 

 

 

 

 

 

 

 

1.       15 Configuration Management

API是结构化的,所以初始化信息作为属性从一个配置文件读取.. 配置信息可能通过调用多种日志类和对像改变.

另外, LogManager中有方法允许配置文件重新读取. 当这发生, 配置文件值会覆盖任何被程序改变的值.

1.       16Packaging

所有日志类是在java.*命名空间, java.util.loging.

1.17  Localization 本地化

日信息可能需要被本地化.

每个Logger可能有一个跟它名字相关的资源包. 相应的资源包可以被用来影射未加工的字串和本地字串.

通常本地化会被Formatters执行. 为了方便,formatter类提供一个formaMessage方法来提供一些基本的本地化和格式化支持..

1.       18远程方法和串行化

正如多数JAVA平台APIS. 日志APIS设置来使用内部单独地止空间. 所有调用都有意本地化. 然而, 有时一些handlers可能希望转发它们的输出到它们其它系统. 有几种方法做这些事.

 

 

 

 

 

 

 

 

一些Handlers(例如SocketHandler)可能写数据到另外的系统使用XMLFormatter. 这提供一个简单, 标准,的格式可以解析和执行在多种系统.

 

 

 

 

 

 

 

 

一些Handlers可能希望传送LogRecord对像通过RMI. LogRecord类因此是可串行化的. 然而有一个问题是怎么样处理LogRecord参数. 一些Parameters可能没有串行化,并其它系统可能没有设计来串行化如此多的状态. 为解决这问题, LogRecord类有一个自定义writeObject方法转换参数为字串(使用Object.toString())在写出它们之前. 具体看LogRecord API Specification.

 

 

 

 

 

 

 

 

多类Logging类不尝试串行化. Loggershandlers都是状态丰富的类,被绑在指定虚拟机. 在这种关系,它们类似java.io, 也不串行化.

*******************************************************************************

例1.            1

import java.util.logging.Logger;

import java.util.logging.Level;

public class SimpleLogger{

       public static void main(String[] args){

              Logger s = Logger.getLogger("s");

              //因为使用了Logger,所以需要导入java.util.logging.Logger

              s.log(Level.INFO, "this is a info");      

              因为使用了Level,所以需要导入java.util.logging.Level

       }

}

//:~

D:/java/logging>java SimpleLogger

2005-3-13 11:09:10 SimpleLogger main

信息: this is a info

*******************************************************************************

例1.            2

import java.util.logging.Logger;

import java.util.logging.Level;

public class SimpleLogger{

       public static void main(String[] args){

              Logger s = Logger.getLogger("s");

              //因为使用了Logger,所以需要导入java.util.logging.Logger

              s.log(Level.INFO, "this is a info");      

              //因为使用了Level,所以需要导入java.util.logging.Level

              s.setLevel(Level.WARNING);

              Logger sb = Logger.getLogger("s.b");

              sb.log(Level.INFO, "this is a sb.info");

              //因为s设置了LevelWARNING,所以sb从它的父Logger s继承了该属性

              //所以sbLevelWARNING,所以INFO记录不会被发布

              sb.log(Level.WARNING, "this is a sb.warning");

       }

}

//:~

D:/java/logging>java SimpleLogger

2005-3-13 11:16:00 SimpleLogger main

信息: this is a info

2005-3-13 11:16:00 SimpleLogger main

警告: this is a sb.warning

 

 

 

 

 

 

 

 

D:/java/logging>

*******************************************************************************

:1.3

import java.util.logging.Logger;

import java.util.logging.Level;

import java.util.logging.FileHandler;

import java.io.IOException;

public class SimpleLogger{

       public static void main(String[] args){

              Logger s = Logger.getLogger("s");

              //因为使用了Logger,所以需要导入java.util.logging.Logger

              s.log(Level.INFO, "this is a info");      

              //因为使用了Level,所以需要导入java.util.logging.Level

              s.setLevel(Level.WARNING);

              try{

                     FileHandler myFileHandler = new FileHandler("SimpleLogger.log");

                     //因为使用了FileHandler,所以需要导入java.util.logging.FileHandler

                     //也因为上句产生了IOException,所以了导入该EXCEPTION,并处理它

                     s.addHandler(myFileHandler);

                     /*

                     因为在c:/program files/java/jdk1.5.0/jre/lib/logging.properties

                     默认设置了ConsoleHandler,所以不添加Handler都会在控制台看到日志

                     现在添加了myFileHandler,就会在文件中看到日志(默认为XML格式)

                     */

              }catch(IOException e){};

             

              Logger sb = Logger.getLogger("s.b");

              sb.log(Level.INFO, "this is a sb.info");

              //因为s设置了LevelWARNING,所以sb从它的父Logger s继承了该属性

              //所以sbLevelWARNING,所以INFO记录不会被发布

              sb.log(Level.WARNING, "this is a sb.warning");

       }

}

//:~

 

 

 

 

 

 

 

 

D:/java/logging>java SimpleLogger

2005-3-13 11:31:20 SimpleLogger main

信息: this is a info

2005-3-13 11:31:20 SimpleLogger main

警告: this is a sb.warning

 

 

 

 

 

 

 

 

D:/java/logging>

<?xml version="1.0" encoding="GBK" standalone="no"?>

<!DOCTYPE log SYSTEM "logger.dtd">

<log>

<record>

  <date>2005-03-13T11:50:41</date>

  <millis>1110743441640</millis>

  <sequence>2</sequence>

  <logger>s.b</logger>

  <level>WARNING</level>

  <class>SimpleLogger</class>

  <method>main</method>

  <thread>10</thread>

  <message>this is a sb.warning</message>

</record>

</log>

*******************************************************************************

:1.4

import java.util.logging.Logger;

import java.util.logging.Level;

import java.util.logging.Filter;

import java.util.logging.LogRecord;

import java.util.logging.FileHandler;

import java.io.IOException;

public class SimpleLogger{

       public static void main(String[] args){

              Logger s = Logger.getLogger("s");

              //因为使用了Logger,所以需要导入java.util.logging.Logger

              s.log(Level.INFO, "this is a info");      

              //因为使用了Level,所以需要导入java.util.logging.Level

              s.setLevel(Level.WARNING);

              s.setFilter(new MyFilter());

              try{

                     FileHandler myFileHandler = new FileHandler("SimpleLogger.log");

                     //因为使用了FileHandler,所以需要导入java.util.logging.FileHandler

                     //也因为上句产生了IOException,所以了导入该EXCEPTION,并处理它

                     s.addHandler(myFileHandler);

                     /*

                     因为在c:/program files/java/jdk1.5.0/jre/lib/logging.properties

                     默认设置了ConsoleHandler,所以不添加Handler都会在控制台看到日志

                     现在添加了myFileHandler,就会在文件中看到日志(默认为XML格式)

                     */

              }catch(IOException e){};

              s.log(Level.WARNING, "this is a s.warning");

              //因为myFilter会过滤掉上面这条日志,所以它不会被记录(也就是不显示出来)

              Logger sb = Logger.getLogger("s.b");

              sb.log(Level.INFO, "this is a sb.info");

              //因为s设置了LevelWARNING,所以sb从它的父Logger s继承了该属性

              //所以sbLevelWARNING,所以INFO记录不会被发布

              sb.log(Level.WARNING, "this is a sb.warning");

       }

}

 

 

 

 

 

 

 

 

class MyFilter implements Filter{

//因为使用Filter,所以需要导入java.util.logging.Filter;

       public boolean isLoggable(LogRecord record){

       //因为使用LogRecord,所以需要导入java.util.logging.LogRecord

              if(record.getLevel().intValue() > java.util.logging.Level.WARNING.intValue()){

                     return true;

              }

              else

                     return false;          

       }

}

//:~

D:/java/logging>java SimpleLogger

2005-3-13 11:50:41 SimpleLogger main

信息: this is a info

2005-3-13 11:50:41 SimpleLogger main

警告: this is a sb.warning

 

 

 

 

 

 

 

 

D:/java/logging>

<?xml version="1.0" encoding="GBK" standalone="no"?>

<!DOCTYPE log SYSTEM "logger.dtd">

<log>

<record>

  <date>2005-03-13T11:50:41</date>

  <millis>1110743441640</millis>

  <sequence>2</sequence>

  <logger>s.b</logger>

  <level>WARNING</level>

  <class>SimpleLogger</class>

  <method>main</method>

  <thread>10</thread>

  <message>this is a sb.warning</message>

</record>

</log>

***********************************************************************

例1.            5

import java.util.logging.Logger;

import java.util.logging.Level;

import java.util.logging.Filter;

import java.util.logging.LogRecord;

import java.util.logging.FileHandler;

import java.util.logging.SimpleFormatter;

import java.io.IOException;

public class SimpleLogger{

       public static void main(String[] args){

              Logger s = Logger.getLogger("s");

              //因为使用了Logger,所以需要导入java.util.logging.Logger

              s.log(Level.INFO, "this is a info");      

              //因为使用了Level,所以需要导入java.util.logging.Level

              s.setLevel(Level.WARNING);

              s.setFilter(new MyFilter());

              try{

                     FileHandler myFileHandler = new FileHandler("SimpleLogger.log");

                     //因为使用了FileHandler,所以需要导入java.util.logging.FileHandler

                     //也因为上句产生了IOException,所以了导入该EXCEPTION,并处理它

                     myFileHandler.setFormatter(new SimpleFormatter());

                     //因为使用了SimpleFormatter,所以要导入java.util.logging.SimpleFormatter

                     //因为设置了FormatterSimpleFormatter,所以文件的内容会变成简单格式而不是XML格式              

                     s.addHandler(myFileHandler);

                     /*

                     因为在c:/program files/java/jdk1.5.0/jre/lib/logging.properties

                     默认设置了ConsoleHandler,所以不添加Handler都会在控制台看到日志

                     现在添加了myFileHandler,就会在文件中看到日志(默认为XML格式)

                     */

              }catch(IOException e){};

              s.log(Level.WARNING, "this is a s.warning");

              //因为myFilter会过滤掉上面这条日志,所以它不会被记录(也就是不显示出来)

              Logger sb = Logger.getLogger("s.b");

              sb.log(Level.INFO, "this is a sb.info");

              //因为s设置了LevelWARNING,所以sb从它的父Logger s继承了该属性

              //所以sbLevelWARNING,所以INFO记录不会被发布

              sb.log(Level.WARNING, "this is a sb.warning");

       }

}

 

 

 

 

 

 

 

 

class MyFilter implements Filter{

//因为使用Filter,所以需要导入java.util.logging.Filter;

       public boolean isLoggable(LogRecord record){

       //因为使用LogRecord,所以需要导入java.util.logging.LogRecord

              if(record.getLevel().intValue() > java.util.logging.Level.WARNING.intValue()){

                     return true;

              }

              else

                     return false;          

       }

}

//:~

D:/java/logging>java SimpleLogger

2005-3-13 12:11:48 SimpleLogger main

信息: this is a info

2005-3-13 12:11:49 SimpleLogger main

警告: this is a sb.warning

 

 

 

 

 

 

 

 

D:/java/logging>

2005-3-13 12:11:49 SimpleLogger main

警告: this is a sb.warning

例1.            6

使用如下方法即可

java.util.logging.Logger

 void

 

 

 

 

 

 

 

 

setUseParentHandlers(boolean useParentHandlers)
          Specify whether or not this logger should send its output to it's parent Logger.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值