精华内容
下载资源
问答
  • 在创建Spring Boot工程时,我们引入了spring-boot-starter,其中包含了spring-boot-starter-logging,该依赖内容就是Spring Boot默认的日志框架Logback,所以我们在引入log4j之前,需要先排除该包的依赖,再引入log4...

    在创建Spring Boot工程时,我们引入了spring-boot-starter,其中包含了spring-boot-starter-logging,该依赖内容就是Spring Boot默认的日志框架Logback,所以我们在引入log4j之前,需要先排除该包的依赖,再引入log4j的依赖。

    log4j有两个版本,差距较大,
    springboot1.3.x以下版本才支持log4j ,1.3.x以上版本只支持log4j2

    区别在于需要引入的包
    log4j

    <artifactId>spring-boot-starter-log4j</artifactId>
    

    log4j2

    <artifactId>spring-boot-starter-log4j2</artifactId>
    

    刚刚上面说过,在引入log4j依赖之前需要先排除默认引入的logging

     <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
    <!--            排除自带的日志框架-->
                <exclusions>
                    <exclusion>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-logging</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
    

    因为log4j2对于log4j来说有很多变动,如果不喜欢用log4j2,1.3.x版本以上的spring boot框架也可以引入以下两个包使用log4j。

    <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
    </dependency>
    
    <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
    </dependency>
    

    配置log4j2.xml
    在引入了log4j依赖之后,只需要在src/main/resources目录下加入log4j-spring.properties配置文件,就可以开始对应用的日志进行配置使用。

    注意:Spring Boot官方推荐优先使用带有-spring的文件名作为你的日志配置(如使用log4j-spring.properties,而不是log4j.properties,不过取名为log4j.properties也是没有问题的)

    但是 log4j2版本则需要注意,只能使用非properties文件进行配置,xml或者yml,或者Json。

    在application.properties中指定特定配置文件(新版本boots)
    log4j.config=classpath:log4j.properties

    配置日志输出级别
    其中INFO是日志输出级别,共有5级:

    FATAL       0  
    ERROR      3  
    WARN       4  
    INFO         6  
    DEBUG      7 
    

    通过如下配置,设定root日志的输出级别为INFO,appender为控制台输出stdout

    log4j.rootCategory=INFO, stdout
    

    配置日志输出的格式

    Layout:日志输出格式,Log4j提供的layout有以下几种:
    org.apache.log4j.HTMLLayout(以HTML表格形式布局),
    org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
    org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
    org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
    

    配置日志打印参数

    log4j.appender.A1.layout.ConversionPattern=%-4r %-5p %d{yyyy-MM-dd HH:mm:ssS} %c %m%n
    

    日志信息格式中几个符号所代表的含义

    -X号: X信息输出时左对齐;
     %p: 输出日志信息优先级,即DEBUG,INFO,WARN,ERROR,FATAL,
     %d: 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:20021018221028921
     %r: 输出自应用启动到输出该log信息耗费的毫秒数
     %c: 输出日志信息所属的类目,通常就是所在类的全名
     %t: 输出产生该日志事件的线程名
     %l: 输出日志事件的发生位置,相当于%C.%M(%F:%L)的组合,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main (TestLog4.java:10)
     %x: 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。
     %%: 输出一个"%"字符
     %F: 输出日志消息产生时所在的文件名称
     %L: 输出代码中的行号
     %m: 输出代码中指定的消息,产生的日志具体信息
     %n: 输出一个回车换行符,Windows平台为"/r/n",Unix平台为"/n"输出日志信息换行
     可以在%与模式字符之间加上修饰符来控制其最小宽度、最大宽度、和文本的对齐方式。如:
     1)%20c:指定输出category的名称,最小的宽度是20,如果category的名称小于20的话,默认的情况下右对齐。
     2)%-20c:指定输出category的名称,最小的宽度是20,如果category的名称小于20的话,"-"号指定左对齐。
     3)%.30c:指定输出category的名称,最大的宽度是30,如果category的名称大于30的话,就会将左边多出的字符截掉,但小于30的话也不会有空格。
     4)%20.30c:如果category的名称小于20就补空格,并且右对齐,如果其名称长于30字符,就从左边较远输出的字符截掉。
    

    配置日志输出位置:
    Appender 为日志输出目的地,Log4j提供的appender有以下几种:
    log4j.appender.file=org.apache.log4j.DailyRollingFileAppender

    file代表是file这个日志,日志有很多的,数据库,控制台,等都可以配置

    org.apache.log4j.ConsoleAppender(控制台),
    org.apache.log4j.FileAppender(文件),
    org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
    org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件),
    org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
    

    列子1:

     ### set log levels ###
    log4j.rootLogger = debug ,  stdout ,  D ,  E
    
    ### 输出到控制台 ###
    log4j.appender.stdout = org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.Target = System.out
    log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern =  %d{ABSOLUTE} %5p %c{ 1 }:%L - %m%n
    
    ### 输出到日志文件 ###
    log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
    log4j.appender.D.File = logs/log.log
    log4j.appender.D.Append = true
    log4j.appender.D.Threshold = DEBUG ## 输出DEBUG级别以上的日志
    log4j.appender.D.layout = org.apache.log4j.PatternLayout
    log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
    
    ### 保存异常信息到单独文件 ###
    log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
    log4j.appender.E.File = logs/error.log ## 异常日志文件名
    log4j.appender.E.Append = true
    log4j.appender.E.Threshold = ERROR ## 只输出ERROR级别以上的日志!!!
    log4j.appender.E.layout = org.apache.log4j.PatternLayout
    log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
    

    配置日志输出到数据库中

    log4j.rootCategory=INFO,stdout,jdbc
    
    log4j.appender.jdbc=org.apache.log4j.jdbc.JDBCAppender
    log4j.appender.jdbc.driver=com.mysql.jdbc.Driver
    log4j.appender.jdbc.URL=jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=true
    log4j.appender.jdbc.user=root
    log4j.appender.jdbc.password=root
    log4j.appender.jdbc.sql=insert into log_icecoldmonitor(level,category,thread,time,location,note) values('%p','%c','%t','%d{yyyy-MM-dd HH:mm:ss:SSS}','%l','%m')
    

    数据库驱动

    <dependency>
       <groupId>mysql</groupId>
       <artifactId>mysql-connector-java</artifactId>
    </dependency>
    

    创建表结构

    CREATE TABLE `log_icecoldmonitor` (
      `Id` int(11) NOT NULL AUTO_INCREMENT,
      `level` varchar(255) NOT NULL DEFAULT '' COMMENT '优先级',
      `category` varchar(255) NOT NULL DEFAULT '' COMMENT '类目',
      `thread` varchar(255) NOT NULL DEFAULT '' COMMENT '进程',
      `time` varchar(30) NOT NULL DEFAULT '' COMMENT '时间',
      `location` varchar(255) NOT NULL DEFAULT '' COMMENT '位置',
      `note` text COMMENT '日志信息',
      PRIMARY KEY (`Id`)
    )
    

    这样就可以保存到日志到数据库了,可能会出现如下异常信息:Java连接Mysql数据库警告::Establishing SSL connection原因是MySQL在高版本需要指明是否进行SSL连接。解决方案如下:在mysql连接字符串url中加入ssl=true或者false即可,如下所示。

    url=jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=true
    
    展开全文
  • 日志系统 Log4j 的使用

    2021-08-18 22:16:07
    Log4j 是 Apache 的一个开放源代码项目,通过使用 Log4j,我们可以控制日志信息输送的目的地(控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、UNIXSyslog守护进程等);我们也可以控制每一条日志的...

    一、Log4j 简介

    Log4j 是 Apache 的一个开放源代码项目,通过使用 Log4j,我们可以控制日志信息输送的目的地(控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、UNIXSyslog守护进程等);我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码

    Log4j 是 Apache 为 Java 提供的日志管理工具。他与 System.out.println() 的作用相似,用来跟踪、调试、维护程序。

    二、Log4j 原理

    Log4j设计实现为分层结构,每一层都提供了不同的类,实现不同功能的对象执行不同的任务,在实际的使用中可以根据自己的具体需求灵活的进行扩展。不同组件的框架图如下:

    在这里插入图片描述
    如上图所示,log4j 框架中有两种对象:
    (1)核心对象:框架的支撑对象,是框架必不可少的组成部分。

    核心对象包括下面几种类型:
    logger 对象:是最高的层,负责获取不同级别日志信息,将不同的风格转化日志信息,他提供给appender对象发布前的信息。(这里的层是指所处的位置)
    layout 对象:用于提供格式化不同风格的日志信息,在发布日志信息前,使其变得可读,可重用。
    appender 对象:这个对象属于底层的对象,它负责发布信息到不同的目的地,比如数据库,文件,控制台,UNIXsyslog等等。

    (2)支撑对象:这些都是框架可选的对象,用于提供额外重要的工作。

    level 对象:用于定义日志的级别(粒度和优先级),有七种级别:

    off 最高等级,用于关闭所有日志记录。
    fatal 指出每个严重的错误事件将会导致应用程序的退出。
    error 指出虽然发生错误事件,但仍然不影响系统的继续运行。
    warm 表明会出现潜在的错误情形。
    info 一般和在粗粒度级别上,强调应用程序的运行全程。
    debug 一般用于细粒度级别上,对调试应用程序非常有帮助。
    all 最低等级,用于打开所有日志记录。

    过滤器对象用于分析日志信息并决定日志信息是否输出。每个 appender 对象可以有几个过滤器对象协同工作,当日志信息到达特定的 appender 时,所有的过滤器会帮助appender在其发布到目的地之前进行过滤操作

    对象渲染器:提供一段字符用于识别发送日志的不同对象,这个对象也用于layout对象准备常量信息。
    日志管理器:用于管理日志框架,它负责从初始化配置中读取信息,这个配置可能是文件配置,也可能是类的配置

    三、Log4j 使用

    Log4j 的使用主要有两个步骤,首先定义 Log4j 的配置文件,然后在代码中获取 Log4j 日志记录器。
    配置文件主要支持两种文件格式,XML 格式和 Java 键-值格式的配置文件。这里以第一种格式为例。

    1、定义 Log4j 的配置文件

    Log4j.properties 文件是 Log4j 的配置文件,默认情况下放到 src 目录下即会自动查找到。

    (1)配置根 Logger

    log4j.rootLogger = [ level ] , appenderName1, appenderName2, …
    

    ● level 指定日志的级别,高于等于error级别的日志信息都会输出;
    ● appenderName 指定相应级别日志的输出目的地及一些属性;

    (2)配置日志信息输出目的地 Appender

    log4j.appender.appenderName = fully.qualified.name.of.appender.class  
    log4j.appender.appenderName.option1 = value1   …  
    log4j.appender.appenderName.option = valueN   
    

    Log4j 提供的 appender 有以下几种:

    org.apache.log4j.ConsoleAppender(控制台),  
    org.apache.log4j.FileAppender(文件),  
    org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
    org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件),  
    org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方) 
    org.apache.log4j.JDBCAppender(把日志输出到特定的数据库中)
    

    把日志输出到特定的数据库中时要配置的属性有:

    ● bufferSize 设置buffer的大小,默认是1
    ● driver 设置数据库的驱动字符串,比如:com.mysql.jdbc.Driver
    ● layout 设置使用的layout,默认是org.apache.log4j.PatternLayout
    ● password 设置数据库的密码
    ● sql 设置每次日志产生的时候执行的sql语句,可以是insert,update,detele
    ● url 是指数据库的url
    ● user 设置数据库的用户名
    示例:

    log4j.appender.DB=org.apache.log4j.jdbc.JDBCAppender
    log4j.appender.DB.URL=jdbc:mysql://localhost/DBNAME
    log4j.appender.DB.driver=com.mysql.jdbc.Driver
    log4j.appender.DB.user=user_name log4j.appender.DB.password=password
    log4j.appender.DB.sql=INSERT INTO LOGS
    VALUES('%x','%d','%C','%p','%m')
    log4j.appender.DB.layout=org.apache.log4j.PatternLayout     
    

    (3)配置日志信息的格式(布局)

    log4j.appender.appenderName.layout= fully.qualified.name.of.layout.class  
    log4j.appender.appenderName.layout.option1 = value1   …  
    log4j.appender.appenderName.layout.option = valueN   
    

    Log4j 提供的 layout 有以下几种:

    org.apache.log4j.HTMLLayout(以HTML表格形式布局),  
    org.apache.log4j.PatternLayout(可以灵活地指定布局模式),  
    org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),  
    org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息) 
    

    使用org.apache.log4j.PatternLayout布局时需要指定输出的格式,定义为:

    log4j.appender.E.layout.ConversionPattern = value 
    

    ConversionPattern参数的格式含义类似C语言中的printf函数的打印格式格式化日志信息,打印参数如下:

    %m 输出代码中指定的消息 %p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL   
    %r 输出自应用启动到输出该log信息耗费的毫秒数   
    %c 输出所属的类目,通常就是所在类的全名   
    %t 输出产生该日志事件的线程名   
    %n 输出一个回车换行符,Windows平台为“rn”,Unix平台为“n”   
    %d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921   
    %l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.jav
    

    2、Java 类中使用 log4j

    (1)获取日志记录器

    使用Log4j, 第一步就是获取日志记录器, 这个记录器将负责控制日志信息。日志类提供了很多方法处理日志活动,它不允许我们自己实例化一个logger,但是提供给我们两种静态方法,获得logger对象。

    public static Logger getRootLogger();
    public static Logger getLogger(String name);
    public static Logger getLogger(Class clazz) 
    // getLogger( Class class) 其实调用的是getLogger(class.getName())
    

    第一种方法返回应用实例的根 Logger,它没有名字。
    第二种方法通过名字获得日志对象 Logger,一般取日志信息所在类的名字
    第三种方法通过 class 对象获得日志对象 Logger,用来指定打印出日志信息所在类。如:

    static Logger logger = Logger.getLogger (ServerWithLog4j.class)
    

    日志器的名称不只是一个名称而已,日志器的名称说明了日志器之间的父子关系。子日志器会继承父日志器的 Appender 和 Level
    日志器的父子关系是通过日志器的名称来决定的,例如名称为 com.chj 的日志器是 com.chj.logger 的日志器的爸爸。com.chj.logger会继承com.chj的Appender以及Level。

    (2)读取配置文件

    当获得了日志记录器之后,第二步将配置 Log4j 环境,其语法为:

    BasicConfigurator.configure ()  // 自动快速地使用缺省Log4j环境。  
    PropertyConfigurator.configure ( String configFilename)   // 读取使用Java的特性文件编写的配置文件。  
    DOMConfigurator.configure ( String filename )   // 读取XML形式的配置文件。
    

    (3)插入记录信息(格式化日志信息)

    当上两个必要步骤执行完毕,您就可以轻松地使用不同优先级别的语句插入到您想记录日志的任何地方,其语法如下:

    Logger.debug ( Object message ) ;  
    Logger.info ( Object message ) ;  
    Logger.warn ( Object message ) ;  
    Logger.error ( Object message ) ;
    

    四、Web 项目中使用 Log4j

    上面代码描述了 Log4j 的简单应用,其实使用 Log4j 也就是这样简单方便。当然除了上面的配置方法,还有其它,比如做一个 J2EE 应用,在 J2EE 应用使用 Log4j,必须先在启动服务时加载 Log4j 的配置文件进行初始化,可以在 web.xml 中进行。

    web.xml 配置 log4j 的方式:

    新建一个servlet,这个 servlet 在 init 函数中为 log4j 执行配置。一般就是读入配置文件,所以需要在 web.xml 中为这个 servlet 配置,同时设定 load-on-startup为1。 配置文件位置在 web.xml 中配置一个 param 即可,路径一般是相对于 web 的 root 目录。web 容器在启动服务时加载 Log4j 的配置文件然后调用 configure 函数进行初始化(文件在哪里、正确的文件类型)

    web.xml配置如下:

    <!--用来启动 log4jConfigLocation的servlet -->  
    <servlet>  
    	<servlet-name>Log4JInitServlet</servlet-name>  
    	<servlet-class>com.mucfc.Log4JInitServlet</servlet-class>  
    	<init-param>  
    		<param-name>log4j-properties-location</param-name>  
    		<param-value>/WEB-INF/classes/log4j.properties</param-value>  
    	</init-param>  
    	<load-on-startup>1</load-on-startup>  
    </servlet>  
    

    五、Log4j 示例

    1、添加依赖

    <dependency>
    	<groupId>log4j</groupId>
    	<artifactId>log4j</artifactId>
    	<version>1.2.17</version>
    </dependency>
    

    2、配置文件

    <!-- 指定级别为 error,高于等于 error 级别的日志信息都会输出 -->
    log4j.rootLogger = error,stdout,E 
    
    <!-- 配置 stdout,日志输出到控制台 -->
    log4j.appender.stdout = org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.Target = System.out
    <!-- 配置 stdout,日志输出格式采用 PatternLayout 格式 -->
    log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
    
    <!-- 配置 E,以文件形式输出,指定DailyRollingFileAppender根据时间对日志进行切割 -->
    log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
    <!-- 配置输出文件位置 -->
    log4j.appender.E.File =F://logs/error.log 
    log4j.appender.E.Append = true
    log4j.appender.E.Threshold = ERROR 
    <!-- 配置以小时分隔日志文件,即就是一个小时产生一个日志文件 -->
    log4j.appender.T.DatePattern='.'yyyy-MM-dd-HH   
    log4j.appender.E.layout = org.apache.log4j.PatternLayout
    log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
    

    3、Java 类

    package test;
    import org.apache.log4j.Logger;     // 不要导错包
    
    public class Log4j_test {
        static Logger LOG = Logger.getLogger(Log4j_test.class);   // 获取日志记录器
        public static void main(String[] args) {
            LOG.debug("hello");   // 指定日志信息
            LOG.error("hello");
            LOG.fatal("fatal");
            LOG.warn("warn");
        }
    }
    

    因为指定的日志级别是 error,所以只有 error 和 fatal 级别日志会输出,程序输出如下:
    在这里插入图片描述
    因为指定了输出文件,所以可以在 F://logs/ 目录中发现文件 error.log。
    在这里插入图片描述

    六、SpringBoot 集成 Log4j 日志框架

    1、常用日志框架

    ● java.util.logging:是JDK在1.4版本中引入的Java原生日志框架
    ● Log4j:Apache的一个开源项目,可以控制日志信息输送的目的地是控制台、文件、GUI组件等,可以控制每一条日志的输出格式,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。虽然已经停止维护了,但目前绝大部分企业都是用的log4j。
    ● LogBack:是Log4j的一个改良版本 Log4j2:Log4j2已经不仅仅是Log4j的一个升级版本了,它从头到尾都被重写了

    2、日志门面 slf4j

    上述介绍的是一些日志框架的实现,这里我们需要用日志门面来解决系统与日志实现框架的耦合性。SLF4J,即简单日志门面(Simple Logging Facade for Java),它不是一个真正的日志实现,而是一个抽象层( abstraction layer),它允许你在后台使用任意一个日志实现。
    在这里插入图片描述
    (1)解耦合

    前面介绍的几种日志框架都一样,每一种日志框架都有自己单独的API,要使用对应的框架就要使用其对应的API,这就大大的增加应用程序代码对于日志框架的耦合性。

    使用了 slf4j 后,对于应用程序来说,无论底层的日志框架如何变,应用程序不需要修改任意一行代码,就可以直接使用了

    实际上,SLF4J 所提供的核心 API 是一些接口以及一个 LoggerFactory 的工厂类。从某种程度上,SLF4J有点类似JDBC,不过比JDBC更简单,在JDBC中,你需要指定驱动程序,而在使用SLF4J的时候,不需要在代码中或配置文件中指定你打算使用那个具体的日志系统。如同使用 JDBC 基本不用考虑具体数据库一样,SLF4J 提供了统一的记录日志的接口,只要按照其提供的方法记录即可,最终日志的格式、记录级别、输出方式等通过具体日志系统的配置来实现,因此可以在应用中灵活切换日志系统

    (2)SLF4J有以下几点优势:

    ● Log4j 提供 TRACE、DEBUG、INFO、WARN、ERROR 和 FATAL 六种纪录等级,但是 SLF4J 认为 ERROR 与 FATAL 并没有实质上的差别,所以拿掉了 FATAL 等级,只剩下其他五种。

    ● 大部分人在程序里面会去写 logger.error(exception),其实这个时候 Log4j 会去把这个exception tostring。真正的写法应该是logger(message.exception);而 SLF4J 就不会使得程序员犯这个错误。

    ● Log4j 间接的在鼓励程序员使用 string 相加的写法(这种写法是有性能问题的),而 SLF4J 就不会有这个问题,你可以使用 logger.error(“{} is+serviceid”,serviceid);

    ● 使用 SLF4J 可以方便的使用其提供的各种集体的实现的jar。(类似commons-logger)

    ● 从 commons–logger 和 Log4j merge 非常方便,SLF4J 也提供了一个 swing 的 tools 来帮助大家完成这个merge。

    ● SLF4J 只支持 MDC,不支持 NDC。

    ● 提供字串内容替换的功能,会比较有效率,如:

    // 传统的字符串产生方式,如果没有要记录 Debug 等级的信息,就会浪费时间在产生不必要的信息上
    logger.debug("There are now " + count + " user accounts: " + userAccountList);   
    // 为了避免上述问题,我们可以先检查是不是开启了 Debug 信息记录功能,只是程序的编码会比较复杂
    if (logger.isDebugEnabled()) {    
    	logger.debug("There are now " + count + " user accounts: " + userAccountList); 
      }   
    // 如果 Debug 等级没有开启,则不会产生不必要的字符串,同时也能保持程序编码的简洁
    logger.debug("There are now {} user accounts: {}", count, userAccountList); 
    

    3、为什么选用 log4j2

    相比与其他的日志系统,log4j2丢数据的情况少;在多线程环境下,disruptor技术性能高于logback等10倍以上;利用jdk1.5并发的特性,减少了死锁的发生

    在这里插入图片描述
    可以看到在同步日志模式下, Logback的性能是最糟糕的。
    log4j2 的性能无论在同步日志模式还是异步日志模式下都是最佳的。
    在这里插入图片描述

    log4j2 优越的性能其原因在于 log4j2 使用了 LMAX,用一个无锁的线程间通信库代替 logback 和 log4j 的队列,并发性能大大提升

    4、整合日志框架 log4j2

    (1)导入依赖

    springboot 默认使用 logback 日志框架的,所以需要排除 logback,不然会出现 jar 依赖冲突的报错

    <dependency>  
        <groupId>org.springframework.boot</groupId>  
        <artifactId>spring-boot-starter-web</artifactId> 
        <!-- 去掉 springboot 默认日志框架配置 --> 
        <exclusions>  
            <exclusion>  
                <groupId>org.springframework.boot</groupId>  
                <artifactId>spring-boot-starter-logging</artifactId>  
            </exclusion>  
        </exclusions>   
    </dependency> 
    
    <!-- 引入log4j2依赖 -->   
    <dependency> 
        <groupId>org.springframework.boot</groupId>  
        <artifactId>spring-boot-starter-log4j2</artifactId>   
    </dependency>  
    

    (2)配置文件

    1)方式一:springboot 中 log4j2 的配置文件默认名为 log4j2-spring.xml,这样就不用再在application.yml 中进行配置。
    2)方式二:如果自定义了配置文件名称,则需要在 application.yml 或 Java 代码中配置:

    yml 文件:

    logging:   
    	config: xxxx.xml   
    	level:
        	cn.jay.repository: trace 
    

    Java 代码:

    PropertyConfigurator.configure("conf/log4j.properties"); 
    

    PropertyConfigurator.configure() 函数加载指定位置的 log4j 配置文件。如果没有自定,默认会读取包下面的 log4j.properties 配置。

    log4j2 配置文件 xml 模板:

    <?xml version="1.0" encoding="UTF-8"?>
    <!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
    <!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数--> 
    <configuration monitorInterval="5">   
    	<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
    
        <!--变量配置-->  
      <Properties>
        <!-- 格式化输出:%date表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符-->
        <!-- %logger{36} 表示 Logger 名字最长36个字符 -->
        <property name="LOG_PATTERN" value="%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" />
        <!-- 定义日志存储的路径 -->
        <property name="FILE_PATH" value="更换为你的日志路径" />
        <property name="FILE_NAME" value="更换为你的项目名" />   
      </Properties>
    
    
      <appenders>
      
        <console name="Console" target="SYSTEM_OUT">
          <!--输出日志的格式-->
          <PatternLayout pattern="${LOG_PATTERN}"/>
          <!--控制台只输出level及其以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
          <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
        </console>
    
        <!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,适合临时测试用-->
        <File name="Filelog" fileName="${FILE_PATH}/test.log" append="false">
          <PatternLayout pattern="${LOG_PATTERN}"/>
        </File>
    
        <!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
        <RollingFile name="RollingFileInfo" fileName="${FILE_PATH}/info.log"
    filePattern="${FILE_PATH}/${FILE_NAME}-INFO-%d{yyyy-MM-dd}_%i.log.gz">
          <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
          <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
          <PatternLayout pattern="${LOG_PATTERN}"/>
          <Policies>
            <!--interval属性用来指定多久滚动一次,默认是1 hour-->
            <TimeBasedTriggeringPolicy interval="1"/>
            <SizeBasedTriggeringPolicy size="10MB"/>
          </Policies>
          <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
          <DefaultRolloverStrategy max="15"/>
        </RollingFile>
    
        <!-- 这个会打印出所有的warn及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
        <RollingFile name="RollingFileWarn" fileName="${FILE_PATH}/warn.log"
    filePattern="${FILE_PATH}/${FILE_NAME}-WARN-%d{yyyy-MM-dd}_%i.log.gz">
          <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
          <ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
          <PatternLayout pattern="${LOG_PATTERN}"/>
          <Policies>
            <!--interval属性用来指定多久滚动一次,默认是1 hour-->
            <TimeBasedTriggeringPolicy interval="1"/>
            <SizeBasedTriggeringPolicy size="10MB"/>
          </Policies>
          <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
          <DefaultRolloverStrategy max="15"/>
        </RollingFile>
    
        <!-- 这个会打印出所有的error及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
        <RollingFile name="RollingFileError" fileName="${FILE_PATH}/error.log"
    filePattern="${FILE_PATH}/${FILE_NAME}-ERROR-%d{yyyy-MM-dd}_%i.log.gz">
          <!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
          <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
          <PatternLayout pattern="${LOG_PATTERN}"/>
          <Policies>
            <!--interval属性用来指定多久滚动一次,默认是1 hour-->
            <TimeBasedTriggeringPolicy interval="1"/>
            <SizeBasedTriggeringPolicy size="10MB"/>
          </Policies>
          <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件开始覆盖-->
          <DefaultRolloverStrategy max="15"/>
        </RollingFile>
    
      </appenders>
    
      <!--Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。-->  
    <!--然后定义loggers,只有定义了logger并引入的appender,appender才会生效-->   <loggers>
    
        <!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
        <logger name="org.mybatis" level="info" additivity="false">
          <AppenderRef ref="Console"/>
        </logger>
        <!--监控系统信息-->
        <!--若是additivity设为false,则 子Logger 只会在自己的appender里输出,而不会在 父Logger 的appender里输出。-->
        <Logger name="org.springframework" level="info" additivity="false">
          <AppenderRef ref="Console"/>
        </Logger>
    
        <root level="info">
          <appender-ref ref="Console"/>
          <appender-ref ref="Filelog"/>
          <appender-ref ref="RollingFileInfo"/>
          <appender-ref ref="RollingFileWarn"/>
          <appender-ref ref="RollingFileError"/>
        </root>   </loggers>
    
    </configuration> 
    

    log4j2 配置参数介绍:
    (1)根节点 Configuration 有两个属性 status 和 monitorinterval。

    ● status 用来指定 log4j 本身的打印日志的级别;

    ● monitorinterval 用于指定 log4j 自动重新配置的监测间隔时间,单位是s,最小是5s。

    (2)根节点 Configuration 有两个子节点:Appenders 和 Loggers(表明可以定义多个Appender和Logger)。

    ● Appenders 节点常见的有三种子节点 Console、RollingFile、File。

    1)Console 节点用来定义输出到控制台的Appender

    name 指定Appender的名字;
    target 为 SYSTEM_OUT 或 SYSTEM_ERR,一般只设置默认SYSTEM_OUT。
    PatternLayout 指定输出格式,不设置默认为 %m%n。

    2)File 节点用来定义输出到指定位置的文件的Appender

    name:指定Appender的名字;
    fileName:指定输出日志的目的文件带全路径的文件名;
    PatternLayout:输出格式,不设置默认为:%m%n。

    3)RollingFile 节点用来定义超过指定条件自动删除旧的创建新的Appender

    name 指定 Appender 的名字;
    fileName 指定输出日志的目的文件带全路径的文件名;
    PatternLayout 指定输出格式,不设置默认为:%m%n;
    filePattern 指定当发生Rolling时,文件的转移和重命名规则;
    Policies 指定滚动日志的策略,就是什么时候进行新建日志文件输出日志;
    TimeBasedTriggeringPolicy 是 Policies 子节点,基于时间的滚动策略,interval属性用来指定多久滚动一次,默认是1 hour;modulate=true 用来调整时间,比如现在是早上3am,interval是4,那么第一次滚动是在4am,接着是8am,12am…而不是7am;
    SizeBasedTriggeringPolicy 是 Policies 子节点,基于指定文件大小的滚动策略,size属性用来定义每个日志文件的大小;
    DefaultRolloverStrategy 用来指定同一个文件夹下最多有几个日志文件时开始删除最旧的,创建新的(通过max属性)。

    ● Loggers节点,常见的有两种 Root和Logger。

    1)Root 节点用来指定项目的根日志,如果没有单独指定 Logger,那么就会默认使用该Root日志输出。

    level 指定日志输出级别;
    AppenderRef 为 Root 的子节点,用来指定该日志输出到哪个Appender。

    2)Logger 节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等

    level 指定日志输出级别;
    name 指定该 Logger 所适用的类或者类所在的包全路径,继承自Root节点;
    AppenderRef 是 Logger的子节点,用来指定该日志输出到哪个 Appender,如果没有指定,就会默认继承自Root,如果指定了,那么会在指定的这个 Appender 和 Root 的 Appender 中都会输出,此时我们可以设置 Logger 的 additivity=“false” 只在自定义的 Appender 中进行输出。

    (3)Controller 中使用 log4j2

    1)方式一:非 Slf4j 门面模式

    import org.apache.log4j.Logger;
    
    @RestController //声明Rest风格的控制器
    @RequestMapping("/logging")
    public class LogController {
        Logger logger=Logger.getLogger(LogController.class);
    
        @RequestMapping("logtest")
        @ResponseBody
        public String logtest(){
            logger.fatal("致命错误");
    	logger.error("严重警告");
    	logger.warn("警告");
    	logger.info("普通信息");
    	logger.debug("调试信息");
    	return "";
        }
    }
    

    2)方式二:@Slf4j 门面模式

    ● Java 代码

     import org.apache.log4j.PropertyConfigurator; 
     import org.slf4j.Logger; 
     import org.slf4j.LoggerFactory;
    
    @RestController //声明Rest风格的控制器 
    @RequestMapping("/logging") 
    public class LogController {
        
        try {
        		PropertyConfigurator.configure("conf/log4j.properties");
        		// 使用指定类初始化日志对象,在日志输出的时候,可以打印出日志信息所在类
        		Logger logger = LoggerFactory.getLogger(LogController.class);
        		logger.info("test");
        	} catch (Exception ex) {
        		System.out.println( ex.getMessage());
        	} 	
        } 
    

    ● @Slf4j 注解

    lombok 中的 @Slf4j 注解可以很方便的使用 org.slf4j.Logger 对象。日常开发尽量使用 Slf4j 门面来处理日志,尽量避免使用具体的日志框架。

    @Slf4j 
    @RestController 
    @RequestMapping("/logging") 
    public class LogController {    
    	
    	@GetMapping("/do")  
    	public String log() {
        	log.info("log4j2 test date: {} info: {}", LocalDate.now(), "日志框架学习");    
        	return "log4j2";  
        }    
      } 
    
    展开全文
  • Log4j的异步日志

    2021-03-01 08:08:38
    先引用一些网络上的异步日志介绍log4j日志异步化大幅提升系统性能 - 穿林度水 - 博客园​www.cnblogs.comorg.apache.log4j.AsyncAppender就是实现异步日志输入的Appender我们知道,一个日志输出行为,牵涉到logger,...

    先引用一些网络上的异步日志介绍log4j日志异步化大幅提升系统性能 - 穿林度水 - 博客园​www.cnblogs.com

    org.apache.log4j.AsyncAppender就是实现异步日志输入的Appender

    我们知道,一个日志输出行为,牵涉到logger,appender,logevent,其中一个系统可能包含多个logger,当指定一个logger时,这个logger也可能包含多个appender,一个日志内容被封装成一个logevent来传递;

    org.apache.log4j.Category类是logger类的父类

    public

    void error(Object message, Throwable t) {

    if(repository.isDisabled(Level.ERROR_INT))

    return;

    if(Level.ERROR.isGreaterOrEqual(this.getEffectiveLevel()))

    forcedLog(FQCN, Level.ERROR, message, t);

    }

    最终都会调用的每个Appender的append方法;

    异步输出日志工作原理

    AsyncAppender采用的是生产者消费者的模型进行异步地将Logging Event送到对应的Appender中。

    a、 生产者:外部应用了Log4j的系统的实时线程,实时将Logging Event传送进AsyncAppender里

    b、 中转:Buffer和DiscardSummary

    c、 消费者:Dispatcher线程和appenders

    工作原理:

    1) Logging Event进入AsyncAppender,AsyncAppender会调用append方法,在append方法中会去把logging Event填入Buffer中,当消费能力不如生产能力时,AsyncAppender会把超出Buffer容量的Logging Event放到DiscardSummary中,作为消费速度一旦跟不上生成速度,中转buffer的溢出处理的一种方案。

    2) AsyncAppender有个线程类Dispatcher,它是一个简单的线程类,实现了Runnable接口。它是AsyncAppender的后台线程。

    Dispatcher所要做的工作是:

    ① 锁定Buffer,让其他要对Buffer进行操作的线程阻塞。

    ② 看Buffer的容量是否满了,如果满了就将Buffer中的Logging Event全部取出,并清空Buffer和DiscardSummary;如果没满则等待Buffer填满Logging Event,然后notify Disaptcher线程。

    ③ 将取出的所有Logging Event交给对应appender进行后面的日志信息推送。

    以上是AsyncAppender类的两个关键点:append方法和Dispatcher类,通过这两个关键点实现了异步推送日志信息的功能,这样如果大量的Logging Event进入AsyncAppender,就可以游刃有余地处理这些日志信息了。

    我们来看下org.apache.log4j.AsyncAppender的成员变量

    public class AsyncAppender extends AppenderSkeleton

    implements AppenderAttachable {

    /*** The default buffer size is set to 128 events.*/

    public static final int DEFAULT_BUFFER_SIZE = 128;

    /*** Event buffer, also used as monitor to protect itself and* discardMap from simulatenous modifications.*/

    private final List buffer = new ArrayList();

    /*** Map of DiscardSummary objects keyed by logger name.*/

    private final Map discardMap = new HashMap();

    /*** Buffer size.*/

    private int bufferSize = DEFAULT_BUFFER_SIZE;

    /** Nested appenders. */

    AppenderAttachableImpl aai;

    /*** Nested appenders.*/

    private final AppenderAttachableImpl appenders;

    /*** Dispatcher.*/

    private final Thread dispatcher;

    /*** Should location info be included in dispatched messages.*/

    private boolean locationInfo = false;

    /*** Does appender block when buffer is full.*/

    private boolean blocking = true;

    /*** Create new instance.*/

    这个blocking变量默认为true,一般情况下我们不允许丢失日志,不过这样会导致当buff满的时候,写日志的线程将会blocking,具体可以参看下面的

    org.apache.log4j.AsyncAppender的append调用方法

    org.apache.log4j.Dispatcher.java

    package org.apache.log4j;

    import org.apache.log4j.helpers.AppenderAttachableImpl;

    import org.apache.log4j.spi.LoggingEvent;

    /*** Obsolete AsyncAppender dispatcher provided for compatibility only.** @deprecated Since 1.3.*/

    class Dispatcher extends Thread {

    /*** @deprecated*/

    private org.apache.log4j.helpers.BoundedFIFO bf;

    private AppenderAttachableImpl aai;

    private boolean interrupted = false;

    AsyncAppender container;

    /**** @param bf* @param container* @deprecated*/

    Dispatcher(org.apache.log4j.helpers.BoundedFIFO bf, AsyncAppender container) {

    this.bf = bf;

    this.container = container;

    this.aai = container.aai;

    // It is the user's responsibility to close appenders before // exiting. this.setDaemon(true);

    // set the dispatcher priority to lowest possible value this.setPriority(Thread.MIN_PRIORITY);

    this.setName("Dispatcher-" + getName());

    // set the dispatcher priority to MIN_PRIORITY plus or minus 2 // depending on the direction of MIN to MAX_PRIORITY. //+ (Thread.MAX_PRIORITY > Thread.MIN_PRIORITY ? 1 : -1)*2); }

    void close() {

    synchronized (bf) {

    interrupted = true;

    // We have a waiting dispacther if and only if bf.length is // zero. In that case, we need to give it a death kiss. if (bf.length() == 0) {

    bf.notify();

    }

    }

    }

    /*** The dispatching strategy is to wait until there are events in the buffer* to process. After having processed an event, we release the monitor* (variable bf) so that new events can be placed in the buffer, instead of* keeping the monitor and processing the remaining events in the buffer.**

    * Other approaches might yield better results.*

    */

    public void run() {

    //Category cat = Category.getInstance(Dispatcher.class.getName()); LoggingEvent event;

    while (true) {

    synchronized (bf) {

    if (bf.length() == 0) {

    // Exit loop if interrupted but only if the the buffer is empty. if (interrupted) {

    //cat.info("Exiting."); break;

    }

    try {

    //LogLog.debug("Waiting for new event to dispatch."); bf.wait();

    } catch (InterruptedException e) {

    break;

    }

    }

    event = bf.get();

    if (bf.wasFull()) {

    //LogLog.debug("Notifying AsyncAppender about freed space."); bf.notify();

    }

    }

    // synchronized synchronized (container.aai) {

    if ((aai != null) && (event != null)) {

    aai.appendLoopOnAppenders(event);

    }

    }

    }

    // while // close and remove all appenders aai.removeAllAppenders();

    }

    }

    我们来看下最终org.apache.log4j.AsyncAppender的append调用方法:

    /*** {@inheritDoc}*/

    public void append(final LoggingEvent event) {

    // // if dispatcher thread has died then // append subsequent events synchronously // See bug 23021 if ((dispatcher == null) || !dispatcher.isAlive() || (bufferSize <= 0)) {

    synchronized (appenders) {

    appenders.appendLoopOnAppenders(event);

    }

    return;

    }

    // Set the NDC and thread name for the calling thread as these // LoggingEvent fields were not set at event creation time. event.getNDC();

    event.getThreadName();

    // Get a copy of this thread's MDC. event.getMDCCopy();

    if (locationInfo) {

    event.getLocationInformation();

    }

    synchronized (buffer) {

    while (true) {

    int previousSize = buffer.size();

    if (previousSize < bufferSize) {

    buffer.add(event);

    // // if buffer had been empty // signal all threads waiting on buffer // to check their conditions. // if (previousSize == 0) {

    buffer.notifyAll();

    }

    break;

    }

    // // Following code is only reachable if buffer is full // // // if blocking and thread is not already interrupted // and not the dispatcher then // wait for a buffer notification boolean discard = true;

    if (blocking

    && !Thread.interrupted()

    && Thread.currentThread() != dispatcher) {

    try {

    buffer.wait();

    discard = false;

    } catch (InterruptedException e) {

    // // reset interrupt status so // calling code can see interrupt on // their next wait or sleep. Thread.currentThread().interrupt();

    }

    }

    // // if blocking is false or thread has been interrupted // add event to discard map. // if (discard) {

    String loggerName = event.getLoggerName();

    DiscardSummary summary = (DiscardSummary) discardMap.get(loggerName);

    if (summary == null) {

    summary = new DiscardSummary(event);

    discardMap.put(loggerName, summary);

    } else {

    summary.add(event);

    }

    break;

    }

    }

    }

    }

    展开全文
  • 一、log4j简介 Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以把日志信息输送控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等目的地;此外,我们还可以控制每一条...

    一、log4j简介

    Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以把日志信息输送控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等目的地;此外,我们还可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。

    Log4j主要由三个部分构成:日志信息的优先级,日志信息的输出目的地,和日志信息的输出格式。日志信息的优先级从高到低有ERROR、WARN、 INFO、DEBUG,分别用来指定这条日志信息的重要程度;日志信息的输出目的地指定了日志将打印到控制台还是文件中;而输出格式则控制了日志信息的显示内容。

    Log4j有两种系列的版本,一种是1.x系列的版本,可名为Log4j1,目前的最新版本是1.2.17,已停止更新(2012年5月)。另一种是2.x系列的版本,可名为Log4j2,目前的最新版本是2.14.1(2021年3月),还在不断的更新,Log4j2应该会逐渐取代Log4j1。其次,1.x版本的配置文件的后缀名可为".xml"和".properties",而2.x版本不再支持1.x中的以.properties为后缀的文件配置方式,其配置文件后缀名只能为".xml",".json"或者".jsn"。

    二、入门级示例

    在程序中使用Log4j之前,需要下载Log4j,1.x系列的Log4j的下载地址为:http://logging.apache.org/log4j/1.2/index.html
    ,下载完毕后,解压之,应该会发现很多文件,我们只取其中的log4j-1.2.17.jar包,并将其导入到项目的classpath中,然后再将log4j.properties配置文件放于src根目录中(配置文件的位置是可以随意的,只要在初始化Log4j配置时,其路径设置正确即可)。如此,就可以在程序中使用Log4j了。

    1.新建一个Java项目,其名Log4jTest,导入1.x系列的Log4j库jar包:log4j-1.2.17.jar,整个项目的最终目录如下:
    在这里插入图片描述

    2.在src的根目录中创建并设置log4j配置文件

    ### 设置根记录器 ###
    log4j.rootLogger = debug,A,B,C
     
    ### 输出日志信息到控制台 ###
    log4j.appender.A = org.apache.log4j.ConsoleAppender
    log4j.appender.A.Target = System.out
    log4j.appender.A.layout = org.apache.log4j.PatternLayout
    log4j.appender.A.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
     
    ### 输出DEBUG级别以上的日志到=D:\\logs\\log.log,分隔符为\\或//都可 ###
    log4j.appender.B = org.apache.log4j.DailyRollingFileAppender
    log4j.appender.B.File = D://logs//log.log
    log4j.appender.B.Append = true  
    log4j.appender.B.Threshold = DEBUG 
    log4j.appender.B.layout = org.apache.log4j.PatternLayout
    log4j.appender.B.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
    
    ### 输出ERROR级别以上的日志到=D:\\logs\\error.log,分隔符为\\或//都可 ###
    log4j.appender.C = org.apache.log4j.DailyRollingFileAppender
    log4j.appender.C.File = D://logs//error.log
    log4j.appender.C.Append = true
    log4j.appender.C.Threshold = ERROR 
    log4j.appender.C.layout = org.apache.log4j.PatternLayout
    log4j.appender.C.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
    

    3.在主程序中设置日志信息

    package log4jtest;
    
    import java.io.File;
    import org.apache.log4j.Logger;
    import org.apache.log4j.PropertyConfigurator;
    
    /**
     * @author ym
     */
    public class Log4jTest {
    
        /**
         * @param args
         */
        public static void main(String[] args){
            // 加载配置文件进行初始化
            String path=System.getProperty("user.dir")+File.separator+"src"
                    +File.separator+"log4j.properties";
            PropertyConfigurator.configure(path);
            // 获得记录器
            Logger logger = Logger.getLogger(Log4jTest.class);
            // 输出各种级别的日志信息
            // 记录debug级别的信息  
            logger.debug("This is debug message.");
            // 记录info级别的信息  
            logger.info("This is info message.");
            // 记录error级别的信息  
            logger.error("This is error message.");
        }
    }
    

    4.输出结果
    (1)首先是输出到控制的日志信息
    在这里插入图片描述
    (2)再就是输出到文件中的日志信息
    在这里插入图片描述

    在这里插入图片描述
    5.注意事项
    在主程序中,我们是通过如下的代码手动初始化配置的:

    // 加载配置文件进行初始化
    String path=System.getProperty("user.dir")+File.separator+"src"
            +File.separator+"log4j.properties";
    PropertyConfigurator.configure(path);
    

    这是一种初始化配置的方式,但如果每次使用记录器输出日志信息,都需要手动设置properties文件的路径,那未免有些麻烦。那有没有自动初始化配置的方法呢?答案是:有的。但不管是上述的方法,还是接下来要介绍的方法,都需要告诉程序你的properties配置文件在哪里?只是上述的方法除了要告诉路径外,还要手动初始化配置而已。

    如果要告诉程序你的properties配置文件在哪里?可把配置文件所在的文件夹路径添加到classpath中,如例子中的配置文件是在src文件夹中,那么只要把src的路径添加到classpath中即可,如下,往classpath添加了src路径:
    在这里插入图片描述
    如此,就可以使用如下的程序输出日志信息了,显然,相比于手动初始化配置,这种方式无疑要简洁一些。

    package log4jtest;
    
    import org.apache.log4j.Logger;
    
    /**
     * @author ym
     */
    public class Log4jTest {
    
        /**
         * @param args
         */
        public static void main(String[] args){
            // 获得记录器
            Logger logger = Logger.getLogger(Log4jTest.class);
            // 输出各种级别的日志信息
            // 记录debug级别的信息  
            logger.debug("This is debug message.");
            // 记录info级别的信息  
            logger.info("This is info message.");
            // 记录error级别的信息  
            logger.error("This is error message.");
        }
    }
    

    三、配置文件

    1.x系列的Log4j支持两种配置文件格式,一种是XML格式的文件(.xml),另一种是properties格式的文件(.properties)。下面我们介绍的是properties格式的配置文件:
    配置文件示例:

    ### 设置根记录器 ###
    log4j.rootLogger = debug,A,B,C
     
    ### 输出日志信息到控制台 ###
    log4j.appender.A = org.apache.log4j.ConsoleAppender
    log4j.appender.A.Target = System.out
    log4j.appender.A.layout = org.apache.log4j.PatternLayout
    log4j.appender.A.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
     
    ### 输出DEBUG级别以上的日志到=D:\\logs\\log.log,分隔符为\\或//都可 ###
    log4j.appender.B = org.apache.log4j.DailyRollingFileAppender
    log4j.appender.B.File = D://logs//log.log
    log4j.appender.B.Append = true  
    log4j.appender.B.Threshold = DEBUG 
    log4j.appender.B.layout = org.apache.log4j.PatternLayout
    log4j.appender.B.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
    
    ### 输出ERROR级别以上的日志到=D:\\logs\\error.log,分隔符为\\或//都可 ###
    log4j.appender.C = org.apache.log4j.DailyRollingFileAppender
    log4j.appender.C.File = D://logs//error.log
    log4j.appender.C.Append = true
    log4j.appender.C.Threshold = ERROR 
    log4j.appender.C.layout = org.apache.log4j.PatternLayout
    log4j.appender.C.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
    

    (1)配置根记录器Logger,其语法为:

    log4j.rootLogger = [ level ] , appenderName1, appenderName2, …
    

    其中,level 是日志记录的优先级,分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定义的级别。Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过定义此处的级别,可以控制到应用程序中相应级别的日志信息的开关。比如在这里定义了DEBUG级别,则应用程序中所有级别的日志信息都将被打印出来,而如果在这里定义了INFO级别,则应用程序中的DEBUG级别的日志信息将不被打印出来,因为DEBUG的优先级低于INFO的优先级。为了可以打印所有级别的日志信息,此处一般把级别设置为DEBUG。appenderName是追加器的名称,用于指定日志信息所输出的地方。追加器可以有多个,即可以同时指定多个输出目的地。

    (2)配置日志信息的输出目的地Appender,其语法为:

    log4j.appender.appenderName = 全限定类名
    log4j.appender.appenderName.option1 = value1
    …
    log4j.appender.appenderName.optionN = valueN
    

    其中,Log4j提供的appender有以下几种:
    org.apache.log4j.ConsoleAppender(控制台),
    org.apache.log4j.FileAppender(文件),
    org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
    org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件),
    org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
    (3)各种追加器的选项设置

    • ConsoleAppender选项
      Threshold=WARN:指定日志消息的输出最低层次。
      ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。
      Target=System.err:默认情况下是:System.out,指定输出控制台
    • FileAppender 选项
      Threshold=WARN:指定日志消息的输出最低层次。
      ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。
      File=mylog.txt:指定消息输出到mylog.txt文件。
      Append=false:默认值是true,即将消息追加到指定文件中,false指将消息覆盖指定的文件内容。
    • DailyRollingFileAppender 选项
      Threshold=WARN:指定日志消息的输出最低层次。
      ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。
      File=mylog.txt:指定消息输出到mylog.txt文件。
      Append=false:默认值是true,即将消息追加到指定文件中,false指将消息覆盖指定的文件内容。
      DatePattern=’.'yyyy-ww:每周滚动一次文件,即每周产生一个新的文件。当然也可以指定按月、周、天、时和分。即对应的格式如下:
    ’.'yyyy-MM: 每月
    ’.'yyyy-ww: 每周
    ’.'yyyy-MM-dd: 每天
    ’.'yyyy-MM-dd-a: 每天两次
    ’.'yyyy-MM-dd-HH: 每小时
    ’.'yyyy-MM-dd-HH-mm: 每分钟
    
    • RollingFileAppender 选项
      Threshold=WARN:指定日志消息的输出最低层次。
      ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。
      File=mylog.txt:指定消息输出到mylog.txt文件。
      Append=false:默认值是true,即将消息追加到指定文件中,false指将消息覆盖指定的文件内容。
      MaxFileSize=100KB:后缀可以是KB, MB 或者是 GB. 在日志文件到达该大小时,将会自动滚动,即将原来的内容移到mylog.log.1文件。
      MaxBackupIndex=2:指定可以产生的滚动文件的最大数。
      (4)配置日志信息的布局,其语法为:
    log4j.appender.appenderName.layout = 全限定类名
    log4j.appender.appenderName.layout.option1 = value1
    …
    log4j.appender.appenderName.layout.optionN = valueN
    

    其中,Log4j提供的layout有以下几种:
    org.apache.log4j.HTMLLayout(以HTML表格形式布局),
    org.apache.log4j.PatternLayout(可以灵活地指定布局模式,推荐使用这种),
    org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
    org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)

    (4)日志输出格式的设置
    在配置文件中可以通过log4j.appender.appenderName.layout.ConversionPattern设置日志的输出格式。
    各种通配符如下:

    %p: priority,输出日志信息的优先级,即ALL,DEBUG,INFO,WARN,ERROR,FATAL, OFF
    %d: date,输出日志记录的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyyy MM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921
    %r: 输出自应用启动到输出该log信息耗费的毫秒数
    %c: class,输出日志信息所属的类目(类信息从创建logger时传入的Class对象className.class中获得),通常就是所在类的全限定类名,如果加上{<层数>}表示列出从最内层算起的指定层数的名字空间。
    %C: 列出调用logger的类的全限定名称(包含包路径),假设当前类是"org.apache.xyz.SomeClass",%C表示org.apache.xyz.SomeClass,%C{1}表示SomeClass。
    %t: thread,输出产生该日志事件的线程名,主程序中的线程名默认是main
    %l: location,输出日志事件的发生位置,相当于%c.%t(%f:%L)的组合,包括类目、发生的线程,以及在代码中的行数。举例:log4jtest.Log4jTest.main(Log4jTest.java:24)
    %x: 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中
    %%: 输出一个”%”字符
    %F: file name,输出日志消息产生时所在的源文件名称
    %L: line number,输出调用logger的代码行的行号
    %m: message,输出代码中的指定消息,即日志的具体信息
    %M: 输出调用logger的方法名
    %n: 输出一个回车换行符,Windows平台为”/r/n”,Unix平台为”/n”输出日志信息换行
    

    可以在%与通配字符之间加上修饰符来控制其最小宽度、最大宽度、和文本的对齐方式。如:

    %20c   :指定输出category的名称,最小的宽度是20,如果category的名称小于20的话,默认的情况下右对齐。
    %-20c  :指定输出category的名称,最小的宽度是20,如果category的名称小于20的话,”-”号指定左对齐。
    %.30c  :指定输出category的名称,最大的宽度是30,如果category的名称大于30的话,就会将左边多出的字符截掉,但小于30的话也不会有空格。
    %20.30c:如果category的名称小于20就补空格,并且右对齐,如果其名称长于30字符,就从左边交远销出的字符截掉。 
    

    在这里插入图片描述

    log4j.logger 用法如下

        # 1)log4j.logger.包名 = 日志级别 , appenderName1,appenderName2,....
        # 定义该包名下的所有类的日志输出
        # 2)log4j.logger.类全名含包名 = 日志级别 ,appenderName1,appenderName2,....
        # 定义指定类的日志输出
        # 3) log4j.logger.日志对象Logger命名名称 = 日志级别 , appenderName1,appenderName2,....
        # 定义了某命名名称的日志的 输出,如: 
        # log4j.logger.Log1 就是指定义通过 Logger.getLogger("Log1") 获取的日志对象的日志输出
         
        #以log4j.logger.包名为例子
        log4j.logger.edu.service.impl = error,service_stdout,service_logfile
        log4j.appender.service_stdout=org.apache.log4j.ConsoleAppender 
        log4j.appender.service_stdout.layout=org.apache.log4j.PatternLayout
        log4j.appender.service_stdout.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH:mm:ss}][%C{1}:%L] - %m%n
        log4j.appender.service_logfile = org.apache.log4j.DailyRollingFileAppender
        log4j.appender.service_logfile.file=d:\\log\\service.log
        log4j.appender.service_logfile.DatePattern= '.'yyyy-MM-dd
        log4j.appender.service_logfile.layout=org.apache.log4j.PatternLayout
        log4j.appender.service_logfile.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH:mm:ss}][%C{1}:%L] - %m%n
        log4j.appender.service_logfile.Encoding=UTF-8
        ```
    
    展开全文
  • 文章目录1. 什么是slf4j?2. log4j简介和配置2.1 log4j介绍2.2 log4j三大组件2.3 log4j pom依赖引入2.4 配置log4j3.... log4j2简介和配置5.1 log4j2简介5.2 log4j2常见组件5.3 log4j2配置文件5.4 log4j2异步日志
  • 123456789101112131415161718192021222324# Set root logger level to WARN and append to stdoutlog4j.rootLogger=INFO,stdout,R,R1#日志文件输出目标,控制台/文件#日志输出方式:控制台log4j.appender.stdout=org....
  • 1 日志路径带来的痛点Java 项目中少不了要和log4j日志框架打交道, 开发环境和生产环境下日志文件的输出路径总是不一致, 设置为绝对路径的方式缺少了灵活性, 每次变更项目路径都要修改文件, 目前想到的最佳实现方式...
  • 在之前的一篇文章中(一次鞭辟入里的 Log4j2 异步日志输出阻塞问题的定位),我们详细分析了一个经典的 Log4j2 异步日志阻塞问题的定位,主要原因还是日志文件写入慢了。并且比较深入的分析了 Log4j2 异步日志的原理,...
  • 在强调可重用组件开发的今天,除了自己从头到尾开发一个可重用的日志操作类外,Apache为我们提供了一个强有力的日志操作包-Log4j。官方站点:http://logging.apache.org/log4j/Log4j是Apache的一个开放源代码项目,...
  • 一、关于Log4j日志Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条...
  • Log4j现在已经被大家熟知了,所有细节都可以在网上查到,Log4j支持Appender,其中DailyRollingFileAppender是被经常用到的Appender之一。在讨论今天的主题之前,我们先看下另外一个Appender。 最常用的Appender——...
  • 如何将log4j.properties配置为每次运行应用程序时只有一个日志文件.我已经读过你应该在文件名中使用时间戳,但随着时间的推移,每次运行会创建许多文件.我尝试过DailyRollingFileAppender和RollingFileAppender但是找...
  • 日志论在应用程序中输出日志有有三个目的:(1)监视代码中变量的变化情况,把数据周期性地记录到文件中供其他应用进行统计分析工作。(2)跟踪代码运行进轨迹,作为日后审计的依据。(3)担当集成开发环境中的调试器,向...
  • 根据官方的测试表明,在线程环境下,Log4j2的异步日志表现更加优秀。在异步日志中,Log4j2使用独立的线程去执行I/O操作,可以极大地提升应用程序的性能。在官方的测试中,下图比较了Sync、Async Appenders和...
  • Apache Log4j 2.2发布,Java日志组件发布时间:2015-02-28 09:16:02来源:红联作者:empastApache Log4j 2.2 发布,此版本是第五个 GA 版本,包括一些 bug 修复和新特性。新特性:o LOG4J2-941: Allow JSON layout to ...
  • 相比log4j的话,log4j可以控制日志信息的输送目的地、输出格式以及级别等等,使我们能够更加细致地控制日志的生成过程。Log4j2是对Log4j1的升级,在性能和功能上有显著的改进,包括线程中吞吐量的增强、占位符的...
  • spring boot内部使用Commons Logging来记录日志,但也保留外部接口可以让一些日志框架来进行实现,例如Java Util Logging,Log4J2还有Logback。如果你想用某一种日志框架来进行实现的话,就必须先配置,默认情况下,...
  • 怎么统一到一台服务器上,说实话没有特别好的思路,最后尝试了log4j的SocketAppender。查了不少网络资源,都说的有些不明了,还是得亲自尝试之后才见分晓。1、客户端的配置:客户端的配置比较简单,只需要告诉...
  • http://www.apache.org/dist/jakarta/log4j/jakarta-log4j-1.2.8.zip1.2. Log4j简介在强调可重用组件开发的今天,除了自己从头到尾开发一个可重用的日志操作类外,Apache为我们提供了一个强有力的日志操作包-Log4j。...
  • 背景在应用程序中添加日志记录总的来说基于三个目的:监视代码中变量的变化情况,周期性的记录到文件中供其他应用进行统计分析工作;跟踪代码运行时轨迹,作为日后审计的依据;担当集成开发环境中的调试器的作用,...
  • log4j详解

    2021-02-26 16:36:31
    日志论在应用程序中输出日志有有三个目的:(1)监视代码中变量的变化情况,把数据周期性地记录到文件中供其他应用进行统计分析工作。(2)跟踪代码运行进轨迹,作为日后审计的依据。(3)担当集成开发环境中的调试器,向...
  • 资料:============================================================================================================================================================================================log4j....
  • 日志记录工具log4jLog4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIXSyslog守护进程等;我们也可以控制每一条日志...
  • Log4j日志框架使用

    2021-02-04 18:16:35
    Log4j日志框架使用 Log4j的配置文件 想要使用Log4j,需要在项目目录下创建一个lib文件夹,在文件夹中导入Log4j的jar包 然后,在src目录下创建log4j.properties配置文件,需要将配置文件进行配置然后才能正常使用,...
  • Log4j在java中的使用

    2021-03-10 03:42:33
    通过使用Log4J,可以指定日志信息输出的目的地,控制每一条日志的输出格式,定义日志信息的级别。所有这些功能通过一个配置文件灵活进行配置。一、LOG4J组成LOG4J主要由三大组件组成:. Logger: 决定什么日志信息应该...
  • Java日志记录log4j最简明教程2011-09-21 16:40:29 我来说两句收藏 我要投稿最近在搞一个项目架设,希望从构建一个项目方方面面都彻底研究透,增长实战经验。今天先研究一下日志的构建,这里选择了log4j--java方面...
  • (这是在SLES11,Java 7,Tomcat 6,log4j-1.2.16)我们使用log4j将不同的东西写入不同的日志文件.我继承了这段代码,所以无论好坏,一般结构都会暂时停留.记录器将创建两个日志文件:main.log和stats.log.通过单独的调用将...
  • 项目在ERROR时,都会打印ERROR日志,所以可以在log4j接收到ERROR日志请求时,发送通知消息。实践Filter是log4j2的扩展点,从图中(图片来自如何编写Log4j2脱敏插件)流程可以看到,Filter分别可以在全局、Logger、...
  • Java log4j详细教程

    千次阅读 2021-02-12 12:28:08
    一:Log4j入门简介学习Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以...
  • 一、简介Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 54,556
精华内容 21,822
关键字:

多进程log4j日志