Java Logging Techniques Summary(JUL in Depth)

本文深入探讨Java Util Logging(JUL)的工作流程及组件,包括Level、LogRecord、Formatter、Handler、LogManager和Logger的功能特性。通过实例演示如何配置JUL并展示不同输出级别的效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. JUL is an inbeded util tool for logging.

 

2. The work flow of JUL



3. JUL has abstracted Logging procession into the interaction of several Classes.

    1) Level --> Define the the severe level of the log. 

                  --> JUL has used a different logging level compared with Log4j.

                  -->  1) SEVERE

                         2) WARNING

                         3) INFO

                         4) CONFIG

                         5) FINE

                         6) FINER

                         7) FINEST

                         In addition to that, you have also the levels OFF and ALL to turn the logging of or to log everything.

     2) LogRecord --> Encapsulated a record that to be printed.

                           --> It contains following information:

                           1) Level (The level of this record)

                           2) sequenceNumber (Every time a record is created, sequenceNumber increased by 1)

                           3) sourceClassName (The class where this record is printed)

                           4) sourceMethodName (The method where this record in printed)

                           5) message (The message itself)

                           6) ...

    3) Formatter --> It a formatter that is used to format a LogRecord.

                        --> JUL provides two kinds of Formatter: SimpleFormatter(Default) & XMLFormatter

                        --> SimpleFormatter is used by default. It prints record information as the following format:

                           --> Date + Time + LoggerName/sourceClassName + methodName

                           --> Level + Message

                           --> Exception Info

May 21, 2013 2:35:30 PM edu.xmu.logging.Logging_JDKLogging.AppTest loggerTest
INFO: Main running

                      --> XMLFormatter is not often used. As the format of below:

                           --><record></record>                         

    4) Handler  --> The position where the record to be printed.

                       --> The hierarchy of Handlers is as below:

 

                     --> The Handler contains a reference to Formatter, Level, Filter

                          --> The reference of Formatter is used to format the LogRecord into String.

                          --> The reference of Level is used to define the Level supported by this Handler

                          --> The Filter?...

                     --> The function publish() in Handler is the real function that realize the print LogRecord function.

     5) LogManager  --> An singleton instance that is used to read the configuration file.

                               --> Maintains a map of Logger instance.

                                  -->  When instantiating the LogManager, user can use java.util.logging.manager to point out the custom LogManager.

                                         If we do not point out, then it will use LogManager by default.

                                         After Instantiation, a RootLogger is created and put in the logMap in LogManager.

                                  --> About the logMap in the LogManager

    // Table of known loggers.  Maps names to Loggers.
    private Hashtable<String,Logger> loggers = new Hashtable<String,Logger>();
                                 --> The loggers is organized as the format of Tree:  edu<--xmu<--logging. So the if we getLogger("edu.xmu.logging.LoggingTest"), manager will find in this tree/map, when cannot find this, then it will try to find as getLogger("edu.xmu.logging"), and if cannot find, then will getLogger("edu.xmu") ... So as the level organized.

                                 --> But the LogManager will allow us to control things at more than just the class level. We could set the logging level for a package, or even a set of packages, by calling the LogManager.setLevel(String name, Level level) method.                                                                 So, for example, we could set the logging level of all loggers for this article to Level.FINE by making this call:

 

LogManager.getLogManager().setLevel("logging", Level.FINE);

 

                                      This would make every  Logger with the package prefix of " logging" have a level of  Level.FINE, unless that particular  Logger already had a  Level explicitly set:

Diagram.

                                      We would still need to turn up the levels of the root handlers as before, but would not have to set the individual loggers one at a time.
                                 --> As the name of RootLogger is "", all the configuration for RootLogger is started with "."

     6) Logger  --> The interfact that user used to print log.

                      -->  It contains "name、Handlers、resourceBundleName、useParentHandlers、filter、anonymous、levelObject、parent、kids" fields.

                         -->  It provides getLogger() interface. When user passes into a name, then it returns a Logger instance.  

    public static synchronized Logger getLogger(String name) {
	LogManager manager = LogManager.getLogManager();
	Logger result = manager.getLogger(name);
	if (result == null) {
	    result = new Logger(name, null);
	    manager.addLogger(result);
	    result = manager.getLogger(name);
	}
	return result;
    }

 

4. Several ways to config Logger [Reference to DLevin]

     1) 对Logger的配置支持一下几种方式:  

         <name>.level=INFO|CONFIG….             

         handers=<handlerName1>,<handlerName2>…. (以”,”分隔或以空格、TAB等字符分隔,全局Handler)       

         config=<configClassName1>,<configClassName2>….(自定义类,实现在其构造函数中实现自定义配置)

         <name>.userParentHandlers=true|false|1|0

         <name>.handlers=<handlerName1>,<handlerName2>…(以”,”分隔或以空格、TAB等字符分隔)

         <handlerName>.level=INFO|CONFIG….

        以及各自Handler本身支持的配置,具体各自的Handler。

     2) 用户可以通过以下方式自定义配置文件:

     a. 设置系统属性java.util.logging.config.class,由自定义类的构造函数实现自定义配置,如调用LogManager、Logger中的一些静态方法。

     b.设置系统属性java.util.logging.config.file,自定义配置文件路径。读取该文件中的内容作为配置信息。

     c. 默认使用${java.home}/lib/logging.properties文件作为配置文件(JDK已经提供了一些默认配置,一般是${JRE_HOME}/lib/logging.properties文件)

