【log】log4j 2

关于                                                                                                   

log4j 2 是 log4j 1 的升级版 ,log4j 1 的项目 已经终止 。

log4j 2 特色 和 提升:

    ★ API 分离  :  API 和 实现类 分离 ,即现在需要两个 jar 包  : log4j-api   |  log4j-core

    ★ 性能提升 : 基于LMAX Disruptor 类库的异步日志在多线程环境下 性能超出其他框架

    ★  支持多种 API :支持 Log4j 1.2 ,SLF4J, Commons Logging , java.util.logging(JUL)

    ★ java 8 Lambda 支持

    ★ 自定义 log  level

     ...

组成

   参看 对比 log4j 1.x

                                                  

Logger logger = Logger.getLogger(this.class.getName); //log4j 1.x 
Logger logger = LogManager.getLogger(this.class.getName());//log4j 2
log4j 2  使用 LogManager 请求 Logger,LogManager 会找到 合适的 LoggerContext ,然后从中获取 Logger.


    Logger  层

log4j 1.x  中 Logger 层 是 通过 Loggers 之间的关系 保持 , log4j 2 是 通过 LoggerConfig 对象之间 的关系 保持。

获取根 Logger:

Logger logger = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);
Logger logger = LogManager.getRootLogger();

    LoggerContext

LoggerContext 在 logging 系统 中 扮演着 锚点的作用。

   Configuration

每一个 LoggerContext  对应着一个 有效的 Configuration , Configuration 包含 所有 的 Appenders,context 过滤器,LoggerConfigs ...

    Logger

logger记录器取代了 System.out.println 的 直接输出语句

    LoggerConfig

LoggerConfig  将 分配一个 log level

    Appender

    一个输出目标被称为一个 appender 。大多数的 appenders  也支持配置一个 layout

     Layout

代表输出的log 的格式;

配置                                                                                

log4j 2 的配置  可以用以下四种方式实现:

   ★  通过 XML,JSON,YAML,或者 properties 形式的文件 写 配置文件

   ★ 以编程的方式 ,通过创建  ConfigurationFactory 和 Configuration 实现类

   ★ 以编程的方式,调用   Configuration 接口中 的 API 添加 组件

   ★ 以编程的方式,调用内置 Logger 类的 方法

但是参看了官网的大部分栗子都是 xml 的 ,看来还是比较推崇典型的 xml 形式;


自动配置

log4j 可以在初始化时 自动配置  ,log4j 2  包含四种 ConfigurationFactory 的实现类 :

   ★   一种适用于 JSON 的 JSON ConfigurationFactory

   ★  一种适用于 YAML 的 YAML ConfigurationFactory

   ★  一种适用于 Properties 的 Properties ConfigurationFactory

   ★  一种适用于 XML 的 XML ConfigurationFactory

自动配置机制 :

 ① 首先 Log4j 2  检查 "log4j.configurationFile" 的 系统属性,如果设置 ,则使用 ConfigurationFactory 尝试加载 配置文件。

 ② 如果没有设置 该系统属性,properties ConfigurationFactory 会在 classpath 下 寻找 log4j2-test.properties.

 ③ 没有此类文件, YAML ConfigurationFactory 在 classpath 下寻找 log4j2-test.yaml 或者 log4j2-test.yml

 ④ 没有此类文件,JSON ConfigurationFactory 在 classpath 下寻找 log4j2-test.json或者 log4j2-test.jsn

  ⑤没有此类文件,XML ConfigurationFactory 在 classpath 下 寻找 log4j2-test.xml.


  ⑥ 没有 test 文件 , properties ConfigurationFactory 会在 classpath 下 寻找  log4j2.properties

  ⑦ 没有 properties 文件 ,YAML ConfigurationFactory 在 classpath 下寻找 log4j2.yml或者 log4j2.yaml

  ⑧ 没有 yaml 文件,JSON ConfigurationFactory 在 classpath 下寻找 log4j2.json或者 log4j2.jsn

   ⑨ 没有 json 文件,XML ConfigurationFactory 在 classpath 下 寻找 log4j2.xml.


   ⑩ 如果都没有, 则 使用 DefaultConfiguration  ,输出到控制台 ,且 输出 level 等级 为  error.

