您想查看一个日志记录框架,也许还要查看一个日志记录外观框架。
那里有多个日志记录框架,通常具有重叠的功能,以至于随着时间的流逝,许多日志记录框架演变为依赖于公共API,或者已经通过立面框架使用以抽象化它们的使用并允许将它们交换到位如果需要的话。
构架
一些记录框架
一些伐木立面
用法
基本范例
这些框架中的大多数将允许您编写某种形式的东西(在此处使用slf4j-api
和logback-core
):
package chapters.introduction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// copied from: http://www.slf4j.org/manual.html
public class HelloWorld {
public static void main(String[] args) {
final Logger logger = LoggerFactory.getLogger(HelloWorld.class);
logger.debug("Hello world, I'm a DEBUG level message");
logger.info("Hello world, I'm an INFO level message");
logger.warn("Hello world, I'm a WARNING level message");
logger.error("Hello world, I'm an ERROR level message");
}
}
请注意,使用当前类来创建专用的记录器,这将允许SLF4J / LogBack格式化输出并指示记录消息来自何处。
如SLF4J手册中所述,类中的典型使用模式通常是:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyClass {
final Logger logger = LoggerFactory.getLogger(MyCLASS.class);
public void doSomething() {
// some code here
logger.debug("this is useful");
if (isSomeConditionTrue()) {
logger.info("I entered by conditional block!");
}
}
}
但实际上,使用以下形式声明记录器甚至更常见:
private static final Logger LOGGER = LoggerFactory.getLogger(MyClass.class);
这也允许在静态方法中使用记录器,并且在类的所有实例之间共享记录器。这很可能是您的首选表格。但是,正如Brendan Long在评论中指出的那样,您希望确保一定要理解其中的含义并做出相应的决定(这适用于遵循这些习惯用法的所有日志记录框架)。
还有其他实例化记录器的方法,例如,使用字符串参数创建命名记录器:
Logger logger = LoggerFactory.getLogger("MyModuleName");
调试级别
调试级别因一个框架而异,但常见的是(按关键程度排列,从良性到严重损坏,从可能非常普遍到希望非常罕见):
街区和守卫
现在,假设您有一个代码部分,您将在其中编写许多调试语句。这可能会很快影响您的性能,这既是因为日志本身的影响,也可能是您可能传递给日志方法的任何参数的生成所致。
为了避免此类问题,您通常需要编写以下形式的内容:
if (LOGGER.isDebugEnabled()) {
// lots of debug logging here, or even code that
// is only used in a debugging context.
LOGGER.debug(" result: " + heavyComputation());
}
如果您在调试语句块之前没有使用过此防护程序,即使可能未输出消息(例如,如果您的记录器当前配置为仅打印INFO
级别以上的内容),则该heavyComputation()
方法仍将执行。
组态
配置完全取决于您的日志记录框架,但是它们为此提供了大多数相同的技术:
- 编程配置(在运行时,通过API- 允许更改运行时),
- 静态声明式配置(在启动时,通常是通过XML或属性文件- 可能一开始就是您所需要的)。
它们还提供大多数相同的功能:
- 输出消息格式的配置(时间戳,标记等),
- 输出电平的配置
- 配置细粒度的过滤器(例如,包含/排除包或类),
- 配置附加程序以确定日志记录的位置(控制台,文件,Web服务...),以及可能处理较旧的日志(例如,使用自动滚动文件)的方法。
这是使用logback.xml
文件的声明式配置的常见示例。
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
如前所述,这取决于您的框架,并且可能还有其他选择(例如,LogBack还允许使用Groovy脚本)。XML配置格式也可能因一种实现方式而异。
有关更多配置示例,请(除其他外)参考:
一些历史的乐趣
请注意,Log4J的是看到此刻的一次重大更新,从版本过渡的1.x到2.x的。您可能希望同时查看两者,以获得更多的历史乐趣或困惑,如果选择Log4J,则可能更喜欢使用2.x版本。
正如Mike Partridge在评论中提到的那样,值得注意的是LogBack是由Log4J的前团队成员创建的。创建它是为了解决Java Logging框架的缺点。而且即将推出的主要Log4J 2.x版本本身现在已经集成了LogBack的一些功能。
建议
最重要的是,尽量保持解耦,尝试一些,然后看看最适合您的方法。最后,它只是一个日志记录框架。除非您有非常具体的原因,除了易于使用和个人喜好之外,这些方法中的任何一个都可以,所以没有必要将其挂在身上。它们中的大多数也可以扩展到您的需求。
不过,如果我今天必须选择一个组合,我会选择LogBack + SLF4J。但是,如果几年后您问我,我会建议将Log4J与Apache Commons Logging一起使用,因此请密切注意您的依赖关系并与之一起发展。