5. A simple exmple for configuration JUL

    In the path of ${JRE_HOME}/lib/logging.properties

############################################################
#  	Default Logging Configuration File
#
# You can use a different file by specifying a filename
# with the java.util.logging.config.file system property.  
# For example java -Djava.util.logging.config.file=myfile
############################################################

############################################################
#  	Global properties
############################################################

# "handlers" specifies a comma separated list of log Handler 
# classes.  These handlers will be installed during VM startup.
# Note that these classes must be on the system classpath.
# By default we only configure a ConsoleHandler, which will only
# show messages at the INFO and above levels.
handlers= java.util.logging.ConsoleHandler

# To also add the FileHandler, use the following line instead.
#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler

# Default global logging level.
# This specifies which kinds of events are logged across
# all loggers.  For any given facility this global level
# can be overriden by a facility specific level
# Note that the ConsoleHandler also has a separate level
# setting to limit messages printed to the console.
.level= INFO

############################################################
# Handler specific properties.
# Describes specific configuration info for Handlers.
############################################################

# default file output is in user's home directory.
java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 50000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter

# Limit the message that are printed on the console to INFO and above.
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter


############################################################
# Facility specific properties.
# Provides extra control for each logger.
############################################################

# For example, set the com.xyz.foo logger to only log SEVERE
# messages:
edu.xmu.logging.Logging_JDKLogging.level = ALL

   Comments:

       1) Here we can see that the default handler is ConsoleHandler. So if we didn't change this, by default, the information will be printed in console.

       2) Here we can see that the default level for RootLogger is INFO. So if we didn't change this, by default, the information at levels that is lower than INFO will not be printted.

       3) The default level for ConsoleHander is INFO.

       4) The default formatter is SimpleFormatter. So the output information will be printed as the format specified by SimpleFormatter.  

 

6. A simple example for using JUL

    1. Test Class

package edu.xmu.logging.Logging_JDKLogging;

import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

import org.junit.Before;
import org.junit.Test;

/**
 * Unit test for simple App.
 */
public class AppTest
{
	private static Logger logger = null;
	private static SimpleFormatter fileFormatter = null;
	private static FileHandler fileHandler = null;

	@Before
	public void setUp() throws SecurityException, IOException
	{
		logger = Logger.getLogger(AppTest.class.getName());

		fileFormatter = new SimpleFormatter();
		fileHandler = new FileHandler("Logging.txt");
		fileHandler.setFormatter(fileFormatter);
		fileHandler.setLevel(Level.ALL);

		logger.addHandler(fileHandler);
		logger.setLevel(Level.FINE);
	}

	@Test
	public void loggerTest()
	{
		logger.severe("Severe Logging");
		logger.warning("Warning Logging");
		logger.info("Info Logging");
		logger.config("Config Logging");
		logger.fine("Fine Logging");
		logger.finer("Finner Logging");
		logger.finest("Finest Logging");
	}
}

   2. Console output

May 23, 2013 6:22:54 PM edu.xmu.logging.Logging_JDKLogging.AppTest loggerTest
SEVERE: Severe Logging
May 23, 2013 6:22:54 PM edu.xmu.logging.Logging_JDKLogging.AppTest loggerTest
WARNING: Warning Logging
May 23, 2013 6:22:54 PM edu.xmu.logging.Logging_JDKLogging.AppTest loggerTest
INFO: Info Logging

    3. File output (Logging.txt)

May 23, 2013 6:22:54 PM edu.xmu.logging.Logging_JDKLogging.AppTest loggerTest
SEVERE: Severe Logging
May 23, 2013 6:22:54 PM edu.xmu.logging.Logging_JDKLogging.AppTest loggerTest
WARNING: Warning Logging
May 23, 2013 6:22:54 PM edu.xmu.logging.Logging_JDKLogging.AppTest loggerTest
INFO: Info Logging
May 23, 2013 6:22:54 PM edu.xmu.logging.Logging_JDKLogging.AppTest loggerTest
CONFIG: Config Logging
May 23, 2013 6:22:54 PM edu.xmu.logging.Logging_JDKLogging.AppTest loggerTest
FINE: Fine Logging

    1) Q: Why does the console output?

        A: Because the FileHandler is configured in ${JRE_HOME}/lib/logging.properties files. And this FileHandler is ConsoleHander and is the parent of all applications.

        X: We can add a sentence like below: Then the console output will gone.

logger.setUseParentHandlers(false);

    2) Q: Why does we only have the ConsoleOutput has only three items and fileOutput has five output items?

        A: Because in the configuration file(Refer Below).

java.util.logging.ConsoleHandler.level = INFO

    3) Q: What's the relationship of level in Handler and in Logger?

        A:  We can regard the relationship of them as below figure:<Think LogRecord as water that flows through the two pieces of pie>


    4) Q: How can we make different configuration files for different application/modules instead of configure in code/jre-global-configuration-file? 
        A: This configuration file need to be pass to your application using java -Djava.util.logging.config.file option

 

Reference Links:

    1) http://www.blogjava.net/DLevin/archive/2012/11/08/390992.html

    2) http://www.onjava.com/pub/a/onjava/2002/06/19/log.html?page=2

    3) http://tutorialswithexamples.com/java-logging-configuration-using-properties-file/

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值