Log4j2

Log4j2

Log4j 2包含了基于LMAX分离库的下一代的异步日志系统,在多线程环境下,异步日志系统比Log4j 1.xLogback提高了10倍性能提升(吞吐量和延迟率),各种框架的对比可以看到如下所示:

Log4j 2Log4j的升级版本,该版本比起其前任来说有着显著的改进,包含很多在Logback中的改进以及Logback架构中存在的问题。这是Log4j 2的首次发行的版本,值得关注的改进包括:

  • API分离 – Log4jAPI和其实现进行分类(注:我讨厌这样,本来一个jar包搞定的,要变成好几个,跟slf4j似的的)

  • 为日志审计而设计,与Log4j 1.xLogback不同的是Log4j 2将不会在重新配置期间丢失事件,支持消息可方便进行审计

  • 性能方面的提升,在关键领域比Log4j 1.x的性能提升不少,大部分情况下性能跟Logback差不多

  • 支持多APIs,支持SLF4JCommons Logging API

  • 自动配置重载,支持XMLJSON格式的配置

  • 插件体系架构,所有可配置的组件都是通过Log4j插件进行定义,包括Appender, Layout, Pattern Converter,等等

  • 配置属性支持

配置文件

如果需要使用Log4j2,首先需要在他的依赖文件里引入如下依赖:

    <dependencies>
      <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>2.4.1</version>
      </dependency>
      <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.4.1</version>
      </dependency>
    </dependencies>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-slf4j-impl</artifactId>
        <version>2.0-beta9</version>
    </dependency>

而后在代码文件中,可以使用Slf4j,也可以直接使用Log4j2,如下:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

private static final Logger log = LoggerFactory.getLogger(Test.class);

如果是直接使用的log4j2,则只要用LogManagergetLogger函数获取一个logger,就可以使用logger记录日志,代码如下:

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;

public class HelloLog4j {
  private static Logger logger = LogManager.getLogger("HelloLog4j");

  public static void main(String[] args) {
    MyApplication myApplication = new MyApplication();

    logger.entry();
    logger.info("Hello, World!");
    myApplication.doIt();
    logger.error("Hello, World!");
    logger.exit();
  }
}

需要注意的是,log4j 2.0与以往的1.x有一个明显的不同,其配置文件只能采用.xml, .json或者.jsn。在默认情况下,系统选择configuration文件的优先级如下:

  • classpath下名为log4j-test.json或者log4j-test.jsn文件
  • classpath下名为log4j2-test.xml
  • classpath下名为log4j.json或者log4j.jsn文件
  • classpath下名为log4j2.xml

Logger配置

<?xml version="1.0" encoding="UTF-8"?>
    <!-- status=debug 可以查看log4j的装配过程 -->
    <configuration status="off" monitorInterval="1800">
    <properties>
        <property name="LOG_HOME">/log/fish</property>
        <!-- 日志备份目录 -->
        <property name="BACKUP_HOME">{LOG_HOME}/backup</property>
        <property name="STAT_NAME">stat</property>
        <property name="SERVER_NAME">global</property>
    </properties>
    <appenders>
        <!-- 定义控制台输出 -->
        <Console name="Console" target="SYSTEM_OUT" follow="true">
        <PatternLayout pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} %level [%thread][%file:%line] - %msg%n" />
        </Console>
        <!-- 程序员调试日志 -->
        <RollingRandomAccessFile name="DevLog" fileName="${LOG_HOME}/${SERVER_NAME}"
        filePattern="${LOG_HOME}/${SERVER_NAME}.%d{yyyy-MM-dd-HH}.log">
        <PatternLayout pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} %level [%thread][%file:%line] - %msg%n" />
        <Policies>
        <TimeBasedTriggeringPolicy interval="1" modulate="true" />
        </Policies>
        </RollingRandomAccessFile>
        <!-- 游戏产品数据分析日志 -->
        <RollingRandomAccessFile name="ProductLog"
        fileName="${LOG_HOME}/${SERVER_NAME}_${STAT_NAME}"
        filePattern="${LOG_HOME}/${SERVER_NAME}_${STAT_NAME}.%d{yyyy-MM-dd-HH}.log">
        <PatternLayout
        pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} %level [%thread][%file:%line] - %msg%n" />
        <Policies>
        <TimeBasedTriggeringPolicy interval="1"
        modulate="true" />
        </Policies>
        </RollingRandomAccessFile>
    </appenders>
    <loggers>
        <!-- 3rdparty Loggers -->
        <logger name="org.springframework.core" level="info">
        </logger>
        <logger name="org.springframework.beans" level="info">
        </logger>
        <logger name="org.springframework.context" level="info">
        </logger>
        <logger name="org.springframework.web" level="info">
        </logger>
        <logger name="org.jboss.netty" level="warn">
        </logger>
        <logger name="org.apache.http" level="warn">
        </logger>
        <logger name="com.mchange.v2" level="warn">
        </logger>
        <!-- Game Stat logger -->
        <logger name="com.u9.global.service.log" level="info"
        additivity="false">
            <appender-ref ref="ProductLog" />
        </logger>
        <!-- Root Logger -->
        <root level="DEBUG" includeLocation="true">
            <appender-ref ref="DevLog" />
            <appender-ref ref="Console" />
        </root>
    </loggers>
</configuration>

loggers标签,用于定义loggerlever和所采用的appender,其中appender-ref必须为先前定义的appenders的名称,例如,此处为Console。那么log就会以appender所定义的输出格式来输出logroot标签为log的默认输出形式,如果一个类的log没有在loggers中明确指定其输出lever与格式,那么就会采用root中定义的格式。例如以下定义:

<?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.relin.HelloLog4j" level="error" additivity="false">
      <appender-ref ref="Console"/>
    </logger>
    <root level="trace">
      <appender-ref ref="Console"/>
    </root>
  </loggers>
</configuration>

此时,HelloLog4j则会在error级别上输出log,而其他类则会在trace级别上输出log。需要注意的是additivity选项,如果设置为true(默认值)HelloLog4jlog会被打印两次,第二次打印是由于HelloLog4j同时也满足root里面定义的trace。在log4j2中可以配置不同的Logger输出到不同的文件中,如果有时候需要按照不同的级别输出到不同的文件中,则直接在loggerAppenderRef中定义不同的level指向。

<loggers>
    <logger name="com.mvc.login" level="info" additivity="false">
        <appenderRef ref="LoginController" level="error"/>
        <appenderRef ref="InfoController" level="info"/>
    </logger>
</loggers>
下一页