Log4j日志框架

Log4j日志框架

1、Log4j 简单入门

1、简单介绍

Log4j 官方网站: http://logging.apache.org/log4j/1.2/、Maven仓库:https://search.maven.org/search?q=g:log4j

  1. Log4j =》Log for java,从时间上讲,Log4j 的产生时间要比JUL早
  2. Log4j 很重要的一个缺陷是不支持占位符,但是用户可自己定义实现占位符的功能
  3. 从官网或者Maven仓库可以发现 Log4j 最后的版本是1.2.17

Log4j是Apache下的一款开源日志框架,通过使用Log4j,可以控制日志信息输出到控制台、文件、甚至是数据库中。我们可以控制每条日志的输出格式,通过定义日志的输出级别,可以更灵活的控制日志的输出过程,方便项目调试。这些设置可以通过一个配置文件来灵活的进行配置,而不需要修改应用的代码。

2、入门案例

1、建立maven工程并添加依赖

<!--https://search.maven.org/search?q=g:log4j-->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
</dependency>

2、默认直接获取Logger对象打印日志,可以发现没有打印我们想要的内容 (是由于我们什么都没有配置,并且Log4j也没有默认配置)

import org.apache.log4j.Logger;
public class Log4jTest {
    public static void main(String[] args) {
        /**
         * Log4j获取日志记录器对象的两个方法:
         *   public static Logger getLogger(String name);
         *   public static Logger getLogger(Class clazz);
         */
        Logger logger = Logger.getLogger(Log4jTest.class);
        logger.info("hello log4j");
    }
}

// 输出内容
log4j:WARN No appenders could be found for logger (Log4jTest).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

注意:如果既没有Java硬编码配置,又没有使用配置文件配置日志输出。默认是没有任何配置,不会输出任何内容

3、使用Log4j提供的初始化默认配置方式

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;

public class Log4jTest {
    public static void main(String[] args) {
        // 初始化配置信息,在入门案例中暂不使用配置文件
        BasicConfigurator.configure();
        /**
         * Log4j获取日志记录器对象的两个方法:
         *   public static Logger getLogger(String name);
         *   public static Logger getLogger(Class clazz);
         */
        Logger logger = Logger.getLogger(Log4jTest.class);
        logger.fatal("fatal test"); // 记录严重的错误信息,一般会造成系统崩溃并终止运行
        logger.error("error test"); // 记录错误信息,不会影响系统运行
        logger.warn("warn test"); // 记录警告信息
        logger.info("info test"); // 记录运行信息
        logger.debug("debug test"); // (默认)记录调式信息,一般在开发中使用
        logger.trace("trace test"); // 记录追踪信息,记录程序的流程信息
    }
}

// 输出内容
0 [main] FATAL Log4jTest  - fatal test
0 [main] ERROR Log4jTest  - error test
0 [main] WARN Log4jTest  - warn test
0 [main] INFO Log4jTest  - info test
0 [main] DEBUG Log4jTest  - debug test

可以发现只打印出了TRACE没有打印出来,是由于默认日志级别为DEBUG,低于DEBUG级别的是不会打印出来

2、Log4j 组件介绍

Log4j主要由Loggers(日志记录器)、Appenders(输出端)和Layout(日志格式化器)组成,其中Loggers控制日志的输出级别与日志是否输出;Appenders指定日志的输出方式(输出到控制台、文件等);Layout控制日志信息的输出格式。

1、Loggers

日志记录器,负责收集处理日志记录,实例的命名就是类"xx"的full quailied name(类的全限定名),Logger的名字大小写敏感,其命名有继承机制。例如:name为org.apache.commoms的logger会继承name为org.apache的logger。

Log4j中有一个特殊的logger叫做"root",它是所有logger的根,也就意味着其他所有的logger都会直接或者间接的继承自root。root logger可以用Logger.getRootLogger()方法获取。JUL也有一个名为”.“的根。

