1.日志记录器(Loggers),log4j是一个被广泛使用的Java日志记录框架

  大家平时使用Log4j一般都是在classpath下放置一个log4j的配置文件,1.日志记录器(Loggers),1.日志记录器(Loggers),log4j2 不使用配置文件,  大家平时使用Log4j一般都是在classpath下放置一个log4j的配置文件,job.002.log这种,一个比较完善的日志系统应当有输出媒介、优先级、格式化、日志过滤、日志管理、参数配置等功能,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,log4j是一个被广泛使用的Java日志记录框架,log4j2则是原有log4j的升级版本

图片 5

LoggerContext

  在日记系统中,LoggerContext扮演者首要的角色。但是,依照真实情状,一个应用中大概存在多少个有效的LoggerContext。

Log4j的组成:

Log4j的组成:

 
Log4j由多个根本的重组构成:日志记录器(Loggers),输出端(Appenders)和日志格式化器(Layout)。

1.日志记录器(Loggers):调节要出口哪些日志记录语句,对日记消息举行等级限制。
2.输出端(Appenders):内定了日记将打印到调节台照旧文件中。

3.日志格式化器(Layout):调整天志音信的突显格式。

  于是点开Log4j的源码,商量了一番,发掘采纳Log4j的底层代码完全能够动态变化新的Logger,相比较关键的类有

org.apache.logging.log4j.core.Layout负责格式
org.apache.logging.log4j.core.Appender就是配置文件里的Appender,我们使用FileAppender,也可以使用RollingFileAppender,
org.apache.logging.log4j.core.config.Configuration和org.apache.logging.log4j.core.LoggerContext是负责Log4j的配置的。

日记等级用Level类表示,四个日志等第相应的是贰个整数值,范围和整型值的限量是一模一样的,该整数值愈大,表达警戒品级愈高。Level有9个放置的等第,分别是:

RollingFileAppender

滚动输出日志到文件中,RollingFileAppender 依照TriggeringPolicy
和RolloverPolicy滚动将日志事件输出到fileName钦定的文书中。TriggeringPolicy用于决定是不是触发RolloverPolicy所定义的日志滚动操作,若未设置RolloverPolicy
,则会利用暗中认可设置 DefaultRolloverStrategy。

RollingFileAppender参数如下:

  • append、bufferedIO、bufferSize、createOn德姆and、filter、fileName、immediateFlush、layout、name、ignoreExceptions等质量与FileAppender类似,就不一一概述了;
  • filePattern:存档日志文件的文本名情势,格局格式正视于所运用的RolloverPolicy
  • policy:TriggeringPolicy,触发计谋;触发计策有如下三种:Composite
    Triggering
    Policy(组合政策)、CronTriggeringPolicy(按期触发)、OnStartupTriggeringPolicy(JVM虚构机运营时触发)、SizeBasedTriggeringPolicy(基于日志文件大小触发)、TimeBasedTriggeringPolicy(基于时直接触)
  • strategy:RolloverStrategy,决定期存款档文件名称、数量和岗位的安顿。

其它Appender:
SyslogAppenders将日志记录发送给本地恐怕远程系统的日志服务;SMTPAppender会将日志内容以邮件的格局发送出去;FailoverAppender设置在管理日志的经过中,借使二个要么多个Appender失利,自动切换成任何Appender上等,愈来愈多音讯详见官网

Configuration  

  每叁个LoggerContext都有贰个实惠的Configuaration,它蕴涵了所有的Appenders、context-wide
Filters、LoggerConfigs以及对StrSubstitutor的引用。在重新配置时期,八个Configuaration会同一时间存在;一旦日志器被重复赋予新的Configuaration,旧的Configuaration就能够终止工作并废弃。

测试类:

完全架构:

鸣谢

log4j2使用手续

注:小编笔者当下应用的 IDE 为
速龙lij,自从写Android代码时接纳了Android Studio后,就爱上了 AMDlij
这一种类的制品了。

  1. 下载 log4j2
    的JAR包:从http://logging.apache.org/log4j/2.x/download.html
    官方网站下载最新版Apache Log4j 2 binary
    压缩包,解压后会获得比比较多JA中华V包,只要求将在那之中的 log4j-core-2.7.jar 和
    log4j-api-2.7.jar 加多到花色中就能够;
  2. 在类型的 src 文件夹下增多 log4j2.xml 文件,该公文为 log4j2
    的配备文件,暗中同意文件内容为:

