输出高效的日志信息

  日志系统(Log System)是将信息输出到一个或者多个目标上的一种机制。一个日志器(Logger)有下面几个组件。

  • 一个或多个处理器(Handler):处理器决定目标和日志消息的格式。可以把日志消息输出到控制台上、写到文件中或保存到数据库中。
  • 一个名称(Name):一般来说,类中的日志记录器的名称是基于它的包名和类名的。
  • 一个级别(Level):日志消息有一个关联的级别来表示它的重要性。日志记录器也有一个级别用来决定它要输出什么级别的消息。日志记录器仅输出与它的级别相同重要或者更重要的消息。

  使用日志系统有以下两个主要目的:

  • 当捕获到异常时尽可能多地输出信息,这有助于定位并解决错误;
  • 输出关于程序正在执行的类和方法的信息。

  在本节,我们将学习如何使用java.util.logging包提供的类来将一个日志系统增加到并发应用程序中。

1. 创建一个名为MyFormatter的类,继承java.util.logging.Formatter类。然后,实现抽象format()方法。它以LogRecord对象为参数,返回一个带有日志消息的String对象。

import java.util.Date;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;

public class MyFormatter extends Formatter {

    @Override
    public String format(LogRecord record) {
        StringBuilder sb = new StringBuilder();
        sb.append("["+record.getLevel()+"] - ");
        sb.append(new Date(record.getMillis())+" : ");
        sb.append(record.getSourceClassName()+"."+record.getSourceMethodName()+" : ");
        sb.append(record.getMessage()+"\n");
        return sb.toString();
    }

}

2. 创建一个名为MyLogger的类。

import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;


public class MyLogger {
    private static Handler handler;
    
    public static Logger getLogger(String name){
        Logger logger = Logger.getLogger(name);
        logger.setLevel(Level.ALL);
        try {
            if(handler==null){
                handler = new FileHandler("D:\\recipe8.log");
                Formatter format = new MyFormatter();
                handler.setFormatter(format);
            }
            if(logger.getHandlers().length==0){
                logger.addHandler(handler);
            }
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return logger;
    }
}

3. 创建一个名为Task的类,实现Runnable接口。它是用来测试Logger对象的任务。

import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

public class Task implements Runnable {
        
    @Override
    public void run() {
        try {            
            Logger logger = MyLogger.getLogger(this.getClass().getName());
            logger.entering(Thread.currentThread().getName(), "run()");
            TimeUnit.SECONDS.sleep(2);
            logger.exiting(Thread.currentThread().getName(), "exit()",
                    Thread.currentThread());
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }    
    
}

4. 实现范例的主类Main,并实现main()方法。

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


public class Main {