PS:自Log4j 1.2版以来, Logger 类已经取代了 Category 类。对于熟悉早期版本的Log4j的人来说,Logger 类可以被视为 Category 类的别名。

2、Appenders

Appender 用来指定日志输出到哪个地方(和JUL的Handler很像),可以同时指定日志的输出目的地。Log4j 常用的输出目的地。有以下几种:

输出端类型作用
ConsoleAppender将日志输出到控制台
FileAppender将日志输出到文件中
DailyRollingFileAppender将日志输出到一个日志文件,并且每天输出到一个新的文件
RollingFileAppender将日志信息输出到一个日志文件,并且指定文件的尺寸,当文件大小达到指定尺寸时,会自动把文件改名,同时产生一个新的文件
JDBCAppender把日志信息保存到数据库中

3、Layouts

Layouts 布局器,用于控制日志输出的格式,让我么可以自定义日志格式,Log4j 常用的 Layouts 有以下几种

格式化器作用
HTMLLayout格式化日志为html表格形式
XMLLayout格式化日志为xml文档形式
SimpleLayout(默认)简单的日志输出格式化,打印的日志格式为(info - message)
PatternLayout最强大的格式化器,可以根据自定义格式输出日志,如果没有指定转换格式,默认的格式只显示消息内容;

4、日志输出格式

使用PatternLayout可以自定义格式输出,是我们最常用的方式,这种格式化输出采用类似C语言的printf函数的打印格式化日志信息,具体占位符及含义如下:

参数说明举例
%m输出代码中指定的日志信息logger.info(日志信息)
%p输出日志级别INFO、DEBUG、ERROR %-8p 表示占用8个字符,若字符不够用空格代替
%n换行符必须在结尾加上换行符,否则日志将杂乱不堪
%r输出从应用启动到输出该log信息耗费的毫秒数log打印时间 - 应用启动时间
%c输出打印语句所属的类全名%c :com.xd.App %c{1}:App
%C列出调用logger的类的全名(包含包路径)%C :com.xd.App %C{1}:App
%t输出产生该日志所在的线程名名称main 、thread-0、thread-1
%d输出服务器当前时间,精确到豪秒输出服务器当前时间, 默认为ISO8601, 也可指定格式:%d{yyyy-MM-dd HH:mm:ss}
%l输出日志发生的位置,包含包、类、方法、代码行数com.log.App.haveConfigFile(App.java:25)
%L输出代码中的行号12
%F显示调用logger的类的文件名App.class
%%输出一个百分号 %%
%*        可以在 % 与字符之间加上修饰符来控制最小宽度、最大宽度和文本的对其方式。如:
%5c       输出category名称,最小宽度是5,category<5,默认的情况下右对齐
%-5c      输出category名称,最小宽度是5,category<5,"-"号指定左对齐,会有空格
%.5c      输出category名称,最大宽度是5,category>5,就会将左边多出的字符截掉,<5不会有空格
%20.30c   category名称<20补空格,并且右对齐,>30字符,就从左边交远销出的字符截掉

5、日志输出级别

关于日志级别信息,例如:DEBUG、INFO、WARN、ERROR…级别是分大小的,DEBUG < INFO < WARN < ERROR,分别用来指定这条日志信息的重要程度,Log4j 输出日志的规则是:只输出级别不低于设定级别的日志信息,假设 Loggers 级别设定为 INFO,则 INFO、WARN、ERROR 级别的日志信息都会输出,而级别低于 INFO 的 DEBUG 则不会输出。

Log4j 的默认日志级别是:DEBUG

  1. OFF:最高等级的而级别,用户关闭所有的日志记录
  2. FATAL:严重的错误信息,一般会造成系统崩溃并终止运行
  3. ERROR:记录错误信息,不会影响系统运行。一般情况不想输出太多日志,则使用该级别即可
  4. WARN:记录警告信息
  5. INFO:记录运行信息
  6. DEBUG:(默认)记录调式信息,一般在开发中使用
  7. TRACE:记录追踪信息,记录程序的流程信息,一般情况不会使用
  8. ALL:最低等级,用于打开所有级别的日志记录

