逐日生成日志文件

您也许需要逐日生成日志文件,以此更加整洁的记录日志信息。

为了逐日生成日志文件,需要使用org.apache.log4j.DailyRollingFileAppender,该类继承了FileAppender类,继承了它的所有属性。

除了上述提到的FileAppender类的属性,该类多包含了一个重要属性:

属性 描述
DatePattern 该属性表明什么时间回滚文件,以及文件的命名约定。缺省情况下,在每天午夜回滚文件。

DatePattern使用如下规则控制回滚计划:

DatePattern 描述
'.'yyyy-MM 在本月末,下月初回滚文件。
'\.'yyyy-MM-dd 在每天午夜回滚文件,这是缺省值。
'\.'yyyy-MM-dd-a 在每天中午和午夜回滚文件。
'\.'yyyy-MM-dd-HH 在每个整点回滚文件。
'\.'yyyy-MM-dd-HH-mm 每分钟回滚文件。
'\.'yyyy-ww 根据地域,在每周的第一天回滚。

log4j.properties

下述Log4j.properties示例文件产生的日志文件在每天中午和午夜回滚:

/Log4jDemo/Log4jConfig/DailyRollingFileAppender/log4j.properties
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Define the root logger with appender file
log4j.rootLogger = DEBUG, FILE

# Define the file appender
log4j.appender.FILE=org.apache.log4j.DailyRollingFileAppender

# Set the name of the file
#log4j.appender.FILE.File=${log}/log.out
log4j.appender.FILE.File=log.out

# Set the immediate flush to true (default)
log4j.appender.FILE.ImmediateFlush=true

# Set the threshold to debug mode
log4j.appender.FILE.Threshold=debug

# Set the append to false, should not overwrite
log4j.appender.FILE.Append=true

# Set the DatePattern
log4j.appender.FILE.DatePattern='.' yyyy-MM-dd-a

# Define the layout for file appender
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.conversionPattern=%m%n

如果您想使用XML配置文件,可以像上一节一样生成XML配置文件,只需添加和DailyRollingFileAppender相关的配置即可。

Log4j 使用多个文件记录日志 RollingFileAppender类

您可能因为某些原因,需要将日志写入多个文件,比如当文件大小达到一定阀值时。

为了将日志写入多个文件,您需要使用org.apache.Log4j.RollingFileAppender,该类继承了FileAppender类,继承了它的所有属性。
除了上述提到的FileAppender类的属性,该类还包括如下可配置的属性:

RollingFileAppender新增属性 描述
maxFileSize 这是文件大小的关键值,大于该值时,文件会回滚。该值默认为10MB
maxBackupIndex 该值表示备份文件的个数,默认为1。

log4j.properties

下面是为RollingFileAppender定义的示例配置文件Log4j.properties

/Log4jDemo/Log4jConfig/RollingFileAppender/Log4j.properties
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# Define the root logger with appender file
log4j.rootLogger = DEBUG, FILE

# Define the file appender
log4j.appender.FILE=org.apache.log4j.RollingFileAppender

# Set the name of the file
log4j.appender.FILE.File=log.out

# Set the immediate flush to true (default)
log4j.appender.FILE.ImmediateFlush=true

# Set the threshold to debug mode
log4j.appender.FILE.Threshold=debug

# Set the append to false, should not overwrite
log4j.appender.FILE.Append=true

# Set the maximum file size before rollover
log4j.appender.FILE.MaxFileSize=5KB

# Set the the backup index
log4j.appender.FILE.MaxBackupIndex=2

# Define the layout for file appender
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.conversionPattern=%m%n

如果您想使用XML配置文件,可以像上一节一样生成XML配置文件,只需添加和RollingFileAppender相关的配置即可。
该示例配置文件展示了每个日志文件最大为5MB,如果超过该最大值,则会生成一个新的日志文件。由于maxBackupIndex的值为2,当第二个文件的大小超过最大值时,会擦去第一个日志文件的内容,所有的日志都回滚至第一个日志文件。

Log4j 使用文件记录日志 FileAppender类

使用org.apache.log4j.FileAppender将日志记录到文件。

FileAppender配置参数

FileAppender拥有如下配置参数:

