`
xyheqhd888
  • 浏览: 403689 次
  • 性别: Icon_minigender_1
  • 来自: 秦皇岛
社区版块
存档分类
最新评论

日志(Logging)

阅读更多

1. 日志(Logging)

     程序不免会出现错误,当出现错误时,可能会想将错误信息以某种方式存储下来,以供使用者或是程序开发人员调试(Debug)时使用。java.lang.logging包提供了一系列的logging工具类,如果只是要简单地记录一些信息,就可以使用这些工具类。

     要使用J2SE的日志功能,首先要取得java.util.logging.Logger实例,这可以通过Logger类的静态getLogger()方法来取得。如下例,当程序在启动时没有提供参数时会显示警示信息:

package ysu.hxy;
 
import java.util.logging.*; 

public class LoggingDemo {
    public static void main(String[] args) {
        Logger logger = Logger.getLogger("LoggingDemo");
        
        try {
            System.out.println(args[0]);
        }
        catch(ArrayIndexOutOfBoundsException e) {
            logger.warning("没有提供执行时的自变量!");

        }                
    }
}

 执行结果:

D:\Java_Test>java ysu.hxy.LoggingDemo
2009-4-7 15:41:43 ysu.hxy.LoggingDemo main
警告: 没有提供执行时的自变量!

2.Logging的等级:

      在进行信息的记录时,依信息程序的不同,会设定不同等级的信息输出。可以通过操作Logger上的几个方法来得到不同等级的信息输出。如下列范例:

package ysu.hxy;

import java.util.logging.*;

public class LoggingLevelDemo
{
	public static void main(String[] args)
	{
		Logger logger = Logger.getLogger("loggingLevelDemo");

		logger.severe("严重信息");
		logger.warning("警示信息");
		logger.info("一般信息");
		logger.config("设定方面的信息");
		logger.fine("细微的信息");
		logger.finer("更细微的信息");
		logger.finest("最细微的信息");
	}
}

 运行结果:

D:\Java_Test>java ysu.hxy.LoggingLevelDemo
2009-4-7 15:50:43 ysu.hxy.LoggingLevelDemo main
严重: 严重信息
2009-4-7 15:50:43 ysu.hxy.LoggingLevelDemo main
警告: 警示信息
2009-4-7 15:50:43 ysu.hxy.LoggingLevelDemo main
信息: 一般信息

 

此示例中config()方法及以下的信息并没有显示出来,这是因为Logger的默认等级是INFO,比这个等级更低的信息,Logger并不会将信息输出

      Logger的默认等级是定义在执行环境的属性文件logging.properties中,这个文件位于JRE安装目录的lib目录下。部分内容如下:

      handlers = java.util.logging.ConsoleHandler

      .level = INFO

      java.util.logging.ConsoleHandler.level = INFO

Logger默认的处理者(Handler)是java.util.logging.ConsolerHandler,也就是将信息输出至命令行模式。一个Logger可以拥有多个处理者,每个处理者可以有自己的信息等级,在通过Logger的等级限制后,实际上还要再经过处理者的等级限制。所以在上面的范例中如果想要看到所有的信息,则必须同时设定Logger与ConsoleHandler的等级。下面的范例示范了如何设定:

package ysu.hxy;

import java.util.logging.*;

public class LoggingLevelDemo2
{
	public static void main(String[] args)
	{
		Logger logger = Logger.getLogger("loggingLevelDemo2");
		//显示所有等级的信息
		logger.setLevel(Level.ALL);

		ConsoleHandler consoleHandler = new ConsoleHandler();
		//显示所有等级的信息
		consoleHandler.setLevel(Level.ALL);
		//设定处理者为ConsoleHandler
		logger.addHandler(consoleHandler);

		logger.severe("严重信息");
		logger.warning("警示信息");
		logger.info("一般信息");
		logger.config("设定方面的信息");
		logger.fine("细微的信息");
		logger.finer("更细微的信息");
		logger.finest("最细微的信息");
	}
}

运行结果:

D:\Java_Test>java ysu.hxy.LoggingLevelDemo2
2009-4-7 16:02:10 ysu.hxy.LoggingLevelDemo2 main
严重: 严重信息
2009-4-7 16:02:10 ysu.hxy.LoggingLevelDemo2 main
严重: 严重信息
2009-4-7 16:02:10 ysu.hxy.LoggingLevelDemo2 main
警告: 警示信息
2009-4-7 16:02:10 ysu.hxy.LoggingLevelDemo2 main
警告: 警示信息
2009-4-7 16:02:10 ysu.hxy.LoggingLevelDemo2 main
信息: 一般信息
2009-4-7 16:02:10 ysu.hxy.LoggingLevelDemo2 main
信息: 一般信息
2009-4-7 16:02:10 ysu.hxy.LoggingLevelDemo2 main
配置: 设定方面的信息
2009-4-7 16:02:10 ysu.hxy.LoggingLevelDemo2 main
良好: 细微的信息
2009-4-7 16:02:10 ysu.hxy.LoggingLevelDemo2 main
较好: 更细微的信息
2009-4-7 16:02:10 ysu.hxy.LoggingLevelDemo2 main
最好: 最细微的信息

 

Level.ALL表示显示所有的信息,所有这一次的执行结果可显示所有等级的信息。如果要关闭所有的信息,可以设定为Level.OFF.Logger的Severe(),warning(),info()等方法,实际上是个便捷的方法。也可以直接使用log()方法并指定等级来执行相同的作用。

package onlyfun.caterpillar;

import java.util.logging.*;

public class LoggingLevelDemo3 {
    public static void main(String[] args) {
        Logger logger = Logger.getLogger("loggingLevelDemo3");
        logger.setLevel(Level.ALL);
        
        ConsoleHandler consoleHandler = new ConsoleHandler();
        consoleHandler.setLevel(Level.ALL);
        logger.addHandler(consoleHandler);
        
        logger.log(Level.SEVERE, "严重信息");
        logger.log(Level.WARNING, "警示信息");
        logger.log(Level.INFO, "一般信息");
        logger.log(Level.CONFIG, "设定方面的信息");
        logger.log(Level.FINE, "细微的信息");
        logger.log(Level.FINER, "更细微的信息");
        logger.log(Level.FINEST, "最细微的信息");
    }
}

3.Handler和Formatter

   Logger默认的输出处理者是ConsoleHandler。ConsoleHandler的输出是使用System.err对象,而信息的默认等级是INFO,这可以在JRE安装目录下lib目录的logging.properties中看到:

   handlers = java.util.logging.ConsoleHandler

   java.util.logging.ConsoleHandler.level = INFO

J2SE提供了5个默认的Handler:

(1) java.util.logging.ConsoleHandler  以System.err输出日志。

(2) java.util.logging.FileHandler  将信息输出到文件。

(3) java.util.logging.StreamHandler 以指定的OutputStream实例输出日志。

(4) java.util.logging.SocketHandler 将信息通过Socket传送至远程主机。

(5) java.util.logging.MemoryHandler 将信息暂存在内存中。

以下代码将信息输出至文件中:

package ysu.hxy;

import java.io.IOException;
import java.util.logging.*;

public class HandlerDemo
{
	public static void main(String[] args) 
	{
		Logger logger = Logger.getLogger("handlerDemo");
        
		try
		{
			FileHandler fileHandler = 
				new FileHandler("%h/myLogger.log");
			logger.addHandler(fileHandler);
			logger.info("测试信息");
		}
		catch (SecurityException e)
		{
			e.printStackTrace();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}
}

 执行的结果会在命令行模式显示信息,并将结果输出至文件中。%h表示使用者的根目录(c:\document and settings\hexinyu目录中)。%t可以取得系统的暂存目录,%g自动为文件编号。例如可以设定为%h/myLogger%g.log,表示将.log文件存储在使用者根目录中,并自动为每个文件增加编号。此范例输出的文件内容如下:

<?xml version="1.0" encoding="GBK" standalone="no"?>
<!DOCTYPE log SYSTEM "logger.dtd">
<log>
<record>
  <date>2009-04-07T16:31:02</date>
  <millis>1239093062781</millis>
  <sequence>0</sequence>
  <logger>handlerDemo</logger>
  <level>INFO</level>
  <class>ysu.hxy.HandlerDemo</class>
  <method>main</method>
  <thread>10</thread>
  <message>测试信息</message>
</record>
</log>

  fileHandler默认的输出格式是XML格式,输出格式由java.util.logging.Formatter来控制。例如FileHandler的默认格式是java.util.logging.XMLFormatter, 而ConsolerHandler的默认格式是java.util.logging.SimpleFormatter,可以使用Handler实例的setFormatter()方法来设定信息的输出格式。例如:

fileHandler.setFormatter(new SimpleFormatter());

如果FileHandler的Formatter设定为SimpleFormatter,则输出的日志文件内容就是简单的文字信息,打开文件后会发现与命令行模式下看到的信息内容相同。

4. 自定义Formatter 

     除了XMLFormatter与SimpleFormatter之外,也可以自定义日志的输出格式,只要继承抽象类Formatter,并重新定义其format()方法即可。format()方法会传入一个java.util.logging.LogRecord对象作为参数,可以使用它来取得一些与程序执行有关的信息。如下示例中自定义了一个简单的TableFormatter。

package ysu.hxy;

import java.util.logging.*;

public class TableFormatter extends Formatter
{
	public String format(LogRecord logRecord)
	{
		return "LogRecord info:" + 
			    logRecord.getSourceClassName()+"\n" +
			    "Level\t|\tLoggerName\t|\tMessage\t|\n"+
			    logRecord.getLevel() +"\t|\t"+
			    logRecord.getLoggerName() + "\t|\t" +
			    logRecord.getMessage() + "\t|\n\n";
	}
}

 自定义好Formatter之后,就可以使用Handler实例的setFormatter()方法设定Formatter对象,如下列代码所示:

package ysu.hxy;

import java.util.logging.*;

public class TableFormatterDemo
{
	public static void main(String[] args) 
	{
		Logger logger = Logger.getLogger("tableFormatter");

		try
		{
			for(Handler h : logger.getParent().getHandlers())
			{
				if( h instanceof ConsoleHandler)
				{
					h.setFormatter(new TableFormatter());
				}
			}

			logger.info("信息1");
			logger.warning("信息2");
		}
		catch (SecurityException e)
		{
			e.printStackTrace();
		}
	}
}

 您取得默认的根(Root)Logger,并判断出其不意ConsoleHandler实例,之后设定ConsoleHandler实例的Formater为自定义的TableFormatter。执行结果如下所示:

D:\Java_Test>java ysu.hxy.TableFormatterDemo
LogRecord info:ysu.hxy.TableFormatterDemo
Level   |       LoggerName      |       Message |
INFO    |       tableFormatter  |       信息1   |

LogRecord info:ysu.hxy.TableFormatterDemo
Level   |       LoggerName      |       Message |
WARNING |       tableFormatter  |       信息2   |

5. Logger层次关系

   在使用Logger的静态getLogger()方法取得Logger实例时,给getLogger()方法的名称是有意义的。如果给定ysu,实际上将从根(Root)logger继承一些特性,像日志等级(Level)以及根logger的处理者。如果再取得一个Logger实例,并给定名称ysu.hxy,则这次取得的Logger将继承ysu这个Logger上的特性。从以下范例可以看出Logger在名称上的继承关系:

package ysu.hxy;

import java.util.logging.*;

public class LoggerHierarchyDemo
{
	public static void main(String[] args)
	{
		Logger onlyfunLogger = Logger.getLogger("ysu");

		Logger caterpillarLogger = Logger.getLogger("ysu.hxy");

		System.out.println("root logger:"+onlyfunLogger.getParent());

		System.out.println("onlyfun logger:" + caterpillarLogger.getParent().getName());

		System.out.println("caterpillar Logger:" + caterpillarLogger.getName() + "\n");

		onlyfunLogger.setLevel(Level.WARNING);
		caterpillarLogger.info("caterpillar ' info");

		caterpillarLogger.setLevel(Level.INFO);
		caterpillarLogger.info("caterpillar ' info");
	}
}

   getParent()方法可以取得Logger上的上层父Logger,根Logger并没有名称,所以直接调用它的toString()以取得字符串描述。当Logger没有设定等级时,则使用父Logger的等级设定,所以在上面的范例中,onlyfunLogger设定等级为WARNING时,caterpillarLogger调用info()方法时并不会有信息显示(因为WARNING等级比INFO高)。只有在caterpillarLoger 设定了自己的等级为INFO之后,才会显示信息。执行结果如下:

D:\Java_Test>java ysu.hxy.LoggerHierarchyDemo
root logger:java.util.logging.LogManager$RootLogger@757aef
onlyfun logger:ysu
caterpillar Logger:ysu.hxy

2009-4-7 17:19:20 ysu.hxy.LoggerHierarchyDemo main
信息: caterpillar ' info

 

在每个处理者方面,当每个Logger处理完自己的日志动作之后,它会向父Logger 传播,让父Logger的处理者也可以处理日志。例如root logger的处理者是ConsoleHandler,所以若子Logger加入了FileHandler来处理完日志之后,向上传播至父Logger,会再由ConsolerHandler来处理,故同样会在命令行模式上显示信息。之前的范例就是这样的例子。

分享到:
评论

相关推荐

    python日志logging工具类

    一个完美控制日志输出的工具类

    python 日志 logging模块详细解析

    主要介绍了python 日志 logging模块 详细解析,本文通过实例代码给大家介绍的非常详细,对大家的工作或学习具有一定的参考借鉴价值,需要的朋友可以参考下

    python日志logging模块使用方法分析

    本文实例讲述了python日志logging模块使用方法。分享给大家供大家参考,具体如下: 一、从一个使用场景开始 开发一个日志系统, 既要把日志输出到控制台, 还要写入日志文件 import logging # 创建一个logger ...

    Python同时向控制台和文件输出日志logging的方法

    本文实例讲述了Python同时向控制台和文件输出日志logging的方法。分享给大家供大家参考。具体如下: python提供了非常方便的日志模块,可实现同时向控制台和文件输出日志的功能。 #-*- coding:utf-8 -*- import ...

    Python日志logging模块功能与用法详解

    本文实例讲述了Python日志logging模块功能与用法。分享给大家供大家参考,具体如下: 本文内容: logging模块的介绍 logging模块的基础使用 logging模块的扩展使用 logging中的Filter 使用配置文件配置logging...

    Python 日志logging模块用法简单示例

    本文实例讲述了Python 日志logging模块用法。分享给大家供大家参考,具体如下: demo.py(日志,输出到控制台): import logging # 导入logging模块 # 日志级别默认是WARNING logging.basicConfig(level=logging....

    MyBatis源码分析之日志logging详解

    主要给大家介绍了关于MyBatis源码分析之日志logging的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

    Python零基础速成班-第11讲-Python日志Logging,小游戏设计game of life.ipynb

    Python零基础速成班,适用于入门或初级学习人群,采用Jupyter Notebook原装教程,.ipynb格式拷贝到Jupyter Notebook目录下即可运行,网页交互式可视化Python编程,全中文注解,下载即用,对初学者非常友好,也可作为...

    python中日志logging模块的性能及多进程详解

    使用Python来写后台任务时,时常需要使用输出日志来记录程序运行的状态,并在发生错误时将错误的详细信息保存下来,以别调试和...本文就介绍了python中日志logging模块性能及多进程的相关资料,需要的朋友可以参考下。

    python改变日志(logging)存放位置的示例

    实现了简单版本的logging.config,支持一般的通过config文件进行配置。感觉还有更好的方法,是直接利用logging.config.fileConfig(log_config_file)方式读进来之后,通过修改handler方式来进行修改。 复制代码 代码...

    .NET Core3.0 日志 logging的实现

    多年的经验,日志记录是软件开发的重要组成部分。没有日志记录机制的系统不是完善的系统。在开发阶段可以通过debug附件进程进行交互调试,可以检测到一些问题,但是在上线之后,日志的记录起到至关重要的作用。它可...

    Python中内置的日志模块logging用法详解

    Python的logging模块提供了通用的日志系统,可以方便第三方模块或者是应用使用。这个模块提供不同的日志级别,并可以采用不同的方式记录日志,比如文件,HTTP GET/POST,SMTP,Socket等,甚至可以自己实现具体的日志...

    0.31 python之logging日志类的封装.mp4

    0.31 python之logging日志类的封装.mp4

    python使用logging日志

    python使用logging日志

Global site tag (gtag.js) - Google Analytics