注:一般只使用4个级别,优先级从高到低为 ERROR > WARN > INFO > DEBUG

3、硬编码与配置文件

1、Java硬编码配置

1、Java代码配置:Appenders使用ConsoleAppender,Layouts使用SimpleLayout。

import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.SimpleLayout;
import java.io.PrintWriter;

public class Log4jTest {
    public static void main(String[] args) {
        Logger logger = Logger.getLogger(Log4jTest.class);
        // 配置一个控制台输出源
        ConsoleAppender consoleAppender = new ConsoleAppender(new SimpleLayout());
        consoleAppender.setName("console");
        consoleAppender.setWriter(new PrintWriter(System.out));
        logger.addAppender(consoleAppender);
        logger.setLevel(Level.ERROR);

        logger.fatal("fatal test"); // 记录严重的错误信息,一般会造成系统崩溃并终止运行
        logger.error("error test"); // 记录错误信息,不会影响系统运行
        logger.warn("warn test"); // 记录警告信息
        logger.info("info test"); // 记录运行信息
        logger.debug("debug test"); // (默认)记录调式信息,一般在开发中使用
        logger.trace("trace test"); // 记录追踪信息,记录程序的流程信息
    }
}

// 输出内容
FATAL - fatal test
ERROR - error test

2、Java代码配置,Appenders使用ConsoleAppender,Layouts使用自定义Layout。

import org.apache.log4j.*;
import org.apache.log4j.spi.LoggingEvent;

public class Log4jTest {
    public static void main(String[] args) {
        Logger logger = Logger.getLogger(Log4jTest.class);

        // 配置一个自定义Layout(自定义格式化输出)
        Layout layout = new Layout() {
            @Override
            public String format(LoggingEvent loggingEvent) {
                // loggingEvent.getLoggerName()输出包名+类名
                return loggingEvent.getLoggerName() + " " + loggingEvent.getMessage() + "\r\n";
            }

            @Override
            public boolean ignoresThrowable() {
                return false;
            }

            @Override
            public void activateOptions() {
            }
        };
        // 配置一个控制台输出源
        ConsoleAppender consoleAppender = new ConsoleAppender(layout);
        consoleAppender.setName("customConsole");
        logger.addAppender(consoleAppender);
        logger.setLevel(Level.ERROR);

        logger.fatal("fatal test"); // 记录严重的错误信息,一般会造成系统崩溃并终止运行
        logger.error("error test"); // 记录错误信息,不会影响系统运行
        logger.warn("warn test"); //记录警告信息
        logger.info("info test"); // 记录运行信息
        logger.debug("debug test"); // (默认)记录调式信息,一般在开发中使用
        logger.trace("trace test"); // 记录追踪信息,记录程序的流程信息
    }
}

// 输出内容
Log4jTest fatal test
Log4jTest error test

3、注意如下两个配置,需要的时候可以配置

// 初始化配置信息(没有使用使用配置文件情况下)
BasicConfigurator.configure();
// 开启Log4j内置日志记录(用来打印Log4j更加详细的debug信息)
LogLog.setInternalDebugging(true);

2、加载配置文件

通过查看LogManager源码可知log4j是通过静态代码块中,类加载器加载的配置文件,所以可以在resources下新建一个log4j.properties文件:

# 指定日志的输出级别与输出端
# WARN代表的是输出级别, console是我们自定义的一个名称appenderNam, 这个可以设置打印到多个地方, 中间用逗号隔开
log4j.rootLogger = WARN,console
# 配置appender输出方法及配置输出信息的格式
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.layout = org.apache.log4j.SimpleLayout
import org.apache.log4j.Logger;
public class Log4jTest {
    public static void main(String[] args) {
        Logger logger = Logger.getLogger(Log4jTest.class);
        logger.fatal("fatal test"); // 记录严重的错误信息,一般会造成系统崩溃并终止运行
        logger.error("error test"); // 记录错误信息,不会影响系统运行
        logger.warn("warn test"); //记录警告信息
        logger.info("info test"); // 记录运行信息
        logger.debug("debug test"); // (默认)记录调式信息,一般在开发中使用
        logger.trace("trace test"); // 记录追踪信息,记录程序的流程信息
    }
}