DefaultConfiguration 就像 下面的配置一样(XML):

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="Console"/>
    </Root>
  </Loggers>
</Configuration>


使用XML 配置

XML 简约配置结构:其中的 filter 都是可能会出现的区域,此时 Configuration 的 strict 为 false ,即为 简约配置模式,要求不太高,大小写不敏感

<?xml version="1.0" encoding="UTF-8"?>;
<Configuration>
    <!--配置 变量供 appender 使用-->
    <Properties>
        <Property name="name1">value</property>
        <Property name="name2" value="value2"/>
    </Properties>

    <filter ... />

    <!-- 配置 appender 集合-->
    <Appenders>
        <appender ... >
             <filter ... />
        </appender>
        ...
    </Appenders>

    <!-- 配置 logger 集合-->
    <Loggers>
        <Logger name="name1">
           <filter ... />
        </Logger>
        ...
        <Root level="level">
              <AppenderRef ref="name"/>
        </Root>
    </Loggers>
</Configuration>



XML 苛刻配置结构:此时的 strict 为 true ,通过对比可以发现此处的配置明显要比 上面的配置更严格,都指明了 type 属性,首字母大写

<?xml version="1.0" encoding="UTF-8"?>;
<Configuration>
  <Properties>
    <Property name="name1">value</property>
    <Property name="name2" value="value2"/>
  </Properties>
  <Filter type="type" ... />
  <Appenders>
    <Appender type="type" name="name">
      <Layout type="type" pattern="pattern"/>
      <Filter type="type" ... />
    </Appender>
    ...
  </Appenders>
  <Loggers>
    <Logger name="name1">
      <Filter type="type" ... />
    </Logger>
    ...
    <Root level="level">
      <AppenderRef ref="name"/>
    </Root>
  </Loggers>
</Configuration>

其中
<PatternLayout pattern="%m%n"/>

等价于
<PatternLayout>
  <Pattern>%m%n</Pattern>
</PatternLayout>

严格模式配置的栗子:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug" strict="true" name="XMLConfigTest"
               packages="org.apache.logging.log4j.test">
  <Properties>
    <Property name="filename">target/test.log</Property>
  </Properties>
  <Filter type="ThresholdFilter" level="trace"/>
 
  <Appenders>
    <Appender type="Console" name="STDOUT">
      <Layout type="PatternLayout" pattern="%m MDC%X%n"/>
      <Filters>
        <Filter type="MarkerFilter" marker="FLOW" onMatch="DENY" onMismatch="NEUTRAL"/>
        <Filter type="MarkerFilter" marker="EXCEPTION" onMatch="DENY" onMismatch="ACCEPT"/>
      </Filters>
    </Appender>
    <Appender type="Console" name="FLOW">
      <Layout type="PatternLayout" pattern="%C{1}.%M %m %ex%n"/><!-- class and line number -->
      <Filters>
        <Filter type="MarkerFilter" marker="FLOW" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
        <Filter type="MarkerFilter" marker="EXCEPTION" onMatch="ACCEPT" onMismatch="DENY"/>
      </Filters>
    </Appender>
    <Appender type="File" name="File" fileName="${filename}">
      <Layout type="PatternLayout">
        <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
      </Layout>
    </Appender>
    <Appender type="List" name="List">
    </Appender>
  </Appenders>
 
  <Loggers>
    <Logger name="org.apache.logging.log4j.test1" level="debug" additivity="false">
      <Filter type="ThreadContextMapFilter">
        <KeyValuePair key="test" value="123"/>
      </Filter>
      <AppenderRef ref="STDOUT"/>
    </Logger>
 
    <Logger name="org.apache.logging.log4j.test2" level="debug" additivity="false">
      <AppenderRef ref="File"/>
    </Logger>
 
    <Root level="trace">
      <AppenderRef ref="List"/>
    </Root>
  </Loggers>
 
