在这之前,程序员们以如下方式进行日志记录:
if(logger.isDebugEnabled()) { logger.debug("Hi, " + u.getA() + “ “ + u.getB()); }许多人都会抱怨上述代码的可读性太差了。如果有人忘记写if语句,程序输出中会多出很多不必要的字符串。现在,Java虚拟机(JVM)也许对字符串的打印和输出进行了很多优化,但是难道我们仅仅依靠JVM优化来解决上述问题?
log4j 2.0开发团队鉴于以上考虑对API进行了完善。现在你可以这样写代码:
logger.debug("Hi, {} {}", u.getA(), u.getB());和其它一些流行的日志框架一样, 新的API也支持变量参数的占位符功能。
log4j 2.0还支持其它一些很棒的功能,像Markers和flow tracing:
private Logger logger = LogManager.getLogger(MyApp.class.getName()); private static final Marker QUERY_MARKER = MarkerManager.getMarker("SQL"); ... public String doQuery(String table) { logger.entry(param); logger.debug(QUERY_MARKER, "SELECT * FROM {}", table); return logger.exit(); }
Markers可以帮助你很快地找到具体的日志项(Log Entries)。而在某个方法的开头和结尾调用Flow Traces中的一些方法,你可以在日志文件中看到很多新的跟踪层次的日志项,也就是说,你的程序工作流(Program Flow)被记录下来了。下面是Flow Traces的一些例子:
19:08:07.056 TRACE com.test.TestService 19 retrieveMessage - entry 19:08:07.060 TRACE com.test.TestService 46 getKey - entry
插件式的架构
log4j 2.0支持插件式的架构。你可以根据需要自行扩展log4j 2.0,这非常简单。首先,你要为你的扩展建立好命名空间,然后告诉log4j 2.0在哪能够找到它。
<configuration … packages="de.grobmeier.examples.log4j2.plugins">根据上述配置,log4j 2将会在de.grobmeier.examples.log4j2.plugins包中找寻你的扩展插件。如果你建立了多个命名空间,没关系,用逗号分隔就可以了。
下面是一个简单的扩展插件:
@Plugin(name = "Sandbox", type = "Core", elementType = "appender") public class SandboxAppender extends AppenderBase { private SandboxAppender(String name, Filter filter) { super(name, filter, null); } public void append(LogEvent event) { System.out.println(event.getMessage().getFormattedMessage()); } @PluginFactory public static SandboxAppender createAppender( @PluginAttr("name") String name, @PluginElement("filters") Filter filter) { return new SandboxAppender(name, filter); } }
上面标有@PluginFactory注解的方法是一个工厂,它的两个参数直接从配置文件读取。我用@PluginAttr和@PluginElement进行了实现。
剩下的就非常简单了。由于我写的是一个Appender,因此得继承AppenderBase这个类。该类必须实现append()方法,从而进行实际的逻辑处理。除了Appender,你甚至可以实现自己的Logger和Filter。可以参看这些文档docs。
log4j 2的配置变得非常简单。如果你习惯了之前的配置方式,也不用担心,你只要花很少的时间就可以从之前的方式转换到新的方式。请看下面的配置:
<?xml version="1.0" encoding="UTF-8"?> <configuration status="OFF"> <appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </Console> </appenders> <loggers> <logger name="com.foo.Bar" level="trace" additivity="false"> <appender-ref ref="Console"/> </logger> <root level="error"> <appender-ref ref="Console"/> </root> </loggers> </configuration>请看appenders部分,你现在可以使用口语标签(Speaking Tags)了(例如,标签的名字可以跟appender的name属性值匹配),而不再仅仅是类名。当然,这个XML文档无法验证。在急需进行XML验证的情形下,你仍然可以使用更加严格的XML格式,就像2.0之前的XML格式那样:
<appenders> <appender type="type" name="name"> <filter type="type" ... /> </appender> ... </appenders>
上面说的只是一部分改进,你还可以自动重新加载配置文件:
<?xml version="1.0" encoding="UTF-8"?> <configuration monitorInterval="30"> ... </configuration>
监控的时间间隔单位为秒,最小值是5。这意味着,log4j 2在配置改变的情况下可以重新配置日志记录行为。如果值设置为0或负数,log4j 2不会对配置变更进行监测。最为称道的一点是:不像其它日志框架, log4j 2.0在重新配置的时候不会丢失之前的日志记录。
还有一个非常不错的改进,那就是:同XML相比,如果你更加喜欢JSON,你可以自由地进行基于JSON的配置了:
{ "configuration": { "appenders": { "Console": { "name": "STDOUT", "PatternLayout": { "pattern": "%m%n" } } }, "loggers": { "logger": { "name": "EventLogger", "level": "info", "additivity": "false", "appender-ref": { "ref": "Routing" } }, "root": { "level": "error", "appender-ref": { "ref": "STDOUT" } } } } }新的配置方式实在是太强大了,支持诸如 属性替代( property substitution)的特性。请查看相关配置手册以获得更多细节 manual pages。 本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。 2KB翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
2KB项目(www.2kb.com,源码交易平台),提供担保交易、源码交易、虚拟商品、在家创业、在线创业、任务交易、网站设计、软件设计、网络兼职、站长交易、域名交易、链接买卖、网站交易、广告买卖、站长培训、建站美工等服务