// 输出内容
FATAL - fatal test
ERROR - error test
WARN - warn test

4、Appender输出详解

1、将日志输出到控制台

ConsoleAppender:将日志输出到控制台

# 指定日志的输出级别与输出端
# 第1个逗号前是设置的日志级别,后面是自定义名称,输出到什么地方.名称在下方使用
log4j.rootLogger=INFO,console

############################# 控制台输出配置 #############################
# 1、指定控制台日志输出的appender
log4j.appender.console = org.apache.log4j.ConsoleAppender
# 指定消息格式layout,使用简单格式SimpleLayout ,HTML格式HTMLLayout,xml格式xml.XMLLayout
log4j.appender.console.layout = org.apache.log4j.PatternLayout
# 指定消息格式的内容
#log4j.appender.console.layout.conversionPattern = %r [%t] %p %c %x - %m%n
log4j.appender.console.layout.conversionPattern =[%p] %r %l %d{yyyy-MM-dd HH:mm:ss:SSS} %m%n
import org.apache.log4j.Logger;
public class Log4jTest {
    public static void main(String[] args) {
        Logger logger = Logger.getLogger(Log4jTest.class);

        logger.fatal("fatal test"); // 记录严重的错误信息,一般会造成系统崩溃并终止运行
        logger.error("error test"); // 记录错误信息,不会影响系统运行
        logger.warn("warn test"); // 记录警告信息
        logger.info("info test"); // 记录运行信息
        logger.debug("debug test"); // (默认)记录调式信息,一般在开发中使用
        logger.trace("trace test"); // 记录追踪信息,记录程序的流程信息
    }
}

控制台中输出如下内容

[FATAL] 0 Log4jTest.main(Log4jTest.java:6) 2022-03-30 15:09:46:620 fatal test
[ERROR] 0 Log4jTest.main(Log4jTest.java:7) 2022-03-30 15:09:46:620 error test
[WARN] 0 Log4jTest.main(Log4jTest.java:8) 2022-03-30 15:09:46:620 warn test
[INFO] 0 Log4jTest.main(Log4jTest.java:9) 2022-03-30 15:09:46:620 info test

2、将日志输出到指定文件

FileAppender:将日志输出到文件中

# 指定日志的输出级别与输出端
# 第1个逗号前是设置的日志级别,后面是自定义名称,输出到什么地方.名称在下方使用
log4j.rootLogger=INFO,file

############################# 文件输出配置 #############################
# 2、指定文件日志输出的appender【默认是追加的】
log4j.appender.file = org.apache.log4j.FileAppender
# 指定消息格式layout,使用简单格式SimpleLayout ,HTML格式HTMLLayout,xml格式XMLLayout
log4j.appender.file.layout = org.apache.log4j.PatternLayout
# 指定消息格式的内容 (%r [%t] %p %c %x - %m%n)
log4j.appender.file.layout.conversionPattern =[%p] %r %l %d{yyyy-MM-dd HH:mm:ss:SSS} %m%n
# 指定日志文件的保存路径
log4j.appender.file.file = ./logs/log4j.log
# 指定日志文件的字符集
log4j.appender.file.encoding = UTF-8

此时这个日志信息会输出到这个指定位置的文件中。项目同级目录下会自动创建目录与文件(logs/log4j.log)输出内容如下:

