好的例子使用java.util.logging。

297

我想在我的程序中使用日志。我听说过java.util.logging,但我不知道如何开始。

有没有关于使用日志的示例?我该如何在自己的程序中使用日志?


7
好的,请提供需要翻译的内容。 - Jeremy
我建议您使用Apache的commons logging工具。它高度可扩展,并支持为不同的记录器使用单独的日志文件。请参见此处 - Nikunj
SLF4J是比Apache Commons Logging(ACL)更好的日志门面。它具有到其他日志框架的桥梁,使得对ACL、Log4J或Java Util Logging的直接调用通过SLF4J进行,因此如果您希望将所有输出定向到一个日志文件,则只需一个日志配置文件即可。为什么您的应用程序要使用多个日志框架?因为您使用的第三方库,特别是旧版本,可能会这样做。SLF4J支持各种日志实现。它可以将所有内容输出到标准输出,使用Log4J或Logback(推荐使用Logback而不是Log4J)。http://www.slf4j.org/ http://logback.qos.c - bcody
个人建议使用minlog。它非常简单,因为日志类只有几百行代码。 - Chris Dennett
3个回答

375

java.util.logging让你不必再带着一个jar文件跑你的应用程序,而且它可以很好地与一个好的格式化程序一起使用。

一般来说,在每个类的顶部,你应该有:

private static final Logger LOGGER = Logger.getLogger( ClassName.class.getName() );

然后,您可以直接使用Logger类的各种功能。


对于顶层执行流中的任何调试操作,请使用Level.FINE

LOGGER.log( Level.FINE, "processing {0} entries in loop", list.size() );
在调试基本流程问题时,请在循环内部和可能不需要看到那么多细节的地方使用 Level.FINER / Level.FINEST
LOGGER.log( Level.FINER, "processing[{0}]: {1}", new Object[]{ i, list.get(i) } );

使用参数化版本的日志工具来避免生成大量字符串连接垃圾,这会导致GC跟不上。如上所述,Object[]是廉价的,在堆栈分配通常很便宜。


在异常处理中,始终记录完整的异常详细信息:

try {
    ...something that can throw an ignorable exception
} catch( Exception ex ) {
    LOGGER.log( Level.SEVERE, ex.toString(), ex );
}

我总是在这里使用ex.toString()作为消息,因为当我在日志文件中执行"grep -n"查找"Exception"时,我也可以看到消息。否则,它将出现在堆栈转储生成的输出的下一行,您必须拥有更高级的正则表达式来匹配那一行,这通常会让您获得更多不必要的输出。


6
这是否会将内容写入某种文件?我尝试在我的程序中运行它,但似乎还没有成功。我已经有了你给出的初始行,但到目前为止还没有任何进展。 - Doug Hauf
7
你如何查看日志?我正在使用一个库初始化Logger对象并使用.fine()方法进行日志记录,但似乎无法显示消息... - Anubian Noob
8
自1998年以来,我一直在使用Java编程。我始终觉得在Java中实现日志记录比必要的复杂得多。这是我读过的关于在Java中如何记录日志最为简单易懂的解释。而且很简洁。 - Steve McLeod
38
有趣的是,没有人提到可以在哪里找到日志文件。 - Ahmadov
6
如果你想知道日志去了哪里,确保你已经为Logger设置了一个Handler。如果只是要简单地将日志输出到控制台,请使用一个新的ConsoleHandler,并使用addHandler方法将其添加到你的logger中。确保你对logger和handler都调用了setLevel方法。 - Craig Brown

72
应该像这样声明日志记录器:
private final static Logger LOGGER = Logger.getLogger(MyClass.class.getName());

所以,如果你重构了你的类名,它会跟着改变。
我写了一篇关于Java日志记录器的文章,里面有这里的示例

58

有许多不同类型的日志记录示例。请查看java.util.logging包。

示例代码:

import java.util.logging.Logger;

public class Main {

  private static Logger LOGGER = Logger.getLogger("InfoLogging");

  public static void main(String[] args) {
    LOGGER.info("Logging an INFO-level message");
  }
}

不需要硬编码类名

import java.util.logging.Logger;

public class Main {
  private static final Logger LOGGER = Logger.getLogger(
    Thread.currentThread().getStackTrace()[0].getClassName() );

  public static void main(String[] args) {
    LOGGER.info("Logging an INFO-level message");
  }
}

17
为什么不将日志名称设置为 Main.class.getSimpleName()?这样重构工具在需要更改时可以正确更改它,而且它并不像你第二个解决方案那样笨拙。 - Pijusn
5
为记录器名称执行堆栈跟踪是一种破解、缓慢且不正常的方法。它还会导致AOP代理或其他字节编码工具出现异常命名并最终崩溃。 - Adam Gent
10
-1 对于堆栈跟踪业务。它会减慢速度并有可能阻碍编译器的优化。 - phooji
4
初始化日志记录器时,“缓慢性”为什么会有影响?提到“缓慢性”往往被大多数人称为过早优化(是的,这段代码看起来有点不成熟)。 - mikkom
3
在什么情况下会出现问题?如果记录器标签应该与类名相同,那么这样做似乎完全没有问题。重构工具会自动重命名它,而如果它是硬编码字符串,重构工具可能会跳过它或者说“您是否也想重命名它?” - Pijusn
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接