<?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>
  1. 在项目中央银行使 log4j2:

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class LogTest {
    // 获取 Logger 实例
    static Logger logger = LogManager.getLogger();
    public static void main(String[] args) {

        logger.trace("I am a trace message");
        logger.warn("I am a warn message");
        logger.error("I am a error message");
        logger.info("I am a info message");
        logger.fatal("I am a fatal message");
    }
}

意义如下图所示:

图片 1

日记效果图-1

嘿?上边显著定义了五条日志消息,怎么调控台就显得了两条呢?细致的读者maybe会有如此疑心。小小剧透一波:此玄机存在于
log4j 的安插文件中,若想一探毕竟,就三翻五次随作者一齐留神推究吧!

Log4j的组成:

 
Log4j由八个重点的结合构成:日志记录器(Loggers),输出端(Appenders)和日志格式化器(Layout)。

1.日志记录器(Loggers):调节要出口哪些日志记录语句,对日记音信进行等第限制。
2.输出端(Appenders):钦定了日志将打印到调整台还是文件中。

3.日志格式化器(Layout):调节日志音讯的来得格式。

  于是点开Log4j的源码,研商了一番,开掘使用Log4j的最底层代码完全能够动态变化新的Logger,相比首要的类有

org.apache.logging.log4j.core.Layout负责格式
org.apache.logging.log4j.core.Appender就是配置文件里的Appender,我们使用FileAppender,也可以使用RollingFileAppender,
org.apache.logging.log4j.core.config.Configuration和org.apache.logging.log4j.core.LoggerContext是负责Log4j的配置的。

LoggerConfig

  我们平日利用Log4j一般都以在classpath下放置一个log4j的安排文件,举个例子log4j.xml,里面配备好Appenders和Loggers,可是前阵子想做某供给的时候,想要的成效是每三个职务都要有二个单独的日记文件记录下来,举个例子job.001.log,job.002.log这种,这种完全不能够动用布署文件来设置。

2.涉及

log4j是二个被大规模采用的Java日志记录框架,通过利用该框架,我们能够在和谐的体系中依据自家供给灵活配置日志输出格式,进而得到期望格式的日记音讯,用于后续剖析、错误排查等。log4j2则是原有log4j的进级版本,该版本采取更为从简方便。

LoggerConfig

  LoggerConfig将会在Loggers在logging
configuration中被声称的时候创立。在LoggerConfig
拥有一列类的过滤器(Filter),这么些过滤器将会余烬复起全数的笔录日志的平地风波,独有符合供给的日志才会被传送到Appenders。因为LoggerConfig要求将事件传递给Appenders,所以它富有一多级Appenders的援用。

在日志系统中,LoggerContext扮演者首要的剧中人物。不过,依照真实境况,三个施用中或者存在多个有效的LoggerContext。

Configuration  

  每几个LoggerContext都有一个实用的Configuaration,它含有了所有的Appenders、context-wide
Filters、LoggerConfigs以及对StrSubstitutor的引用。在重新配置时期,三个Configuaration会同时设有;一旦日志器被再度赋予新的Configuaration,旧的Configuaration就能够停下职业并甩掉。

日记管理器 LogManager LogManager

log4j2布局格局

log4j2 有如下种种配备方式,可以依据你的希望、喜好等机动选拔:

  1. 由此布置文件进行配置,配置文件能够是 XML、 JSON、 YAML 和
    properties那六种类型中的放肆一种;
  2. 在代码中创造 ConfigurationFactory 和 Configuration 累的完结类;
  3. 在代码中调用Configuration 接口的 API 在暗中认可配置类上增多组件;
  4. 在代码中调用内部类 Logger 的方法完结自定义。

log4j2 不采用布置文件,动态生成logger对象,log4j2logger

  我们平时使用Log4j一般都是在classpath下放置八个log4j的陈设文件,举个例子log4j.xml,里面配备好Appenders和Loggers,可是前阵子想做某必要的时候,想要的法力是每二个职责都要有贰个独门的日记文件记录下来,举例job.001.log,job.002.log这种,这种完全无法选拔安排文件来设置。

一体化架构:

图片 2

遵照logger央求选用去领受或然拒绝该只是她们的八个技能。Log4j允许日志打字与印刷服务打字与印刷到多少个指标地上。在Log4j的传道是叁个出口的目标地对应着三个Appdender。以后的Appender允许是console,
files, remote socket servers, Apache Flume, JMS, remote UNIX Syslog
daemons, and various database APIs。

Appender

   依照logger央求选拔去领受也许拒绝该只是他们的二个技巧。Log4j允许日志打字与印刷服务打印到四个目标地上。在Log4j的布道是二个输出的目标地对应着贰个Appdender。未来的Appender允许是console,