[FATAL] 0 Log4jTest.main(Log4jTest.java:6) 2022-03-30 15:09:46:620 fatal test
[ERROR] 0 Log4jTest.main(Log4jTest.java:7) 2022-03-30 15:09:46:620 error test
[WARN] 0 Log4jTest.main(Log4jTest.java:8) 2022-03-30 15:09:46:620 warn test
[INFO] 0 Log4jTest.main(Log4jTest.java:9) 2022-03-30 15:09:46:620 info test

3、根据时间来拆分日志文件

DailyRollingFileAppender:将日志输出到一个日志文件,并且每天输出到一个新的文件

这个会根据你输入的时间间隔来生成新的日志信息,这个时间可以是一天,也可以是一秒,需要注意的是这个并不是自动为我们生成新的日志文件,是我们手动生成的日志文件,比如:你设置的间隔是 yyyy-MM-dd ,这个时候如果你现在输出了一个日志文件,那么在这个时间开始的后24个小时内都不会生成新的日志文件,在这24小时内输出的日志文件都会存储到这个一个旧的日志文件中。即使过了24个小时,系统也不会为我们自动生成一个新的日志文件,需要程序员在输出日志的时候才会生成一个新的日志文件,加可以精确到秒,那么一秒就会为我们生成一个新的日志文件。

# 指定日志的输出级别与输出端
# 第1个逗号前是设置的日志级别,后面是自定义名称,输出到什么地方.名称在下方使用
log4j.rootLogger=INFO,dailyFile

############################# 按照时间规则输出到文件 #############################
# 3、按日期日志文件输出的appender【在这个类中没有提供覆盖的方法】
log4j.appender.dailyFile = org.apache.log4j.DailyRollingFileAppender
# 指定消息格式layout,使用简单格式SimpleLayout ,HTML格式HTMLLayout,xml格式XMLLayout
log4j.appender.dailyFile.layout = org.apache.log4j.PatternLayout
# 指定消息格式的内容
log4j.appender.dailyFile.layout.conversionPattern =[%p] %r %l %d{yyyy-MM-dd HH:mm:ss:SSS} %m%n
# 指定日志文件的保存路径【当前文件默认是覆盖的】
log4j.appender.dailyFile.file = ./logs/log4j.log
# 指定日志文件的字符集
log4j.appender.dailyFile.encoding = UTF-8
# 指定日期拆分规则 默认【'.'yyyy-MM-dd】时间pattern只能以短横线-划分
log4j.appender.dailyFile.datePattern = '.'yyyy-MM-dd-HH-mm-ss

多次执行测试类,这时可以发现指定路径下会按照时间秒生产日志文件(log4j.log 中文件是覆盖的,log4j.log.xxx文件在同一个时间内是追加的)

log4j.log
log4j.log.2022-03-30-15-46-12
log4j.log.2022-03-30-15-46-14

在测试时可以根据秒来指定拆分策略,但实际生产环境中,我们可以根据按天或者周、月进行拆分。

4、根据文件大小拆分日志文件

RollingFileAppender:将日志信息输出到一个日志文件,并且指定文件的尺寸,当文件大小达到指定尺寸时,会自动把文件改名,同时产生一个新的文件

# 指定日志的输出级别与输出端
# 第1个逗号前是设置的日志级别,后面是自定义名称,输出到什么地方.名称在下方使用
log4j.rootLogger=INFO,rollingFile

