Log4j – Log4j 2 API

Overview

The Log4j 2 API provides the interface that applications should code to and provides the adapter components required for implementers to create a logging implementation. Although Log4j 2 is broken up between an API and an implementation, the primary purpose of doing so was not to allow multiple implementations, although that is certainly possible, but to clearly define what classes and methods are safe to use in "normal" application code.(log4j 2 API提供应用程序应该编码的接口 和为实施者提供了创建一个日志实现所需的适配器组件。尽管log4j 2破碎API和实现之间的关系,这样做的主要目的是不允许多个实现,虽然这样做是可以实现的,但要在“正常”的应用程序代码中明确界定哪些类和方法的使用是安全的。)

Hello World!

No introduction would be complete without the customary Hello, World example. Here is ours. First, a Logger with the name "HelloWorld" is obtained from the LogManager. Next, the logger is used to write the "Hello, World!" message, however the message will be written only if the Logger is configured to allow informational messages.(使用大家惯用的Hello World来做一个介绍。首先,从LogManager中获取一个叫“HelloWorld”的日志记录器。其次,这个日志记录器是用来写“你好,世界!”的消息,但消息只有在Logger被配置为允许该消息级别的日志时才会被打印。)

1 import org.apache.logging.log4j.LogManager;
2 import org.apache.logging.log4j.Logger;
3  
4 public class HelloWorld {
5     private static final Logger logger = LogManager.getLogger("HelloWorld");
6     public static void main(String[] args) {
7         logger.info("Hello, World!");
8     }
9 }

The output from the call to logger.info() will vary significantly depending on the configuration used. See the Configuration section for more details. logger.info() 的输出依赖于使用的配置信息。详细的信息查看 Configuration 部分

Substituting Parameters(替代参数)

Frequently the purpose of logging is to provide information about what is happening in the system, which requires including information about the objects being manipulated. In Log4j 1.x this could be accomplished by doing:(Log4j 1.x 中使用的格式:)

1 if (logger.isDebugEnabled()) {
2     logger.debug("Logging in user " + user.getName() + " with birthday " + user.getBirthdayCalendar());
3 }

Doing this repeatedly has the effect of making the code feel like it is more about logging than the actual task at hand. In addition, it results in the logging level being checked twice; once on the call to isDebugEnabled and once on the debug method. A better alternative would be:(重复这样做会使代码感觉更像是在做日志记录,而不是手头上的实际任务。此外,它的导致记录级别被检查两次;一次是调用logger.isDebugEnabled() ,一次是调用logger.debug()。更好的选择是:)

logger.debug("Logging in user {} with birthday {}", user.getName(), user.getBirthdayCalendar());

With the code above the logging level will only be checked once and the String construction will only occur when debug logging is enabled.(上面的代码只会检查一次日志级别,只有当debug 日志级别启用时,构造字符串的操作才会发生。)

Formatting Parameters(格式化参数)

Formatter Loggers leave formatting up to you if toString() is not what you want. To facilitate formatting, you can use the same format strings as Java's Formatter. For example:(如果使用 toString() 不是想要的格式,可以使用格式化日志记录器自定义格式。为了方便格式化,您可以使用 和java里面的 Formatter 类相同的格式字符串。例如)

1 public static Logger logger = LogManager.getFormatterLogger("Foo");
2  
3 logger.debug("Logging in user %s with birthday %s", user.getName(), user.getBirthdayCalendar());
4 logger.debug("Logging in user %1$s with birthday %2$tm %2$te,%2$tY", user.getName(), user.getBirthdayCalendar());
5 logger.debug("Integer.MAX_VALUE = %,d", Integer.MAX_VALUE);
6 logger.debug("Long.MAX_VALUE = %,d", Long.MAX_VALUE);