files, remote socket servers, Apache Flume, JMS, remote UNIX Syslog
daemons, and various database APIs。

  是在Log4j2.3下测验通过的。注目的在于不选取Logger的时候势供给调用stop方法将Logger移除,不然小编要好测量检验生成九千四个Logger后便会报错open
too many file。

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.FileAppender;
import org.apache.logging.log4j.core.config.AppenderRef;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.apache.logging.log4j.core.layout.PatternLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * 
 */
public class JobLogFactory {
  private JobLogFactory() {
  }
  public static void start(int jobId) {
   //为false时,返回多个LoggerContext对象,   true:返回唯一的单例LoggerContext
   final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
    final Configuration config = ctx.getConfiguration();
   //创建一个展示的样式:PatternLayout,   还有其他的日志打印样式。
    Layout layout = PatternLayout.createLayout(PatternLayout.DEFAULT_CONVERSION_PATTERN, 
        config, null, null, true, false, null, null);
    //TriggeringPolicy tp = SizeBasedTriggeringPolicy.createPolicy("10MB");
    //Appender appender = RollingFileAppender.createAppender(String.format("
    // logs/test/syncshows-job-%s.log", jobID),
     //       "/logs/test/" + jobID + "/syncshows-job-" + jobID + ".log.gz",
     //       "true", jobID, null, null, null, tp, null, layout, null,
     //       null, null, null, config);
   //  日志打印方式——输出为文件
   Appender appender = FileAppender.createAppender(
        String.format("logs/test/syncshows-job-%s.log", jobId), "true", "false", 
        "" + jobId, null, "true", "true", null, layout, null, null, null, config);
    appender.start();
    config.addAppender(appender);
   AppenderRef ref = AppenderRef.createAppenderRef("" + jobId, null, null);
    AppenderRef[] refs = new AppenderRef[]{ref};
    LoggerConfig loggerConfig = LoggerConfig.createLogger("false", Level.ALL, "" + jobId,
        "true", refs, null, config, null);
    loggerConfig.addAppender(appender, null, null);
    config.addLogger("" + jobId, loggerConfig);
    ctx.updateLoggers();
  }
  public static void stop(int jobId) {
    final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
    final Configuration config = ctx.getConfiguration();
    config.getAppender("" + jobId).stop();
    config.getLoggerConfig("" + jobId).removeAppender("" + jobId);
    config.removeLogger("" + jobId);
    ctx.updateLoggers();
  }
  /**
   * 获取Logger
   *
   * 如果不想使用slf4j,那这里改成直接返回Log4j的Logger即可
   * @param jobId
   * @return
   */
  public static Logger createLogger(int jobId) {
    start(jobId);
    return LoggerFactory.getLogger("" + jobId);
  }
}

 

测试类:

import org.slf4j.Logger;
/**
 * 
simple test
 */
public class LoggerTest {
  public static void main(String[] args) {
    for(int i=0;i<50000;i++) {
      Logger logger = JobLogFactory.createLogger(i);
      logger.info("Testing testing testing 111");
      logger.debug("Testing testing testing 222");
      logger.error("Testing testing testing 333");
      JobLogFactory.stop(i);
    }
  }
}

  致谢,谢谢您的读书! 

实际选拔

log4j2为主概念

Loggerontext
LoggerContext在Logger系统中饰演着锚点的剧中人物,一般的话,八个施用只会存在于三个LoggerContext中,可是也足以依赖使用境况的歧异和类别的现实性需求,为三个门类布局多少个不等的LoggerContext。在同多个LoggerContext下,log系统是能够互通的。

Configuration
Configuration断章取义,正是当前LoggerContext中的全体Logger的配置遇到,每三个LoggerContext均会怀有一个动态可配备的Configuration,该Configuration
包涵了脚下LoggerContext情形中负有的Loggers、Appenders、Filters、Layouts等布署消息。注意:在reConfiguration时期,新旧Configuration均会相同的时候设有,可是一旦重配进度甘休,旧的Configuration就能够失效,配置消息会重定向至新的Configuration中。

Logger
Logger是三个经过给LoggerManager.getLogger()方法传递特定的Logger名称而拿到的一个AbstractLogger实现类对象,该目的自己并不具体进展其余操作,而是通过涉及二个LoggerConfig完结具体的Logger配置,并经过兑现AbstractLogger的章程进行实际的操作。注意:通过同叁个名号得到的Logger对象会指向同一个Logger引用。