############################# 按照文件大小拆分输出到文件 #############################
# 4、按照文件大小拆分的appender
log4j.appender.rollingFile = org.apache.log4j.RollingFileAppender
# 指定消息格式layout,使用简单格式SimpleLayout ,HTML格式HTMLLayout,xml格式XMLLayout
log4j.appender.rollingFile.layout = org.apache.log4j.PatternLayout
# 指定消息格式的内容
log4j.appender.rollingFile.layout.conversionPattern =[%p] %r %l %d{yyyy-MM-dd HH:mm:ss:SSS} %m%n
# 指定日志文件的保存路径
log4j.appender.rollingFile.file = ./logs/log4j.log
# 指定日志文件的字符集
log4j.appender.rollingFile.encoding = UTF-8
# 指定日志文件内容的大小【这里为了测试所以1KB】
log4j.appender.rollingFile.maxFileSize = 1KB
# 指定日志文件的数量【默认是1个】 超过5个,按照时间覆盖(最旧的文件覆盖最新的文件)
log4j.appender.rollingFile.maxBackupIndex = 5
import org.apache.log4j.Logger;
public class Log4jTest {
    public static void main(String[] args) {
        Logger logger = Logger.getLogger(Log4jTest.class);
        for (int i = 0; i < 100; i++) {
            logger.fatal("fatal test"); // 记录严重的错误信息,一般会造成系统崩溃并终止运行
            logger.error("error test"); // 记录错误信息,不会影响系统运行
            logger.warn("warn test"); // 记录警告信息
            logger.info("info test"); // 记录运行信息
            logger.debug("debug test"); // (默认)记录调式信息,一般在开发中使用
            logger.trace("trace test"); // 记录追踪信息,记录程序的流程信息
        }
    }
}

只要文件超过1KB,那么则生成另一个文件,文件的数量最多5个。如果5个文件啊不够怎么办,作为日志管理来讲,不可能让日志无休止的增长,所以覆盖策略是:按照时间来进行覆盖,原则是保留新的,覆盖旧的。这个时候日志6会覆盖掉日志1.

log4j.log
log4j.log.1
log4j.log.2
log4j.log.3
log4j.log.4
log4j.log.5

5、将日志信息存储到数据库

JDBCAppender:把日志信息保存到数据库中

数据库这里需要新建数据库,加入数据库的依赖,然后在配置文件中配置连接数据库的信息并且设置插入语句。

-- create table
CREATE TABLE tab_log (
    log_id int(11) NOT NULL AUTO_INCREMENT,
    project_name varchar(255) DEFAULT NULL COMMENT '目项名',
    create_date  varchar(255) DEFAULT NULL COMMENT '创建时间',
    level varchar(255) DEFAULT NULL COMMENT '优先级',
    category  varchar(255) DEFAULT NULL COMMENT '所在类的全名',
    file_name varchar(255) DEFAULT NULL COMMENT '输出日志消息产生时所在的文件名称',
    thread_name varchar(255) DEFAULT NULL COMMENT '日志事件的线程名',
    line varchar(255) DEFAULT NULL COMMENT '号行',
    all_category varchar(255) DEFAULT NULL COMMENT '日志事件的发生位置',
    message  varchar (4000) DEFAULT NULL COMMENT '输出代码中指定的消息',
    PRIMARY KEY (log_id)
);
<!--mysql依赖-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.9</version>
</dependency>
# 指定日志的输出级别与输出端
# 第1个逗号前是设置的日志级别,后面是自定义名称,输出到什么地方.名称在下方使用
log4j.rootLogger=INFO,logDB

############################# 将日志信息存储到数据库 #############################
# 5、持久化日志信息 将日志信息存储到数据库的appender
log4j.appender.logDB = org.apache.log4j.jdbc.JDBCAppender
log4j.appender.logDB.layout = org.apache.log4j.PatternLayout
log4j.appender.logDB.Driver = com.mysql.jdbc.Driver
log4j.appender.logDB.URL = jdbc:mysql://localhost/tab_log
log4j.appender.logDB.User = root
log4j.appender.logDB.Password = password
# 此时要像数据库中插入数据,使用insert语句
log4j.appender.logDB.Sql =  INSERT INTO tab_log(name,create,level,category,fileName,message) values('project_log','%d{yyyy-MM-dd HH:mm:ss}','%p','%c','%F','%m')

然后执行测试类,可以查看到数据中成功插入日志。

6、将日志信息输出到多个位置

上面分别介绍了单个Appender的用法,实际上我们还可以将日志同时输出到多个Appender中。下面示例同时输出到控制台、文件与数据库中