</Configuration>


 Configuration  元素配置

XML 文件中的 Configuration 标签 (<Configuration>) 可配置的属性:

Attribute NameDescription
advertiser(Optional) The Advertiser plugin name which will be used to advertise individual FileAppender or SocketAppender configurations. The only Advertiser plugin provided is 'multicastdns".
dest亦或是 " err " ,可以输出到 stderr ,或者是一个文件路径 或者 url
monitorInterval自动重新检查配置文件是否改变的最短时间设置,单位为 秒
name配置文件的名称
packagesA comma separated list of package names to search for plugins. Plugins are only loaded once per classloader so changing this value may not have any effect upon reconfiguration.
schemaIdentifies the location for the classloader to located the XML Schema to use to validate the configuration. Only valid when strict is set to true. If not set no schema validation will take place.
shutdownHookSpecifies whether or not Log4j should automatically shutdown when the JVM shuts down. The shutdown hook is enabled by default but may be disabled by setting this attribute to "disable"
status

日志应该被记录到 控制台的 内置 Log4j 事件的等级. 可选值 为  "trace", "debug", "info", "warn", "error" and "fatal".

(应该是 log4j api内部的日志输出设置)

strict开启 XML 严格模式 . 不支持 JSON 配置文件.
verbose加载插件时启用诊断信息


Appenders 元素配置

一个输出目标被称为一个 appender 。大多数的 appenders  也支持配置一个 layout


loggers 配置

logger记录器取代了 System.out.println 的 直接输出语句,每个 Configuration 必须有一个 root logger,


Filters 配置

Log4j 允许在 四个地方指定 一个 filter:

① 在 同等级的 Appenders,loggers 和 properties 元素 之间

② 在 logger 元素 内

③ 在 appeder 元素内

④ 在 appenderRef 元素内




使用 Properties 配置

配置语法  和 log4j 1 不同,而是像 JSON 和 XML 的配置文件一样, properties 配置 是根据 插件 和 插件的 参数 来定义 配置。

log4j 2.6 之前和 之后的 配置不同 ,2.6 之后 ,当第一次使用 identifiers 列表时 不再需要 指定 name。但是如果你要使用多个,仍然要指定。

栗子:

status = error
dest = err
name = PropertiesConfig
 
property.filename = target/rolling/rollingtest.log
 
filter.threshold.type = ThresholdFilter
filter.threshold.level = debug
 
appender.console.type = Console
appender.console.name = STDOUT
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = %m%n
 
appender.rolling.type = RollingFile
appender.rolling.name = RollingFile
appender.rolling.fileName = ${filename}
appender.rolling.filePattern = target/rolling2/test1-%d{MM-dd-yy-HH-mm-ss}-%i.log.gz
appender.rolling.layout.type = PatternLayout
appender.rolling.layout.pattern = %d %p %C{1.} [%t] %m%n
appender.rolling.policies.type = Policies
appender.rolling.policies.time.type = TimeBasedTriggeringPolicy
appender.rolling.policies.time.interval = 2
appender.rolling.policies.time.modulate = true
appender.rolling.policies.size.type = SizeBasedTriggeringPolicy
appender.rolling.policies.size.size=100MB
appender.rolling.strategy.type = DefaultRolloverStrategy
appender.rolling.strategy.max = 5
 
appender.list.type = List
appender.list.name = List
appender.list.filter.threshold.type = ThresholdFilter
appender.list.filter.threshold.level = error
 
logger.rolling.name = com.example.my.app
logger.rolling.level = debug
logger.rolling.additivity = false
logger.rolling.appenderRef.rolling.ref = RollingFile
 
rootLogger.level = info
rootLogger.appenderRef.stdout.ref = STDOUT

hello world                                                 

gradle引用 jar 包:

    compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.7'
    compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.7

hello world:
package com.ycit.log;

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