LoggerConfig
LoggerConfig包蕴了一个Logger对象的切实安顿音讯,如该Logger关联的Appenders、Filters、过滤等第等。

Filter
过滤器,定义LogEvent的过滤法则。log4j中定义了两种过滤状态:Accept(接受)、Deny(拒绝)和Nertual(中立)。
Accept:该Log伊芙nt将被施行而没有须求调用另外过滤器;
Deny:忽略当前LogEvent,并将该LogEvent的调节权移交给过滤器调用者;
Nertual:中立,也正是说,当前LogEvent应该传递给其余过滤器,如果未有别的过滤器能够传递了,那么就由未来以此过滤器来管理。

Appender
Appender意为出口目标地,肩负将日志音讯转发给期望的输出。它负担接收日志事件,使用Layout格式化事件,然后将其发送给对应的对象。对于一个日记事件,大家得以应用七个Appenders来将事件发送到分歧的靶子位置。举例,大家得以在支配台上展现二个大概的日记事件的同一时间,将其通过邮件的法子发送给钦命的接收者。如今,Appender能够是console、文件、远程socket服务器、Apache
Flume、JMS以及远程 UNIX 系统日志守护进度等。

注意:
在某叁个Logger中被启用的log乞请将被转化到该Logger相关联的的富有Appenders上,並且还有也许会被转接到LoggerConfig的父级的Appenders上。因而可知,假设设置不当的话,会生出一连串的遗传反应。如:Logger
A 承袭自 Logger B,何况两个均是root的子节点,若LoggerConfig B
中定义了一个文件作为Appender的话,那么使用LoggerConfig A和LoggerConfig
B的logger
的log诉求都会在该公文中打字与印刷,文件中便会议及展览示很多种复的日志音信,那会给日志深入分析带来不须求的难为。万幸那是足以被制止的,通过安装
Appender 的 additivity属性为false就能够。(暗许情况下,additivity=”true”)

Layout:
Layout用于定义Log伊夫nt的输出格式。

Appender

   依照logger诉求选取去领受或许拒绝该只是他俩的一个技能。Log4j允许日志打字与印刷服务打字与印刷到七个指标地上。在Log4j的说法是一个输出的指标地对应着一个Appdender。以后的Appender允许是console,
files, remote socket servers, Apache Flume, JMS, remote UNIX Syslog
daemons, and various database APIs。

  是在Log4j2.3下测验通过的。注意在不选择Logger的时候应当要调用stop方法将Logger移除,不然笔者要好测验生成九千四个Logger后便会报错open
too many file。

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.FileAppender;
import org.apache.logging.log4j.core.config.AppenderRef;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.apache.logging.log4j.core.layout.PatternLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * 
 */
public class JobLogFactory {
  private JobLogFactory() {
  }
  public static void start(int jobId) {
   //为false时,返回多个LoggerContext对象,   true:返回唯一的单例LoggerContext
   final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
    final Configuration config = ctx.getConfiguration();
   //创建一个展示的样式:PatternLayout,   还有其他的日志打印样式。
    Layout layout = PatternLayout.createLayout(PatternLayout.DEFAULT_CONVERSION_PATTERN, 
        config, null, null, true, false, null, null);
    //TriggeringPolicy tp = SizeBasedTriggeringPolicy.createPolicy("10MB");
    //Appender appender = RollingFileAppender.createAppender(String.format("
    // logs/test/syncshows-job-%s.log", jobID),
     //       "/logs/test/" + jobID + "/syncshows-job-" + jobID + ".log.gz",
     //       "true", jobID, null, null, null, tp, null, layout, null,
     //       null, null, null, config);
   //  日志打印方式——输出为文件
   Appender appender = FileAppender.createAppender(
        String.format("logs/test/syncshows-job-%s.log", jobId), "true", "false", 
        "" + jobId, null, "true", "true", null, layout, null, null, null, config);
    appender.start();
    config.addAppender(appender);
   AppenderRef ref = AppenderRef.createAppenderRef("" + jobId, null, null);
    AppenderRef[] refs = new AppenderRef[]{ref};
    LoggerConfig loggerConfig = LoggerConfig.createLogger("false", Level.ALL, "" + jobId,
        "true", refs, null, config, null);
    loggerConfig.addAppender(appender, null, null);
    config.addLogger("" + jobId, loggerConfig);
    ctx.updateLoggers();
  }
  public static void stop(int jobId) {
    final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
    final Configuration config = ctx.getConfiguration();
    config.getAppender("" + jobId).stop();
    config.getLoggerConfig("" + jobId).removeAppender("" + jobId);
    config.removeLogger("" + jobId);
    ctx.updateLoggers();
  }
  /**
   * 获取Logger
   *
   * 如果不想使用slf4j,那这里改成直接返回Log4j的Logger即可
   * @param jobId
   * @return
   */
  public static Logger createLogger(int jobId) {
    start(jobId);
    return LoggerFactory.getLogger("" + jobId);
  }
}

 