# 指定日志的输出级别与输出端
# 第1个逗号前是设置的日志级别,后面是自定义名称,输出到什么地方.名称在下方使用
log4j.rootLogger=INFO,console,file,logDB

############################# 控制台输出配置 #############################
# 1、指定控制台日志输出的appender
log4j.appender.console = org.apache.log4j.ConsoleAppender
# 指定消息格式layout,使用简单格式SimpleLayout ,HTML格式HTMLLayout,xml格式xml.XMLLayout
log4j.appender.console.layout = org.apache.log4j.PatternLayout
# 指定消息格式的内容
#log4j.appender.console.layout.conversionPattern = %r [%t] %p %c %x - %m%n
log4j.appender.console.layout.conversionPattern =[%p] %r %l %d{yyyy-MM-dd- HH:mm:ss:SSS} %m%n

############################# 文件输出配置 #############################
# 2、指定文件日志输出的appender【默认是追加的】
log4j.appender.file = org.apache.log4j.FileAppender
# 指定消息格式layout,使用简单格式SimpleLayout ,HTML格式HTMLLayout,xml格式XMLLayout
log4j.appender.file.layout = org.apache.log4j.PatternLayout
# 指定消息格式的内容 (%r [%t] %p %c %x - %m%n)
log4j.appender.file.layout.conversionPattern =[%p] %r %l %d{yyyy-MM-dd HH:mm:ss:SSS} %m%n
# 指定日志文件的保存路径
log4j.appender.file.file = ./logs/log4j.log
# 指定日志文件的字符集
log4j.appender.file.encoding = UTF-8

############################# 将日志信息存储到数据库 #############################
# 5、持久化日志信息 将日志信息存储到数据库的appender
log4j.appender.logDB = org.apache.log4j.jdbc.JDBCAppender
log4j.appender.logDB.layout = org.apache.log4j.PatternLayout
log4j.appender.logDB.Driver = com.mysql.jdbc.Driver
log4j.appender.logDB.URL = jdbc:mysql://localhost/tab_log
log4j.appender.logDB.User = root
log4j.appender.logDB.Password = password
# 此时要像数据库中插入数据,使用insert语句
log4j.appender.logDB.Sql =  INSERT INTO tab_log(name,create,level,category,fileName,message) values('project_log','%d{yyyy-MM-dd HH:mm:ss}','%p','%c','%F','%m')

实际上主要是对这个配置的修改:

# 指定日志的输出级别与输出端, 第1个逗号前是设置的日志级别,后面是自定义名称,输出到什么地方.名称在下方使用
log4j.rootLogger = info,console,file

5、自定义配置Logger

# 使用最高父类rootLogger配置logger,这个时候继承的是父logger(根节点)
log4j.rootLogger = info,console

# 配置自定义loggerlogger对象,会默认继承rootLogger
# 级别会覆盖, INFO升级为WARN. Appender会继承, 既会向控制台输出console, 也会向文件file输出
# 注意:这里自定义的com.xyz是Log4jTest类所在的包名路径
log4j.logger.com.xyz = warn,file

# 第三方框架(org.apache.log4j.Logger)的错误日志打印,不指定appender,就是默认rootLogger的appender(console)
log4j.logger.org.apache = error


############################# 控制台输出配置 #############################
# 1、指定控制台日志输出的appender
log4j.appender.console = org.apache.log4j.ConsoleAppender
# 指定消息格式layout,使用简单格式SimpleLayout ,HTML格式HTMLLayout,xml格式xml.XMLLayout
log4j.appender.console.layout = org.apache.log4j.PatternLayout
# 指定消息格式的内容
#log4j.appender.console.layout.conversionPattern = %r [%t] %p %c %x - %m%n
log4j.appender.console.layout.conversionPattern =[%p] %r %l %d{yyyy-MM-dd HH:mm:ss:SSS} %m%n