    public static void main(String[] args) {
        Logger logger = MyLogger.getLogger("Core");
        logger.entering("Core", "main()",args);
        Thread threads[] = new Thread[5];
        for(int i=0;i<threads.length;i++){
            logger.log(Level.INFO, "Launching thread: ", +i);
            Task task = new Task();
            threads[i] = new Thread(task);
            logger.log(Level.INFO, "Thread created: "+threads[i].getName());
            threads[i].start();
        }
        logger.log(Level.INFO, "Five Threads created. Waiting for its finalization.");
        try {
            for(int i=0;i<threads.length;i++){
                threads[i].join();
                logger.log(Level.INFO, "Thread has finished its execution", threads[i]);
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        logger.exiting("Core", "main()");
    }
}

5. 控制台输出结果如下

十月 28, 2015 7:40:16 下午 Main main
信息: Launching thread: 
十月 28, 2015 7:40:16 下午 Main main
信息: Thread created: Thread-1
十月 28, 2015 7:40:16 下午 Main main
信息: Launching thread: 
十月 28, 2015 7:40:16 下午 Main main
信息: Thread created: Thread-2
十月 28, 2015 7:40:16 下午 Main main
信息: Launching thread: 
十月 28, 2015 7:40:16 下午 Main main
信息: Thread created: Thread-3
十月 28, 2015 7:40:16 下午 Main main
信息: Launching thread: 
十月 28, 2015 7:40:16 下午 Main main
信息: Thread created: Thread-4
十月 28, 2015 7:40:16 下午 Main main
信息: Launching thread: 
十月 28, 2015 7:40:16 下午 Main main
信息: Thread created: Thread-5
十月 28, 2015 7:40:16 下午 Main main
信息: Five Threads created. Waiting for its finalization.
十月 28, 2015 7:40:18 下午 Main main
信息: Thread has finished its execution
十月 28, 2015 7:40:18 下午 Main main
信息: Thread has finished its execution
十月 28, 2015 7:40:18 下午 Main main
信息: Thread has finished its execution
十月 28, 2015 7:40:18 下午 Main main
信息: Thread has finished its execution
十月 28, 2015 7:40:18 下午 Main main
信息: Thread has finished its execution
View Code

6. 日志recipe8.log内容如下:

[FINER] - Wed Oct 28 19:40:16 CST 2015 : Core.main() : ENTRY
[INFO] - Wed Oct 28 19:40:16 CST 2015 : Main.main : Launching thread: 
[INFO] - Wed Oct 28 19:40:16 CST 2015 : Main.main : Thread created: Thread-1
[INFO] - Wed Oct 28 19:40:16 CST 2015 : Main.main : Launching thread: 
[INFO] - Wed Oct 28 19:40:16 CST 2015 : Main.main : Thread created: Thread-2
[FINER] - Wed Oct 28 19:40:16 CST 2015 : Thread-1.run() : ENTRY
[INFO] - Wed Oct 28 19:40:16 CST 2015 : Main.main : Launching thread: 
[INFO] - Wed Oct 28 19:40:16 CST 2015 : Main.main : Thread created: Thread-3
[INFO] - Wed Oct 28 19:40:16 CST 2015 : Main.main : Launching thread: 
[FINER] - Wed Oct 28 19:40:16 CST 2015 : Thread-3.run() : ENTRY
[INFO] - Wed Oct 28 19:40:16 CST 2015 : Main.main : Thread created: Thread-4
[INFO] - Wed Oct 28 19:40:16 CST 2015 : Main.main : Launching thread: 
[FINER] - Wed Oct 28 19:40:16 CST 2015 : Thread-2.run() : ENTRY
[FINER] - Wed Oct 28 19:40:16 CST 2015 : Thread-4.run() : ENTRY
[INFO] - Wed Oct 28 19:40:16 CST 2015 : Main.main : Thread created: Thread-5
[INFO] - Wed Oct 28 19:40:16 CST 2015 : Main.main : Five Threads created. Waiting for its finalization.
[FINER] - Wed Oct 28 19:40:16 CST 2015 : Thread-5.run() : ENTRY
[FINER] - Wed Oct 28 19:40:18 CST 2015 : Thread-1.exit() : RETURN {0}
[INFO] - Wed Oct 28 19:40:18 CST 2015 : Main.main : Thread has finished its execution
[FINER] - Wed Oct 28 19:40:18 CST 2015 : Thread-3.exit() : RETURN {0}
[FINER] - Wed Oct 28 19:40:18 CST 2015 : Thread-4.exit() : RETURN {0}
[FINER] - Wed Oct 28 19:40:18 CST 2015 : Thread-2.exit() : RETURN {0}
[INFO] - Wed Oct 28 19:40:18 CST 2015 : Main.main : Thread has finished its execution
[INFO] - Wed Oct 28 19:40:18 CST 2015 : Main.main : Thread has finished its execution
[INFO] - Wed Oct 28 19:40:18 CST 2015 : Main.main : Thread has finished its execution
[FINER] - Wed Oct 28 19:40:18 CST 2015 : Thread-5.exit() : RETURN {0}
[INFO] - Wed Oct 28 19:40:18 CST 2015 : Main.main : Thread has finished its execution
[FINER] - Wed Oct 28 19:40:18 CST 2015 : Core.main() : RETURN
View Code

  在上面的实现类中,已使用LogRecord类的下列方法来获取日志消息的信息。

  • getLevel():返回消息级别。
  • getMillis():返回发送消息到Logger对象时的时间(从1970开始计算的毫秒数)。
  • getSourceClassName():返回发送消息到Logger的类的名称。
  • getSourceMessageName():返回发送消息到Logger的方法的名称。
  • getMessage()方法返回日志消息。

  在主程序中,使用了下列方法。

  • entering():输出FINER级别的消息表示方法开始执行。
  • exiting():输出FINER级别的消息表示方法停止执行。
  • log():输出带有指定级别的消息。

  也有其他类库比java.util.logging包提供了更完全的日志系统,如Log4j或slf4j类库。但是java.util.logging包是Java API的一部分,并且它的所有方法都是安全的,所以用在并发应用程序中没有问题。

 

posted @ 2015-10-28 19:55  ~风轻云淡~  阅读(442)  评论(0编辑  收藏  举报