测试类:

import org.slf4j.Logger;
/**
 * 
simple test
 */
public class LoggerTest {
  public static void main(String[] args) {
    for(int i=0;i<50000;i++) {
      Logger logger = JobLogFactory.createLogger(i);
      logger.info("Testing testing testing 111");
      logger.debug("Testing testing testing 222");
      logger.error("Testing testing testing 333");
      JobLogFactory.stop(i);
    }
  }
}

  致谢,感激您的翻阅! 

不使用计划文件,动态生成logger对象,log4j2logger
大家平时使用Log4j一般都以在classpath下放置一个log4j的配置文件,举个例子log4j.xml,里面配…

log4j2 不应用安插文件,动态生成logger对象

LoggerContext

  在日记系统中,LoggerContext扮演者首要的剧中人物。不过,依照实情,二个行使中恐怕存在三个有效的LoggerContext。

threshold:Appender能够有所阈值等级,并忽略具备低于阈值品级的级其余别的日志记录信息。

透过计划文件配置log4j

现阶段小编还只使用了文件的安插方式,所以本文重视于通过配备文件配置log4j,以后有机会再杰出研商一波代码配置的方法,然后与看官分享
\_

 

LoggerConfig

  LoggerConfig将会在Loggers在logging
configuration中被声称的时候创立。在LoggerConfig
具备一列类的过滤器(Filter),那几个过滤器将会恢复生机全数的记录日志的风浪,只有符合必要的日记才会被传送到Appenders。因为LoggerConfig须求将事件传递给Appenders,所以它富有一多重Appenders的援用。

Appender对象用于将日志消息打印到区别对象(如调控台,文件,套接字,NT事件日志等),全部品类:

log4j2 日志组件

下图是Apache官方网站贴出的log4j的类图,通过此类图能够清楚地看出log4j的类等级次序结构。

图片 3

log4j2类档期的顺序结构图

由类图能够看出:log4j第22中学至关心注重要涵盖如下概念/组成都部队分:Loggerontext、Configuration、Filter、Logger、LoggerConfig、Appender、Layout等,后文种详细解释那几个概念。

log4j2 由以下八个主导组件组成:

  • Loggers:Logger担负捕捉事件并将其发送给合适的Appender;
  • Appenders:担负对Logger传来的日记事件进展拍卖,如过滤、格式化等,然后将拍卖后的日记事件记录到钦点地点;
  • Layouts:负担对日记事件中的数据开展转变和格式化;Layouts决定了数码在一条日志记录中的最后方式。

当Logger记录叁个风浪时,它将事件转载给适当的Appender。然后Appender使用Layout来对日记记录实行格式化,并将其发送给调整台、文件或任何指标地方。别的,Filters可以让您越发钦命二个Appender是还是不是可以利用在一条特定的日记记录上。在日记配置中,Filters并非少不了的,但能够令你越来越灵敏地决定日志新闻的流淌。

于是点开Log4j的源码,切磋了一番,开采使用Log4j的底部代码完全能够动态变化新的Logger,相比根本的类有

图片 4

OFF 最大整数(Integer.MAX_VALUE)

Layout

log4j第22中学利用相当多的Layout为帕特ternLayout,格式为:

<PatternLayout pattern = "%d{yyyy-MM-dd HH:mm:ss z} %-5level %class{36}%L%M - %msg%xEx%n" />

%d{HH:mm:ss:SSS}:日志输出时间,正确到皮秒
%t:当前线程名称
%-5level:日志等级,-5代表左对齐并牢固输出5个字符,假使不足侧面补零
%logger:logger名称
%msg:日志文本
%n:换行
%F:文件所在的类公事名
%L:行号
%M:所在方法名
%l:语句所在的行数,富含类名,方法名,文件名,行数

Configuration  

日记应该怎么打,在哪些岗位,供给打字与印刷出来怎么着的要紧参数?

configuration