############################# 文件输出配置 #############################
# 2、指定文件日志输出的appender【默认是追加的】
log4j.appender.file = org.apache.log4j.FileAppender
# 指定消息格式layout,使用简单格式SimpleLayout ,HTML格式HTMLLayout,xml格式XMLLayout
log4j.appender.file.layout = org.apache.log4j.PatternLayout
# 指定消息格式的内容 (%r [%t] %p %c %x - %m%n)
log4j.appender.file.layout.conversionPattern =[%p] %r %l %d{yyyy-MM-dd HH:mm:ss:SSS} %m%n
# 指定日志文件的保存路径
log4j.appender.file.file = ./logs/log4j.log
# 指定日志文件的字符集
log4j.appender.file.encoding = UTF-8
package com.xyz;

import org.apache.log4j.Logger;
public class Log4jTest {
    public static void main(String[] args) {
        Logger logger = Logger.getLogger(Log4jTest.class);
        logger.fatal("fatal test"); // 记录严重的错误信息,一般会造成系统崩溃并终止运行
        logger.error("error test"); // 记录错误信息,不会影响系统运行
        logger.warn("warn test"); // 记录警告信息
        logger.info("info test"); // 记录运行信息
        logger.debug("debug test"); // (默认)记录调式信息,一般在开发中使用
        logger.trace("trace test"); // 记录追踪信息,记录程序的流程信息


        // 三方框架的错误日志信息打印
        // 因为log4j.properties文件中appender名是类名的包路径,
        // 这里是org.apache.log4j.Logger,就可以继承log4j.properties的配置
        Logger logger2 = Logger.getLogger(Logger.class);
        logger2.fatal("fatal test2"); // 记录严重的错误信息,一般会造成系统崩溃并终止运行
        logger2.error("error test2"); // 记录错误信息,不会影响系统运行
        logger2.warn("warn test2"); // 记录警告信息
        logger2.info("info test2"); // 记录运行信息
        logger2.debug("debug test2"); // (默认)记录调式信息,一般在开发中使用
        logger2.trace("trace test2"); // 记录追踪信息,记录程序的流程信息
    }
}

控制台输出:

[FATAL] 0 com.xyz.Log4jTest.main(Log4jTest.java:7) 2022-03-30 17:58:48:215 fatal test
[ERROR] 10 com.xyz.Log4jTest.main(Log4jTest.java:8) 2022-03-30 17:58:48:225 error test
[WARN] 10 com.xyz.Log4jTest.main(Log4jTest.java:9) 2022-03-30 17:58:48:225 warn test
[FATAL] 10 com.xyz.Log4jTest.main(Log4jTest.java:19) 2022-03-30 17:58:48:225 fatal test2
[ERROR] 10 com.xyz.Log4jTest.main(Log4jTest.java:20) 2022-03-30 17:58:48:225 error test2

文件中输出:

[FATAL] 0 com.xyz.Log4jTest.main(Log4jTest.java:7) 2022-03-30 17:58:48:215 fatal test
[ERROR] 10 com.xyz.Log4jTest.main(Log4jTest.java:8) 2022-03-30 17:58:48:225 error test
[WARN] 10 com.xyz.Log4jTest.main(Log4jTest.java:9) 2022-03-30 17:58:48:225 warn test

可以看出:file中不会存入org.apache这个logger的日志,因为该logger没有指定appender,默认的rootLogger的appender只是输出到控制台的

自定义Logger结论:如果根节点的Logger和自定义父Logger配置的输出位置是不同的则取二者的并集,也就是配置的位置都会进行日志的输出。如果二者配置的日志级别不同,主要以按照我们自定义的父logger的级别输出为主。

6、参考文献 & 鸣谢

  • 日志技术之Log4j学习【CSDN:StudyWinter】https://blog.csdn.net/Zhouzi_heng/article/details/107965987
  • java日志:二、log4j使用【CSDN:小徐也要努力鸭】https://blog.csdn.net/a232884c/article/details/121102525
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值