属性 描述
immediateFlush 该标志位默认为true,意味着每次日志追加操作都将输出流刷新至文件。
encoding 可以使用任何编码,默认情况下使用平台相关的编码。
threshold appender对象的阀值。
Filename 日志文件名。
fileAppend 该值默认为true,其含义是让日志追加至文件末尾。
bufferedIO 该标志位表示是否打开缓冲区写,缺省为false
bufferSize 如果开启缓冲区I/O,该属性指示缓冲区大小,缺省为8kb

示例代码

以下是FileAppender的配置文件示例log4j.properties

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 设置日志文件存放的路径
log=E:\workspacne_JDK8Tomcat8.5\Log4jDemo
# Define the root logger with appender file
log4j.rootLogger = DEBUG, FILE

# Define the file appender
log4j.appender.FILE=org.apache.log4j.FileAppender
# file name
log4j.appender.FILE.File=${log}/log.out

# Set the flush to true
log4j.appender.FILE.ImmediateFlush=true

# Set the threshold to debug mode
log4j.appender.FILE.Threshold=debug

# Set the append to true, overwrite
log4j.appender.FILE.Append=true

# Define the layout for file appender
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.conversionPattern=%m%n
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration
PUBLIC "-//LOG4J//DTD LOG4J//EN"
"https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd" >
<log4j:configuration
xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="STDOUT"
class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%5p [%t] %m%n" />
</layout>
</appender>
<appender name="FILE" class="org.apache.log4j.FileAppender">
<param name="File" value="${log}/log.out" />
<param name="ImmediateFlush" value="true" />
<param name="Threshold" value="debug" />
<param name="Append" value="true" />

<layout class="org.apache.log4j.PatternLayout">
<param name="conversionPattern" value="%m%n" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE"/>
</root>
</log4j:configuration>

log4j.xml中如何使用变量替换

注意,这里的XML文件中使用了变量替换${log},在使用这个log变量之前需要创建这个变量,但是在XML中好像没有创建变量的方法.
解决方案:
使用log4j.xml时实现类似功能的唯一方法是在启动时设置系统属性,然后从log4j.xml中引用该属性。

运行Java时给定参数

启动时,设置系统属性:

1
java -Dlog=E:\workspacne_JDK8Tomcat8.5\Log4jDemo com.yourorg.yourapp.Main

编程方式指定

或在运行时以编程方式设置(在初始化log4j之前):

1
System.setProperty("log", "E:\workspacne_JDK8Tomcat8.5\Log4jDemo")

然后您可以这样引用它:

1
2
3
4
5
<appender name="FILE" class="org.apache.log4j.FileAppender">
...
<param name="file" value="${log}/log.out"/>
...
</appender>

示例

/Log4jDemo/src/demo/file/appender/XMLFileAppenderTest.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package demo.file.appender;

import java.io.IOException;
import java.sql.SQLException;
import org.apache.log4j.Logger;
import demo.Log4jExample;

public class XMLFileAppenderTest
{

static
{
System.setProperty("log", "E:/workspacne_JDK8Tomcat8.5/Log4jDemo");
}
/* Get actual class name to be printed on */
static Logger log = Logger.getLogger(Log4jExample.class.getName());

public static void main(String[] args) throws IOException, SQLException
{
log.debug("Hello this is a debug message");
log.info("Hello this is an info message");
}
}

删除项目目录下的log.out文件,运行上述代码后,项目目录下的会重新生成log.out日志文件

使用绝对路径不使用变量替换

1
2
3
4
5
6
7
8
9
10
11
12
<appender name="FILE" class="org.apache.log4j.FileAppender">
<!-- <param name="File" value="${log}/log.out" /> -->
<param name="File" value="E:/workspacne_JDK8Tomcat8.5/Log4jDemo/log.out" />
<!-- <param name="File" value="log.out" /> -->
<param name="ImmediateFlush" value="true" />
<param name="Threshold" value="debug" />
<param name="Append" value="true" />

<layout class="org.apache.log4j.PatternLayout">
<param name="conversionPattern" value="%m%n" />
</layout>
</appender>

使用相对路径

1
2
3
4
5
6
7
8
9
10
11
12
<appender name="FILE" class="org.apache.log4j.FileAppender">
<!-- <param name="File" value="${log}/log.out" /> -->
<!-- <param name="File" value="E:/workspacne_JDK8Tomcat8.5/Log4jDemo/log.out" /> -->
<param name="File" value="log.out" />
<param name="ImmediateFlush" value="true" />
<param name="Threshold" value="debug" />
<param name="Append" value="true" />