configuration决定了现阶段上下文的loggers配置音讯,是铺排文件根节点,首要含有如下边性值:

  • name:当前布署的称号
  • dest:输出地点,标准错误流、文件或远程邮件发送
  • status:是还是不是记录 Log4j 自个儿的event新闻,默以为 off,可选值有:
    “trace”, “debug”, “info”, “warn”, “error” and “fatal”
  • strict:是或不是使用strict
    xml方式,configuration援助concise(简约)和strict(严俊)二种情势的xml。简约情势下,使得文件编写起来更简明

LoggerContext

filter:Filter对象说了算日志记录央浼是由特定Appender管理大概大意。

布置文件详解

正如是个比较完好详细的 XML
格局的配备文件,该文件通过注释的措施提供轻巧表达以便于明白。

<?xml version="1.0" encoding="UTF-8"?>
<!-- configuration 有多个属性,常用的有:name(配置名)
status(是否记录log4j2本身的event信息,默认是OFF,
可选值有: "trace", "debug", "info", "warn", "error" and "fatal")
dest(错误流输出位置,标准错误流、文件或远程邮件发送)
strict(是否使用strict xml形式,configuration支持concise(简约)和strict(严格)两种模式的xml。
简约模式下,使得文件编写起来更简洁) -->
<configuration status="OFF">
    <!-- 定义如下几个引用名,用于后面配置文件中使用 -->
    <Properties>
        <property name="log_pattern">%d{yyyy-MM-dd HH:mm:ss z} %-5level %class{36}%L%M - %msg%xEx%n
</property><!-- 日志输出格式 -->
        <property name="log-path">${web:rootDir}/logs</property><!-- ${web:rootDir}是项目根目录 -->
        <property name="every_file_size">5M</property><!-- 日志切割的最小单位 -->
        <property name="output_log_level">debug</property><!-- 日志输出级别 -->
    </Properties>

    <!-- 先定义所有的appender(日志输出位置) -->
    <appenders>

        <!-- 输出到控制台 name: 当前appender名 target: 目的位置-->
        <Console name="Console" target="SYSTEM_OUT">
            <!-- ThresholdFilter: 用于定义过滤机制 -->
            <!-- level: 日志过滤级别 -->
            <!-- onMatch="ACCEPT":保留level 及以上级别的日志 -->
            <!-- onMismatch="DENY":丢掉level 以下级别的日志-->
            <!-- onMatch 和 onMissmatch 可选值为:ACCEPT DENY NEUTRAL-->
            <ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY" />

            <!--这个都知道是输出日志的格式 -->
            <PatternLayout pattern="${log_pattern}" />
        </Console>

        <!-- debug级别日志文件 -->
        <!-- RollingFile:日志滚动输出 -->
        <!--每次大小超过size,则这size大小的日志会自动进行压缩,作为存档 -->
        <RollingFile name="app_debug" fileName="${log-path}/debug/debug.log" 
filePattern="${log-path}/debug/debug-%d{yyyy-MM-dd}-%i.log.gz">
            <Filters>
                <ThresholdFilter level="info" onMatch="DENY" onMismatch="NEUTRAL" />
                <ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="NEUTRAL" />
            </Filters>
            <PatternLayout pattern="${log_pattern}" />
            <!-- SizeBasedTriggeringPolicy: 基于日志大小切分日志 -->
            <SizeBasedTriggeringPolicy size="${every_file_size}"/>
        </RollingFile>

        <!-- info级别日志文件 -->
        <RollingFile name="app_info" fileName="${log-path}/info/info.log" 
filePattern="${log-path}/info/info-%d{yyyy-MM-dd}-%i.log.gz">
            <Filters>
                <ThresholdFilter level="warn" onMatch="DENY" onMismatch="NEUTRAL" />
                <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY" />
            </Filters>
            <PatternLayout pattern="${log_pattern}" />
            <SizeBasedTriggeringPolicy size="${every_file_size}"/>
        </RollingFile>

        <!-- error级别日志文件 -->
        <RollingFile name="app_error" fileName="${log-path}/error/error.log" 
filePattern="${log-path}/error/error-%d{yyyy-MM-dd}-%i.log.gz">
            <Filters>
                <ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY" />
            </Filters>
            <PatternLayout pattern="${log_pattern}" />
            <SizeBasedTriggeringPolicy size="${every_file_size}"/>
        </RollingFile>

    </appenders>

    <!-- 定义logger,只有定义了logger并引入之前定义的appender,appender才会生效 -->
    <loggers>
        <!--建立一个默认的root的logger,需要在root的level中指定输出的级别, -->
        <root level="${output_log_level}">
            <appender-ref ref="Console" />
            <appender-ref ref="app_debug"/>
            <appender-ref ref="app_info"/>
            <appender-ref ref="app_error"/>
        </root>
    </loggers>

