java: 自定义java.util.logging.Logger的日志输出格式,输出IDE(ECLIPSE)能自动识别行号的格式

Posted 10km

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java: 自定义java.util.logging.Logger的日志输出格式,输出IDE(ECLIPSE)能自动识别行号的格式相关的知识,希望对你有一定的参考价值。

不好用的 java.util.logging.Logger

我们知道在java环境有很不少第三方提供的日志记录库,比如常用的log4j,其实JDK (1.4 or above)本身也提供了日志输出工具,就是 java.util.logging.Logger.但这个工具吧,用也能用,却不好用,聊胜于无。
对于用惯了log4j的我来说,它不好用,
下是用java.util.logging.Logger输出的日志

import org.junit.Test;
import java.util.logging.Logger;

public class LoggerTest 
	@Test
	public void test() 
		Logger logger = Logger.getLogger(LoggerTest.class.getSimpleName());
		logger.info("hello,world");
	


日志输出了两行,还没有显示行号,在开发环境中我找这行日志的输出位置很麻烦啊。

十一月 09, 2022 5:21:39 下午 net.gdface.utils.SimpleConsoleFormatterTest test
信息: hello,world

同样的代码用log4j输出,

import org.apache.log4j.Logger;
import org.junit.Test;

public class LoggerTest 

    @Test
    public void testLog4j() 
        Logger logger = Logger.getLogger(LoggerTest.class);
        logger.info("hello,world");
    



[main][INFO ] (LoggerTest.java:13) hello,world

比较就可以看出log4j提供的输出内容更短,但提供了更多有效内容,即代码行号,并且在eclipse等IDE中这个格式的输出可以提供超链直接定位到对应的源码位置,这在开发中就方便多了。

不得不用 java.util.logging.Logger 的时候

所以在一般的开发中我肯定更愿意使用log4j,但是 java.util.logging.Logger 也有它存在的意义,它是JDK内置的,它不需要第三方库支持,这在一些偏底层的中间件开发时就有优势了。

但是 java.util.logging.Logger 的输出实在太不友好了,怎么办?我还是习惯log4j的输出格式啊,可不可以自定义输出格式呢?google一查,还真可以(参见 《How do I create a custom logger Formatter?》)。
java.util.logging.Logger 知道自己不能满足各种环境的输出格式需求,所以它的日志输出格式本来就是可以自定义的,

java.util.logging.Formatter 就是用于提供日志输出格式控制的类,要实现自定义的日志输出格式,只要继承此类,重写format(LogRecord record)方法就可以了。

以下就是我基于Formatter实现的日志输出格式的自定义格式类,它可以输出与log4j完全一样的日志格式。

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.logging.ConsoleHandler;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

/**
 * 为 @link java.util.logging.Logger实现自定义的日志输出,可以输出IDE(eclipse)自动识别源码位置的日志格式。方便调试
 * @author guyadong
 * @since 2.7.0
 */
public class SimpleConsoleFormatter extends Formatter 

	@Override
	public String format(LogRecord record) 
		String message = formatMessage(record);
		String throwable = "";
		if (record.getThrown() != null) 
			StringWriter sw = new StringWriter();
			PrintWriter pw = new PrintWriter(sw);
			pw.println();
			record.getThrown().printStackTrace(pw);
			pw.close();
			throwable = "\\n" + sw.toString();
		
		Thread currentThread = Thread.currentThread();
		StackTraceElement stackTrace = currentThread.getStackTrace()[8];
		return String.format("[%s] (%s:%d) %s%s\\n",
				Thread.currentThread().getName(),
				stackTrace.getFileName(),
				stackTrace.getLineNumber(),
				message,
				throwable);
	
	/**
	 * 将@link SimpleConsoleFormatter实例指定为@link Logger的输出格式
	 * @param logger
	 * @return always logger
	 */
	public static Logger installFormatter(Logger logger)
		if(null != logger)
			/** 禁用原输出handler,否则会输出两次 */
			logger.setUseParentHandlers(false);
			ConsoleHandler consoleHandler = new ConsoleHandler();
			consoleHandler.setFormatter(new SimpleConsoleFormatter());
			logger.addHandler(consoleHandler);
		
		return logger;
	


写个测试代码看看效果:

import org.junit.Test;

import net.gdface.logger.SimpleConsoleFormatter;

import java.util.logging.Logger;
public class LoggerTest 
	@Test
	public void test2Logger() 
		/** 
		 * 调用 SimpleConsoleFormatter.installFormatter 
		 * 将SimpleConsoleFormatter实例设置为Logger格式输出控制对象+ 
		 */
		Logger logger = SimpleConsoleFormatter.installFormatter(Logger.getLogger(LoggerTest.class.getSimpleName()));
		logger.info("hello,world");
	


输出与log4j完全一样,eclipse会自动识别日志中的代码行号,生成跳转的链接,完美。

[main] (LoggerTest.java:12) hello,world

SimpleConsoleFormatter 实现参见码云仓库:
(https://gitee.com/l0km/common-java/blob/master/common-base2/src/main/java/net/gdface/logger/SimpleConsoleFormatter.java)

参考资料

《How do I create a custom logger Formatter?》

《How to get Eclipse Console to hyperlink text to source code files?》

以上是关于java: 自定义java.util.logging.Logger的日志输出格式,输出IDE(ECLIPSE)能自动识别行号的格式的主要内容,如果未能解决你的问题,请参考以下文章

Tomcat乱码问题

将信息记录到服务器的默认日志文件中

java注释的自定义

java里怎么自定义一个日期!

Java自定义注解的使用

java 自定义事件的触发及监听