/**
 * Created by xlch on 2017/2/9.
 */
public class Log4jTest {

    private static final Logger logger = LogManager.getLogger(Log4jTest.class);

    @Test
    public void hello() {
        logger.debug("debug level");
        logger.info("info level");
        logger.trace("trace level");
        logger.fatal("fatal level");
        logger.warn("warn level");
        logger.error("error level");
    }

}

运行 hello world ,输出如下语句:使用了默认的配置(见上)
ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.
14:58:03.937 [main] FATAL com.ycit.log.Log4jTest - fatal level
14:58:03.938 [main] ERROR com.ycit.log.Log4jTest - error level

在 classpath 下添加自定义的 log4j2.xml 配置文件

log4j2.xml(默认的配置)

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="error">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>
重新运行 hello world 后的输出:不再提示未发现配置文件
15:33:00.126 [main] FATAL com.ycit.log.Log4jTest - fatal level
15:33:00.129 [main] ERROR com.ycit.log.Log4jTest - error level


控制台 + 文件中 打印 log信息                                     

依然是上面的 jar 包;

log4j2.xml 配置:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="off">

    <!--  配置一些参数以备用   -->
    <Properties>
        <property name="log_home">logs</property>
        <property name="log_error" value="log-error.log"/>
        <property name="log_all" value="log.log"/>
    </Properties>

    <!-- 配置输出终端 通常包括控制台,文件 等 ,配置属性可以通过查看对应源代码进行配置-->
    <!--  例如配置RollingFile ,则可参看 RollingFileAppender 类 中的属性参数进行配置 -->
    <Appenders>
        <!-- 配置控制台输出 -->
        <Console name="Console" target="SYSTEM_OUT">

            <!-- 配置布局形式 -->
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>

        <!--  配置文件输出,注意 log4j2 中未提供 DailyRollingFile ,可以直接在 RollingFile 中选择策略以达到 DailyRollingFile 的效果 -->
        <!-- fileName:当前输出的文件路径  filePattern:rolling后原文件的名称 格式-->
        <RollingFile name="dailyRollingFile" fileName="${log_home}/${log_all}"
                     filePattern="${log_home}/${log_all}.%d{yyyy-MM-dd}.log" append="true">
            <ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
            <policies>
                <!--  基于时间的策略 -->
                <TimeBasedTriggeringPolicy modulate="true" interval="1"/>
            </policies>
        </RollingFile>
        <RollingFile name="rollingFile" fileName="${log_home}/${log_error}"
                     filePattern="${log_home}/${log_error}.%d{yyyy-MM-dd}.log" append="true">
            <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
            <policies>
                <!--  基于文件大小的策略,默认10mb之后另起一个文件 -->
                <SizeBasedTriggeringPolicy/>
            </policies>
        </RollingFile>
    </Appenders>

    <!--  配置记录器 -->
    <Loggers>
        <logger name="org.springframework" level="INFO"></logger><!-- spring 的记录器,控制spring输出 -->
        <Root level="debug"> <!-- 根记录器,所有记录器的父 -->
            <AppenderRef ref="Console" level="debug"/>
            <AppenderRef ref="dailyRollingFile" level="error"/>
            <AppenderRef ref="rollingFile" level="debug"/>
        </Root>
    </Loggers>
</Configuration>




web 项目中使用,结合 SLF4J                              

gradle jar 包引用

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.11'
    compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.7'
    compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.7'
    compile group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: '2.7'
    compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.21'
}

log4j2.xml 同上面的配置

使用的时候,使用 slf4j 的api 进行日志记录

栗子:

package com.ycit.log;

import com.ycit.Log;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Created by xlch on 2017/2/11.
 */
public class Slf4j {

    private static final Logger logger = LoggerFactory.getLogger(Slf4j.class);

    public static void main(String [] args) {
        logger.trace("log4j2 trace level");
        Log log = new Log();
        log.log();
        logger.debug("exit app");
    }

}