</configuration>
importorg.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.FileAppender;
import org.apache.logging.log4j.core.config.AppenderRef;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.apache.logging.log4j.core.layout.PatternLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * 
 */
public class JobLogFactory {
  private JobLogFactory() {
  }
  public static void start(int jobId) {
   //为false时,返回多个LoggerContext对象,   true:返回唯一的单例LoggerContext
   final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
    final Configuration config = ctx.getConfiguration();
   //创建一个展示的样式:PatternLayout,   还有其他的日志打印样式。
    Layout layout = PatternLayout.createLayout(PatternLayout.DEFAULT_CONVERSION_PATTERN, 
        config, null, null, true, false, null, null);
    //TriggeringPolicy tp = SizeBasedTriggeringPolicy.createPolicy("10MB");
    //Appender appender = RollingFileAppender.createAppender(String.format("
    // logs/test/syncshows-job-%s.log", jobID),
     //       "/logs/test/" + jobID + "/syncshows-job-" + jobID + ".log.gz",
     //       "true", jobID, null, null, null, tp, null, layout, null,
     //       null, null, null, config);
   //  日志打印方式——输出为文件
   Appender appender = FileAppender.createAppender(
        String.format("logs/test/syncshows-job-%s.log", jobId), "true", "false", 
        "" + jobId, null, "true", "true", null, layout, null, null, null, config);
    appender.start();
    config.addAppender(appender);
   AppenderRef ref = AppenderRef.createAppenderRef("" + jobId, null, null);
    AppenderRef[] refs = new AppenderRef[]{ref};
    LoggerConfig loggerConfig = LoggerConfig.createLogger("false", Level.ALL, "" + jobId,
        "true", refs, null, config, null);
    loggerConfig.addAppender(appender, null, null);
    config.addLogger("" + jobId, loggerConfig);
    ctx.updateLoggers();
  }
  public static void stop(int jobId) {
    final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
    final Configuration config = ctx.getConfiguration();
    config.getAppender("" + jobId).stop();
    config.getLoggerConfig("" + jobId).removeAppender("" + jobId);
    config.removeLogger("" + jobId);
    ctx.updateLoggers();
  }
  /**
   * 获取Logger
   *
   * 如果不想使用slf4j,那这里改成直接返回Log4j的Logger即可
   * @param jobId
   * @return
   */
  public static Logger createLogger(int jobId) {
    start(jobId);
    return LoggerFactory.getLogger("" + jobId);
  }
}

Appenders

Appenders用于定义当前LoggerContext中所要求运用到的Appender。近年来log4j2提供了二种差别类型的appender可供配置。如下介绍两种常用的,固然想打听更完善的音信,可活动官网

import org.slf4j.Logger;
/**
 * 
simple test
 */
public class LoggerTest {
  public static void main(String[] args) {
    for(int i=0;i<50000;i++) {
      Logger logger = JobLogFactory.createLogger(i);
      logger.info("Testing testing testing 111");
      logger.debug("Testing testing testing 222");
      logger.error("Testing testing testing 333");
      JobLogFactory.stop(i);
    }
  }
}

4.化解方案

Appender类型

ConsoleAppender:
ConsoleAppender是最常用的Appenders之一,它只是将日志新闻突显到调整台上。log4j2的暗中认可Appender即为ConsoleAppender。

ConsoleAppender参数如下:

  • filter:用于决定是不是必要利用该Appender来管理当下日记事件,通过动用CompositeFilter能够整合使用多少个Filter;
  • layout:用于决定怎么着对日记记录进行格式化,默许情形下选取“%m%n”,它会在每一行显示一条日志记录;
  • follow:用于决定Appender是不是须要领悟输出(system.out也许system.err)的生成,默许情状是无需追踪这种转换;
  • name:用于设置Appender的名字;
  • ignoreExceptions:默以为true,用于决定是还是不是须求记录在日记事件管理进程中出现的那些;
  • target:用于内定输出指标地点,暗中认可意况下使用SYSTEM_OUT,但也足以修改成SYSTEM_ERR