<layout class="org.apache.log4j.PatternLayout">
<param name="conversionPattern" value="%m%n" />
</layout>
</appender>

Log4j 日志格式 Layout类

Apache Log4j提供了多个Layout对象,每个根据布局的不同都可格式化日志数据。还可以创建一个Layout对象,以应用特有的方式格式化日志。

所有Layout对象从Appender对象那里接收一个LoggingEvent对象,然后从LoggingEvent对象那里获取信息,并使用恰当的ObjectRenderer对象获取该信息的字符串形式。

Layout类型

位于继承关系顶层的是抽象类org.apache.log4j.Layout,这是所有Log4j APILayout类的基类。
Layout类是个抽象类,在应用中我们从不直接使用该类,而是使用它的子类,如下所示:

  • DateLayout
  • HTMLLayout
  • PatternLayout
  • SimpleLayout
  • XMLLayout

Layout方法

该类对于所有其他Layout对象的通用操作提供了框架性的实现,声明了两个抽象方法:

Layout抽象类的抽象方法 描述
public abstract boolean ignoresThrowable() 该方法指明日志信息是否处理由日志事件传来的java.lang.Throwable对象,如果Layout对象能处理Throwable对象,则Layout对象不会忽略它,并且返回false
public abstract String format(LoggingEvent event) Layout子类实现该方法,以定义各自的格式。

除了这些抽象方法,Layout 类还提供了如下的具体方法:

Layout抽象类具体方法 描述
public String getContentType() 返回布局对象使用的内容类型。
public String getFooter() 记录消息的页脚信息。
public String getHeader() 日志消息的头信息。

每个子类均可覆盖这些方法的实现,返回各自特有的信息。

Log4j 日志级别Level类

org.apache.Log4j.Level类定义了日志级别,您可通过继承Level类定制自己的级别。

级别 描述
OFF 最高级别,用于关闭日志。
FATAL 指明非常严重的错误事件,可能会导致应用终止执行。
ERROR 指明错误事件,但应用可能还能继续运行。
WARN 指明潜在的有害状况。
INFO 指明描述信息,从粗粒度上描述了应用运行过程。
DEBUG 指明细致的事件信息,对调试应用最有用。
TRACE DEBUG级别的粒度更细。
ALL 所有级别,包括定制级别。

日志级别是如何工作的

在一个级别为q的logger对象中,一个级别为p的日志请求在p >= q的情况下是开启的。该规则是Log4j的核心,它假设级别是有序的。
对于标准级别,其顺序为:ALL<TRACE<DEBUG<INFO<WARN<ERROR<FATAL<OFF
例如设置级别为DEBUG,则比DEBUG高的INFO,WARN,ERROR,FATAL都是开启的.

在程序中设置日志级别

使用logger对象的setLevel(Level.级别)方法可以设置期望的日志级别:

SetLevelByMethod.java

/Log4jDemo/src/demo/level/SetLevelByMethod.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package demo.level;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

public class SetLevelByMethod
{
private static Logger log = Logger.getLogger(SetLevelByMethod.class);

public static void main(String[] args)
{
// 使用方法设置日志级别
log.setLevel(Level.WARN);
log.trace("Trace Message!");
log.debug("Debug Message!");
log.info("Info Message!");
log.warn("Warn Message!");
log.error("Error Message!");
log.fatal("Fatal Message!");
}
}

运行效果

1
2
3
2020-08-03 18:32:58 WARN  SetLevelByMethod:17 - Warn Message!
2020-08-03 18:32:58 ERROR SetLevelByMethod:18 - Error Message!
2020-08-03 18:32:58 FATAL SetLevelByMethod:19 - Fatal Message!

可以看到,程序只输出WARM级别和比WARN更高的级别的日志输出

使用配置文件设置日志级别

Log4j提供了基于配置文件设置日志级别的功能.当您需要改变调试级别时,只需要修改配置文件即可,不用再去修改代码。

log4j.properties

下面这个例子和上面那个例子功能一样,不过不用使用setLevel(Level.WARN)方法,只需修改配置文件:

/Log4jDemo/Log4jConfig/Level/log4j.properties
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 输出到控制台
# Root logger option
#ALL<TRACE<DEBUG<INFO< WARN< ERROR< FATAL< OFF
#log4j.rootLogger=OFF, STDOUT
#log4j.rootLogger=FATAL, STDOUT
#log4j.rootLogger=ERROR, STDOUT
#log4j.rootLogger=WARN, STDOUT
log4j.rootLogger=INFO, STDOUT
#log4j.rootLogger=DEBUG, STDOUT
#log4j.rootLogger=TRACE, STDOUT
#log4j.rootLogger=ALL, STDOUT