properties 配置:控制台 和 文件 打印(时间的没调试好):

log4j2.properties

## The level of internal Log4j events that should be logged to the console
## 可选 "trace", "debug", "info", "warn", "error" and "fatal"
status = error
##will send output to stderr, or a file path or URL.
dest = err
## The name of the configuration
name = PropertiesConfig

property.filename = d:\\logs\\loader\\
property.fileSize = 10MB
property.projectName = loader

#filter.threshold.type = ThresholdFilter
#filter.threshold.level = debug

appender.console.type = Console
appender.console.name = STDOUT
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = [%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n

appender.rolling.type = RollingFile
appender.rolling.name = RollingFile
appender.rolling.filter.threshold.level = debug
appender.rolling.filter.threshold.type = ThresholdFilter
appender.rolling.fileName = ${filename}\\${projectName}.log
appender.rolling.filePattern =${filename}\\${projectName}-%d{MM-dd-yy-HH-mm-ss}-%i.log
appender.rolling.layout.type = PatternLayout
appender.rolling.layout.pattern = %d{yyyy-MM-dd HH:mm:ss.SSS} %level [%t] [%c] [%M] [%l] - %msg%n
appender.rolling.policies.type = Policies

# Rotate log file each day
#appender.rolling.policies.time.type = TimeBasedTriggeringPolicy
#appender.rolling.policies.time.interval = 2
#appender.rolling.policies.time.modulate = true

# Rotate log file by size
appender.rolling.strategy.type = DefaultRolloverStrategy
appender.rolling.policies.size.type = SizeBasedTriggeringPolicy
appender.rolling.policies.size.size=${fileSize}
appender.rolling.strategy.max = 5


#appender.error.type=RollingFile
#appender.error.name=RollingFileError
#appender.error.filter.threshold.level = error
#appender.error.filter.threshold.type = ThresholdFilter
#appender.error.fileName=${filename}/${projectName}_error.log
#appender.error.filePattern=${filename}/${projectName}_error.%d{yyyy-MM-dd-HH}.log
#appender.error.layout.type=PatternLayout
#appender.error.layout.pattern=%d %p %C{1.} [%t] %m%n
#appender.error.policies.type=Policies
#appender.error.policies.size.type=SizeBasedTriggeringPolicy
#appender.error.policies.size.size=${fileSize}
#appender.error.strategy.type=DefaultRolloverStrategy

appender.error.type = RollingFile
appender.error.name = RollingFileError
appender.error.filter.threshold.level = error
appender.error.filter.threshold.type = ThresholdFilter
appender.error.fileName = ${filename}\\${projectName}_error.log
appender.error.filePattern =${filename}\\${projectName}_error-%d{MM-dd-yy-HH-mm-ss}-%i.log
appender.error.layout.type = PatternLayout
appender.error.layout.pattern = %d{yyyy-MM-dd HH:mm:ss.SSS} %level [%t] [%c] [%M] [%l] - %msg%n
appender.error.policies.type = Policies

# Rotate log file each day
#appender.rolling.policies.time.type = TimeBasedTriggeringPolicy
#appender.rolling.policies.time.interval = 2
#appender.rolling.policies.time.modulate = true

# Rotate log file by size
appender.error.strategy.type = DefaultRolloverStrategy
appender.error.policies.size.type = SizeBasedTriggeringPolicy
appender.error.policies.size.size=${fileSize}
appender.error.strategy.max = 5

#针对某个包的配置
logger.rolling.name = com.vastio
logger.rolling.level = debug
logger.rolling.additivity = false
logger.rolling.appenderRef.rolling.ref = RollingFile
logger.rolling.appenderRef.console.ref = STDOUT
logger.rolling.appenderRef.error.ref = RollingFileError

#全局配置
rootLogger.level = debug
rootLogger.additivity = false
rootLogger.appenderRef.rolling.ref = RollingFile
rootLogger.appenderRef.console.ref = STDOUT
rootLogger.appenderRef.error.ref = RollingFileError






  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值