FileAppender:
FileAppenders将日志记录写入到文件中,它承受张开、关闭文件,向文件中追加日志记录,并对文件进行加锁,以防数据被毁掉大概覆盖。
FileAppender参数如下:

  • append:是或不是扩大写入,默以为true,表示将日志事件追加在文件末尾,若设置为false,则每一遍都会先清空文件,然后将日志事件写入文件中;
  • bufferedIO:默以为true,表示使用缓存,也正是说每回举办日志输出时会先将日志事件输出到缓存中,缓存满也许安装了immediateFlush
    时,才将日志事件写入磁盘文件。注意:llocking属性不能够与该属性同期采纳;
  • bufferSize:缓存大小,默感觉8192字节;
  • createOn德姆and:当须要时才创造日志文件,即独有当有日记事件必要被输出到该文件中时才成立文件;
  • filter:过滤器,含义与ConsoleAppender中相似;
  • fileName:日志文件名;
  • immediateFlush:表示每一遍写完日志后均进行flush,那能够有限扶助每回日志均被写入磁盘中了;
  • layout:格式化;
  • locking:是还是不是对该日记文件加锁,一般用来多主飞机场景中,默以为false,该属性对质量影响相当的大,须要郁郁寡欢运用;
  • name:Appender名称;
  • ignoreExceptions:用法同ConsoleAppender。

每贰个LoggerContext都有叁个使得的Configuaration,它含有了所有的Appenders、context-wide
Filters、LoggerConfigs以及对StrSubstitutor的援引。在重新配置时期,四个Configuaration会同不平时候设有;一旦日志器被再度赋予新的Configuaration,旧的Configuaration就可认为止专业并屏弃。

树立maven工程,在pom.xml文件中步向注重包,通过设置Log
Level,定义Appender和在配备文件中钦点Layout对象来布署log4j。log4j.properties
文件是叁个log4j配置文件,它保留键/值对中的属性。暗中同意境况下, LogManager
在CLASSPATH中查找名字为log4j.properties的公文。

log4j2 日志等第

log4j2 中默许的日记品级为:trace < debug < info < warn <
error < fatal
当设置了日志输出品级时,当前品级及以上级其他日志会输出,而眼前品级之下级其余日志则不会输出,系统私下认可输出等级为
error,也等于说默许设置下,独有 error 和
fatal这两级日志会输出,那也就分解了为什么下面只输出了两条日志音信

  • trace:即追踪,程序每推进一步均可输出一条trace日志,重要用来表现程序运转轨迹
  • debug:调试
  • info:输出你感兴趣的音讯,一般用来着力的、高档次的会诊信息。在长日子运作的代码段伊始运转及善终运转时应有生出消息,以便通晓今后系统在干什么。不过这么的音信不宜太过频仍
  • warn:提示音讯
  • error:错误新闻,彰显一个荒唐,或一个通用的谬误意况,但还未必会将系统挂起。这种程度的一无可取一般会接触邮件的出殡和埋葬,将消息发送到alert
    list中,运转人士能够在文书档案中著录那些bug并提交
  • fatal:会导致程序崩溃的首要失实,用在最为的图景中,即必须马上获得注意的情状

大家平时使用Log4j一般都是在classpath下放置三个log4j的安顿文件,比方log4j.xml,里面配备好Appenders和Loggers,然则前阵子想做某须要的时候,想要的法力是每二个任务都要有八个独门的日记文件记录下来,举个例子job.001.log,job.002.log这种,这种完全不可能运用布署文件来设置。

每一种Appender对象都具有与其关联的两样性质,那个属性提示该对象的一举一动。

log4j2 配置节点解析

LoggerConfig将会在Loggers在logging
configuration中被声称的时候创立。在LoggerConfig
具有一列类的过滤器(Filter),这几个过滤器将会大张旗鼓全数的记录日志的平地风波,独有符合供给的日记才会被传送到Appenders。因为LoggerConfig需求将事件传递给Appenders,所以它富有一二种Appenders的援引。

Common-logging、SLF4J、Logback

文件配置优先级

对应于四类配置文件:XML、 JSON、 YAML 和 properties,Log4j
分别有与之相应的 ConfigurationFactory
完毕类,分裂的贯彻类能够加载分化扩大名的安顿文件中的配置新闻。当 Log4j
运营时会根据一定的先行级依次在classpath(一般是项目标src文件夹下)查找项目中的配置文件,若找到多少个布署文件,就调用与当下文件扩充名对应的ConfigurationFactory实现类加载该配置文件中的配置音讯,否则继续查找下一优先级的安顿文件,若未找到任何配置文件,就使用默许配置DefaultConfiguration。
昨今差异陈设文件的事先级如下图所示:

图片 5

布局文件优先级

全体架构:

FINEST 300

1.日志记录器(Loggers):调节要出口哪些日志记录语句,对日记新闻举行品级限制。
2.输出端(Appenders):钦命了日志将打字与印刷到调整台依旧文件中。

日记记录器 Logger Logger