# Direct log messages to STDOUT
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{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

SetLevleByConfig.java

/Log4jDemo/src/demo/level/SetLevleByConfig.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package demo.level;

import org.apache.log4j.Logger;

public class SetLevleByConfig
{
private static Logger log = Logger.getLogger(SetLevleByConfig.class);

public static void main(String[] args)
{

log.trace("Trace Message!");
log.debug("Debug Message!");
log.info("Info Message!");
log.warn("Warn Message!");
log.error("Error Message!");
log.fatal("Fatal Message!");
}
}

运行结果

1
2
3
4
2020-08-03 18:49:27 INFO  SetLevleByConfig:14 - Info Message!
2020-08-03 18:49:27 WARN SetLevleByConfig:15 - Warn Message!
2020-08-03 18:49:27 ERROR SetLevleByConfig:16 - Error Message!
2020-08-03 18:49:27 FATAL SetLevleByConfig:17 - Fatal Message!

Log4j Logger类方法

获取Logger类实例

Logger类提供了很多方法用来处理日志,Logger类不允许初始化一个新的实例,但提供了两个静态方法用来获取Logger对象:

Logger类获取Logger实例的方法 描述
public static Logger getRootLogger(); 返回没有名称的根日志记录器
public static Logger getLogger(String name); 按名称返回记录器。
日志的名字是传入的任何字符串,通常为类名或者包名。例如:
static Logger log = Logger.getLogger(log4jExample.class.getName());

打印日志信息的方法

一旦获取一个有名字的logger实例,就可以使用多个方法记录日志。Logger类拥有如下方法用于打印日志信息。

方法 描述
public void debug(Object message) 打印Level.DEBUG级别的消息。
public void error(Object message) 打印Level.ERROR级别的消息。
public void fatal(Object message) 打印具有Level.FATAL级别的消息。
public void info(Object message) 打印Level.INFO级别的消息。
public void warn(Object message) 打印Level.WARN级别的消息。
public void trace(Object message) 打印Level.TRACE级别的消息

所有级别均在org.apache.log4j.Level 类中定义。

示例程序

/Log4jDemo/src/demo/method/LoggerMethodTest.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package demo.method;

import org.apache.log4j.Logger;

public class LogClass
{
private static Logger log = Logger.getLogger(LogClass.class);

public static void main(String[] args)
{

log.trace("Trace Message!");
log.debug("Debug Message!");
log.info("Info Message!");
log.warn("Warn Message!");
log.error("Error Message!");
}

}

运行效果如下:

1
2
3
4
5
2020-08-03 17:55:26 DEBUG LogClass:13 - Debug Message!
2020-08-03 17:55:26 INFO LogClass:14 - Info Message!
2020-08-03 17:55:26 WARN LogClass:15 - Warn Message!
2020-08-03 17:55:26 ERROR LogClass:16 - Error Message!

可以看到log.trace("Trace Message!");这句代码并没有输出,这是因为当前的日志级别是debugLog4j只会输出级别为debug或者小于debug的日志信息.trace的级别更高,所以不会输出

Log4j示例程序

我们已经学会了如何创建配置文件,本章讲述如何生成调试信息,并将其写入一个简单的文本文件。

项目结构

展开/折叠
E:\workspacne_JDK8Tomcat8.5\Log4jDemo
├─lib\
│ ├─commons-logging-1.2.jar
│ ├─log4j-1.2.17.jar
│ ├─log4j-api-2.13.3.jar
│ ├─log4j-core-2.13.3.jar
│ └─mysql-connector-java-8.0.17.jar
├─log.out
├─Log4jConfig\
│ ├─DailyRollingFileAppender\
│ │ └─log4j.properties
│ ├─file\
│ │ └─log4j.properties
│ ├─FileAppender\
│ │ ├─log4j.properties
│ │ └─log4j.xml
│ ├─file_and_stout\
│ │ └─log4j.properties
│ ├─grammar\
│ │ └─log4j.properties
│ ├─HTMLLayout\
│ │ └─log4j.properties
│ ├─JDBCAppender\
│ │ ├─log4j.properties
│ │ └─log4j.xml
│ ├─Level\
│ │ └─log4j.properties
│ ├─loggerPackage\
│ │ └─log4j.xml
│ ├─PatternLayout\
│ │ └─log4j.properties
│ ├─RollingFileAppender\
│ │ └─log4j.properties
│ ├─stdout\
│ │ └─log4j.properties
│ └─xml_file_stdout\
│   └─log4j.xml
├─README.md
└─src\
  ├─demo\
  │ ├─file\
  │ │ └─appender\
  │ │   └─XMLFileAppenderTest.java
  │ ├─level\
  │ │ ├─SetLevelByMethod.java
  │ │ └─SetLevleByConfig.java
  │ ├─Log4jExample.java
  │ ├─logpackage\
  │ │ └─LoggerPackage.java
  │ └─method\
  │   └─LoggerMethodTest.java
  └─log4j.properties

源代码

https://github.com/lanlan2017/Log4jDemo

日志输出到文件

Log4j.properties

下面是为我们的例子创建的一个简单配置文件,让我们再来复习一遍:

  • 定义根日志级别为DEBUG,并将名为FILEappender添加其上。
  • appender FILE定义为org.apache.log4j.FileAppender,它将日志写入log目录下一个名为log.out的文件中。
  • layout被定义为%m%n,即先打印日志信息,然后打印换行。

Log4j.properties文件的内容如下:

/Log4jDemo/Log4jConfig/file/log4j.properties
1
2
3
4
5
6
7
8
9
10
11
12
13
## 定义变量,保存日志文件所在的目录
log = E:/workspacne_JDK8Tomcat8.5/Log4jDemo
## Define the root logger with appender file
log4j.rootLogger = DEBUG, FILE

## Define the file appender
log4j.appender.FILE=org.apache.log4j.FileAppender
## 设置日志文件路径
log4j.appender.FILE.File=${log}/log.out

## Define the layout for file appender
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.conversionPattern=%m%n

Log4jExample.java

/Log4jDemo/src/demo/Log4jExample.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package demo;

import java.io.IOException;
import java.sql.SQLException;
import org.apache.log4j.Logger;

public class Log4jExample
{
/* Get actual class name to be printed on */
static Logger log = Logger.getLogger(Log4jExample.class.getName());

public static void main(String[] args) throws IOException, SQLException
{
log.debug("Hello this is a debug message");
log.info("Hello this is an info message");
}
}

运行效果

复制文件Log4jConfig/file/log4j.properties,粘贴到src目录下,然后运行Log4jExample.java程序,此时项目根目录下,会生成一个log.out文件:

展开/折叠
E:\workspacne_JDK8Tomcat8.5\Log4jDemo
├─lib\
│ ├─commons-logging-1.2.jar
│ ├─log4j-1.2.17.jar
│ ├─log4j-api-2.13.3.jar
│ └─log4j-core-2.13.3.jar
├─log.out
├─Log4jConfig\
│ ├─file\
│ │ └─log4j.properties
│ ├─file_and_stout\
│ │ └─log4j.properties
│ ├─grammar\
│ │ └─log4j.properties
│ ├─Level\
│ │ └─log4j.properties
│ └─stdout\
│   └─log4j.properties
└─src\
  ├─demo\
  │ ├─level\
  │ │ ├─SetLevelByMethod.java
  │ │ └─SetLevleByConfig.java
  │ ├─Log4jExample.java
  │ └─method\
  │   └─LoggerMethodTest.java
  └─log4j.properties

打开这个log.out文件,可以看到如下内容

/Log4jDemo/log.out
1
2
3
Hello this is a debug message
Hello this is an info message

日志输出到控制台

log4j.properties

/Log4jDemo/Log4jConfig/stdout/log4j.properties
1
2
3
4
5
6
7
8
9
# Root logger option
#log4j.rootLogger=INFO, STDOUT
log4j.rootLogger=DEBUG, STDOUT

# Direct log messages to STDOUT
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{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

替换log4j配置文件 重新运行

复制文件/Log4jDemo/Log4jConfig/stdout/log4j.properties,粘贴到src目录下,然后运行Log4jExample.java.此时日志将会输出在控制台.

1
2
3
2020-08-03 17:34:14 DEBUG Log4jExample:14 - Hello this is a debug message
2020-08-03 17:34:14 INFO Log4jExample:15 - Hello this is an info message

日志同时输出到文件和控制台

log4j.properties

/Log4jDemo/Log4jConfig/file_and_stout/log4j.properties
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 定义变量,保存日志文件所在的目录
log = E:/workspacne_JDK8Tomcat8.5/Log4jDemo
# Define the root logger with appender file and stdout
log4j.rootLogger = DEBUG, FILE, STDOUT

# Define the FILE appender
log4j.appender.FILE=org.apache.log4j.FileAppender
# 设置日志文件路径
log4j.appender.FILE.File=${log}/log.out
# Define the layout for file appender
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.conversionPattern=%m%n

# Define the STDOUT appender
log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender
log4j.appender.STDOUT.Target=System.out
# Define the layout for STDOUT appender
log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout
log4j.appender.STDOUT.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

复制文件/Log4jDemo/Log4jConfig/file_and_stout/log4j.properties,覆盖src目录下的log4j.properties,删除掉项目根目录下的log.out文件,然后运行Log4jExample.java
这样会重新生成log.out,并写一份日志写到该文件中:

/Log4jDemo/log.out
1
2
3
Hello this is a debug message
Hello this is an info message

另一份日志打印在控制台中:

控制台输出
1
2
3
2020-08-03 17:41:36 DEBUG Log4jExample:14 - Hello this is a debug message
2020-08-03 17:41:36 INFO Log4jExample:15 - Hello this is an info message

log4j配置

Log4j的配置包括在配置文件中:

  1. 指定Level
  2. 定义Appender
  3. 指明Layout

Log4j.properties文件是Log4j的配置文件,属性以键值对的形式定义。默认情况下,LogManager会在CLASSPATH中寻找Log4j.properties文件。

  • 根日志的级别定义为DEBUG,并将名为XXXappender添加其上。
  • 将名为XXXappender设置为合法的appender
  • 设置XXX这个appenderlayout

Log4j.properties的语法

appender XXXXX定义的Log4j.properties的语法如下:

# Define the root logger with appender XXX
log4j.rootLogger = DEBUG, XXX

# Set the appender named XXX to be a File appender
log4j.appender.XXX=org.apache.log4j.FileAppender

# Define the layout for XXX appender
log4j.appender.XXX.layout=org.apache.log4j.PatternLayout
log4j.appender.XXX.layout.conversionPattern=%m%n

Log4j.properties示例

使用上述语法,我们在Log4j.properties定义如下属性:

  • 定义根日志级别为DEBUG,并将名为FILEappender添加在其上。
  • appender FILE定义为org.apache.log4j.FileAppender,它将日志写入log目录下一个名为log.out的文件中。
  • layout被定义为%m%n,其中%m表示日志信息,%n表示换行符,则%m%n表示打印出日志信息并在末尾加入换行。
Log4j.properties
1
2
3
4
5
6
7
8
9
10
11
12
&#35; 定义变量,该变量表示日志文件所在的目录
log = E:/workspacne_JDK8Tomcat8.5/Log4jDemo
&#35; Define the root logger with appender file
log4j.rootLogger = DEBUG, FILE

&#35; Define the file appender
log4j.appender.FILE=org.apache.log4j.FileAppender
log4j.appender.FILE.File=${log}/log.out

&#35; Define the layout for file appender
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.conversionPattern=%m%n

变量替换

值得注意的是,Log4j支持Unix风格的变量替换,比如${variableName}

级别

所有可能的选项如下:

  • TRACE
  • DEBUG
  • INFO
  • WARN
  • ERROR
  • FATAL
  • ALL

这些级别会在本教程的后续部分讲解。

Appender对象

Apache Log4j提供的Appender对象主要负责将日志信息打印至不同目的地,比如控制台、文件、网络套接字、NT事件日志等。

Appender对象属性

每个Appender对象都有不同的属性,这些属性决定了该对象的行为。

属性 描述
layout Appender使用Layout对象和与之关联的模式来格式化日志信息。
target 目的地可以是控制台、文件,或依赖于appender的对象。
level 级别用来控制过滤日志信息。
threshold Appender可脱离于日志级别定义一个阀值级别,Appender对象会忽略所有级别低于阀值级别的日志。
filter Filter对象可在级别基础之上分析日志信息,来决定Appender对象是否处理或忽略一条日志记录。

将Appender添加到Logger对象

通过在配置文件中使用如下方法,将Appender对象添加至Logger对象:

1
log4j.logger.[logger-name]=level, appender1,appender2...appendern

也可以在XML中定义同样的配置:

1
2
3
4
<logger name="com.apress.logging.Log4j" additivity="false">
<appender-ref ref="appender1"/>
<appender-ref ref="appender2"/>
</logger>

在程序中为Logger对象添加Appender对象

如果想在程序中添加Appender对象,可使用如下方法:

1
public void addAppender(Appender appender);

addAppender()方法为Logger对象增加一个Appender。如示例配置展示的那样,可以通过逗号分隔的列表,为logger添加多个Appender,将日志信息打印到不同的目的地。

所有可用的Appender

在上面的例子中,我们只用到了FileAppender,所有可用的appender包括:

  • AppenderSkeleton
  • AsyncAppender
  • ConsoleAppender
  • DailyRollingFileAppender
  • ExternallyRolledFileAppender
  • FileAppender
  • JDBCAppender
  • JMSAppender
  • LF5Appender
  • NTEventLogAppender
  • NullAppender
  • RollingFileAppender
  • SMTPAppender
  • SocketAppender
  • SocketHubAppender
  • SyslogAppender
  • TelnetAppender
  • WriterAppender

我们将在使用文件记录日志一章讲解FileAppender,在使用数据库记录日志一章讲解JDBCAppender

Layout对象

我们已经在appender中使用了PatternLayoutlayout对象的所有选项包括:

  • DateLayout
  • HTMLLayout
  • PatternLayout
  • SimpleLayout
  • XMLLayout

使用HTMLLayoutXMLLayout,可以生成HTMLXML格式的日志。

日志格式化
您将在日志格式一章学习如何格式化日志信息。

log4j架构

Log4j采用分层架构

Log4j API采用分层架构,每一层有不同的对象,完成不同的任务。这种分层架构让设计变得灵活,且易于日后扩展。

Log4j框架组件图

下图展示了Log4j框架中的组件:
图片

Log4j对象分类

Log4j里有两种类型的对象:

  • 核心对象:这是框架必需的对象,使用框架时必需用到它们。
  • 支持对象:这是框架的可选对象,它们支持核心对象做一些额外的,但并不重要的任务。

核心对象

核心对象包括如下几种类型:

Logger对象

最上一层是Logger对象,该对象负责获取日志信息,并存储于一个分层的命名空间之中。

Layout对象

Layout层提供了用于以各种风格格式化日志信息的对象,在发布日志信息之前,它为appender对象提供支持。
Layout对象对于发布日志信息非常重要,它使日志变得可读、可复用。

Appender对象

该对象位于分层架构中的较低一层,Appender对象负责将日志信息发布到不同目的地,比如:

  • 数据库、
  • 文件、
  • 控制台、
  • Unix Syslog等。

支持对象

Log4j 中还有其他一些对象,同样在框架中发挥着重要作用。

Level对象

Level对象定义了日志信息的粒度和优先级。API定义了七种级别:

序号 级别 描述
8 OFF 最高级别,用于关闭日志。
7 FATAL 指明非常严重的错误事件,可能会导致应用终止执行。
6 ERROR 指明错误事件,但应用可能还能继续运行。
5 WARN 指明潜在的有害状况。
4 INFO 指明描述信息,从粗粒度上描述了应用运行过程。
3 DEBUG 指明细致的事件信息,对调试应用最有用。
2 TRACE DEBUG级别的粒度更细。
1 ALL 所有级别,包括定制级别。

Filter对象

Filter对象用来分析日志信息,进而决定该条日志是否被记录。

一个Appender对象可对应多个Filter对象,当日志信息传给Appender对象时,与其关联的所有Filter对象需要判断是否将日志信息发布到目的地。

ObjectRenderer对象

ObjectRenderer对象负责为传入日志框架的不同对象提供字符串形式的表示,Layout对象使用该对象来准备最终的日志信息。

LogManager对象

LogManager对象管理日志框架,它负责从系统级的配置文件或类中读取初始配置参数。

使用下载好的lib

下载lib,然后添加到build path.

Maven依赖

到项目文件夹并找到pom.xml,添加以下依赖关系:

pom.xml
1
2
3
4
5
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>

省略….

参考资料

https://www.w3cschool.cn/java/log4j-installation.html
https://wiki.jikexueyuan.com/project/log4j/installation.html