To use a formatter Logger, you must call one of the LogManager getFormatterLogger methods. The output for this example shows that Calendar toString() is verbose compared to custom formatting:(为了使用一个格式化日志记录器,你一定要调用LogManager.getFormatterLogger()方法获取Logger 。下面的信息显示了Calendar.toString() 比自定义的格式冗长de多   

2012-12-12 11:56:19,633 [main] DEBUG: User John Smith with birthday java.util.GregorianCalendar[time=?,areFieldsSet=false,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.ZoneInfo[id="America/New_York",offset=-18000000,dstSavings=3600000,useDaylight=true,transitions=235,lastRule=java.util.SimpleTimeZone[id=America/New_York,offset=-18000000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=3,startMonth=2,startDay=8,startDayOfWeek=1,startTime=7200000,startTimeMode=0,endMode=3,endMonth=10,endDay=1,endDayOfWeek=1,endTime=7200000,endTimeMode=0]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=?,YEAR=1995,MONTH=4,WEEK_OF_YEAR=?,WEEK_OF_MONTH=?,DAY_OF_MONTH=23,DAY_OF_YEAR=?,DAY_OF_WEEK=?,DAY_OF_WEEK_IN_MONTH=?,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=?,ZONE_OFFSET=?,DST_OFFSET=?]
2012-12-12 11:56:19,643 [main] DEBUG: User John Smith with birthday 05 23, 1995
2012-12-12 11:56:19,643 [main] DEBUG: Integer.MAX_VALUE = 2,147,483,647
2012-12-12 11:56:19,643 [main] DEBUG: Long.MAX_VALUE = 9,223,372,036,854,775,807

Mixing Loggers with Formatter Loggers(将Loggers 和 Formatter Loggers混合使用)

Formatter loggers give fine-grained control over the output format, but have the drawback that the correct type must be specified (for example, passing anything other than a decimal integer for a %d format parameter gives an exception).Formatter loggers提供了细粒度的输出格式控制,但是you一个缺点----必须指定正确的类型(例如,给%d传递一个非数字的值将会抛出异常)。)

If your main usage is to use {}-style parameters, but occasionally you need fine-grained control over the output format, you can use the printf method:(如果你主要使用{} 风格的参数,但是偶尔地你也需要细粒度的控制输出格式,你可以使用printf 方法)

1 public static Logger logger = LogManager.getLogger("Foo");
2  
3 logger.debug("Opening connection to {}...", someDataSource);
4 logger.printf(Level.INFO, "Logging in user %1$s with birthday %2$tm %2$te,%2$tY", user.getName(), user.getBirthdayCalendar());

Java 8 lambda support for lazy logging(Java 8的lambda 可以让你更懒的记录日志)

In release 2.4, the Logger interface added support for lambda expressions. This allows client code to lazily log messages without explicitly checking if the requested log level is enabled. For example, previously you would write:(在2.4版中,日志记录器接口添加了对lambda表达式的支持。这允许客户端代码不需要明确检查请求的日志级别是否启用,可以更懒的打印日志消息。例如,以前你会写:)

1 // pre-Java 8 style optimization: explicitly check the log level
2 // to make sure the expensiveOperation() method is only called if necessary
3 if (logger.isTraceEnabled()) {
4     logger.trace("Some long-running operation returned {}", expensiveOperation());
5 }

With Java 8 you can achieve the same effect with a lambda expression. You no longer need to explicitly check the log level:(使用Java 8的lambda 表达式,不再需要明确检查日志级别: )

1 // Java-8 style optimization: no need to explicitly check the log level:
2 // the lambda expression is not evaluated if the TRACE level is not enabled
3 logger.trace("Some long-running operation returned {}", () -> expensiveOperation());

Logger Names(日志记录器的名称)

Most logging implementations use a hierarchical scheme for matching logger names with logging configuration. In this scheme the logger name hierarchy is represented by '.' characters in the logger name, in a fashion very similar to the hierarchy used for Java package names. For example, org.apache.logging.appender and org.apache.logging.filter both have org.apache.logging as their parent. In most cases, applications name their loggers by passing the current class's name to LogManager.getLogger. Because this usage is so common, Log4j 2 provides that as the default when the logger name parameter is either omitted or is null. For example, in all examples below the Logger will have a name of "org.apache.test.MyTest".(大多数日志实现都使用一个分层的方案来匹配日志名称。在这个方案中,日志名称的层次关系是通过’.'来实现的,就像java包名的层次一样。例如,org.apache.logging.appender和org.apache.logging.filter都org.apache.logging作为他们的父级。在大多数情况下,应用程序通过传递当前类的名字给LogManager.getLogger()来命名它们的日志器。因为这种用法用的普遍,log4j 2将它设置为默认参数。例如,在下面所有的日志记录器的名称都会命名为 "org.apache.test.MyTest"。)

1 package org.apache.test;
2  
3 public class MyTest {
4     private static final Logger logger = LogManager.getLogger(MyTest.class);
5 }
1 package org.apache.test;
2  
3 public class MyTest {
4     private static final Logger logger = LogManager.getLogger(MyTest.class.getName());
5 }
1 package org.apache.test;
2  
3 public class MyTest {
4     private static final Logger logger = LogManager.getLogger();
5 }

 

posted on 2017-02-13 00:48  近博  阅读(1042)  评论(0编辑  收藏  举报

导航