本篇文章中涉及到的所有代码都已经上传到gitee中: gitee.com/sss123a/log...
上一篇
log4j组件
在Log4j中,主要由三个重要组件构成:
- Logger:负责捕捉日志记录信息;
- Appender:负责把格式好的日志信息输出到指定地方,可以是控制台、磁盘文件等;
- Layout:负责发布不同风格的日志信息;
Logger
负责处理日志记录。实例的命名就是类的全限定名。Logger 的名字大小写敏感。其命名有继承机制。如:org.apache.commons 的 logger 会继承 org.apache 的 logger。
Log4j 中,有一个特殊的 logger,叫 root,它是所有的 logger 的根。root logger 可以通过 Logger.getRootLogger() 方法获取。
Level
日记记录的优先级priority,优先级由高到低分为
OFF , FATAL , ERROR , WARN , INFO , DEBUG , ALL。
log4j建议使用FATAL ,ERROR ,WARN ,INFO ,DEBUG这五个级别。
- OFF 为最高等级 关闭了日志信息
- FATAL 为可能导致应用中止的严重事件错误
- ERROR 为严重错误 主要是程序的错误
- WARN 为一般警告,比如session丢失
- INFO 为一般要显示的信息,比如登录登出
- DEBUG 为程序的调试信息
- TRACE 为比DEBUG更细粒度的事件信息
- ALL 为最低等级,将打开所有级别的日志
Log4j
默认级别是 debug
,只要日志级别高于 debug
,都会输出
每个Logger可关联多个Appender,Appender作为日志输出的目的地处理器,对应于JUL的Handler,可以输出到如控制台,文件,网络等地方,其关联了对应的Layout,用于格式化日志输出。
Appender(配置日志信息输出位置),同jul中的Handler
- ConsoleAppender: 日志输出到控制台;
- FileAppender:输出到文件
- RollingFileAppender:输出到文件,文件达到一定阈值时,自动备份日志文件
- DailyRollingFileAppender:可定期备份日志文件,默认一天一个文件,也可设置为每分钟一个、每小时一个
- WriterAppender:可自定义日志输出位置。
这里的测试DEMO都是以xml配置文件为基础的,如果不清楚的可以详见我之前的文章: juejin.cn/post/734761...
FileAppender
将日志保存到一个文件中,不支持日志备份,可能会导致这个日志文件越来越庞大,所以这个appender使用很少
java
package com.matio.log4j.appender;
import org.apache.log4j.Logger;
import org.apache.log4j.helpers.Loader;
import org.apache.log4j.xml.DOMConfigurator;
public class FileAppenderTest {
public static void main(String[] args) {
// 加载resources/log4j-fileappender.xml文件
DOMConfigurator.configure(Loader.getResource("log4j-fileappender.xml"));
Logger logger = Logger.getLogger("fff");
logger.info("测试info");
}
}
log4j-fileappender.xml文件如下:
xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration debug="false" xmlns:log4j='http://jakarta.apache.org/log4j/'>
<logger name="fff" additivity="false">
<appender-ref ref="xxx"/>
<level value="info"/>
</logger>
<!-- FileAppender:将日志保存到一个文件中 -->
<appender name="xxx" class="org.apache.log4j.FileAppender">
<!-- file:日志文件 -->
<param name="file" value="D:/test/bis-file.log"/>
<!-- append:是否以追加的方式记录日志,默认true -->
<param name="append" value="true"/>
<!-- bufferedIO:是否启用缓冲区,这时日志并不会立即刷新到文件中,可能会存在延迟或程序停止后丢失(因为日志还在缓冲区中),默认false -->
<param name="bufferedIO" value="false"/>
<!-- bufferedIO:当bufferedIO=true时有效,指定缓冲区的大小,默认8k -->
<param name="bufferSize" value="1024"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{dd HH:mm:ss,SSS\} %-5p] [%t] %c{2\} - %m%n"/>
</layout>
<!-- threshold:日志级别 -->
<param name="threshold" value="debug"/>
<!-- encoding:文件内容编码 -->
<param name="encoding" value="UTF-8"/>
<!-- errorHandler:输出日志时如果出现异常就交给该handler处理 -->
<errorHandler class="org.apache.log4j.helpers.OnlyOnceErrorHandler"/>
<!-- immediateFlush:每来一条日志就刷新到文件中-->
<param name="immediateFlush" value="true"/>
</appender>
</log4j:configuration>
DailyRollingFileAppender
按照指定频率对日志文件进行备份,默认每天备份一次
java
package com.matio.log4j.appender;
import org.apache.log4j.Logger;
import org.apache.log4j.helpers.Loader;
import org.apache.log4j.xml.DOMConfigurator;
import java.util.Random;
public class DailyRollingFileAppenderTest {
public static void main(String[] args) throws InterruptedException {
// 加载resources/log4j-dailyrollingfileappender.xml文件
DOMConfigurator.configure(Loader.getResource("log4j-dailyrollingfileappender.xml"));
Logger logger = Logger.getLogger("aaa");
int index = 0;
while (true) {
logger.info("test" + (++index));
Thread.sleep(new Random().nextInt(1000));
}
}
}
log4j-dailyrollingfileappender.xml文件如下:
xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration debug="false" xmlns:log4j='http://jakarta.apache.org/log4j/'>
<logger name="aaa" additivity="false">
<appender-ref ref="xxx"/>
<level value="info"/>
</logger>
<!-- DailyRollingFileAppender:按照指定频率对日志文件进行备份,默认每天备份一次 -->
<appender name="xxx" class="org.apache.log4j.DailyRollingFileAppender">
<!-- file:日志文件 -->
<param name="file" value="D:/test/bis.log"/>
<!-- datePattern:按照什么频率来滚动日志
'.'yyyy-MM 对应monthly(每月)
'.'yyyy-ww 对应weekly(每周)
'.'yyyy-MM-dd 对应daily(每天) 默认
'.'yyyy-MM-dd-a 对应half-daily(每半天)
'.'yyyy-MM-dd-HH 对应hourly(每小时)
'.'yyyy-MM-dd-HH-mm 对应minutely(每分钟)
-->
<param name="datePattern" value="'.'yyyy-MM-dd-HH-mm"/>
<!-- append:是否以追加的方式记录日志,默认true -->
<param name="append" value="true"/>
<!-- bufferedIO:是否启用缓冲区,这时日志并不会立即刷新到文件中,可能会存在延迟或程序停止后丢失(因为日志还在缓冲区中),默认false -->
<param name="bufferedIO" value="false"/>
<!-- bufferedIO:当bufferedIO=true时有效,指定缓冲区的大小,默认8k -->
<param name="bufferSize" value="1024"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{dd HH:mm:ss,SSS\} %-5p] [%t] %c{2\} - %m%n"/>
</layout>
<!-- threshold:日志级别 -->
<param name="threshold" value="debug"/>
<!-- encoding:文件内容编码 -->
<param name="encoding" value="UTF-8"/>
<!-- errorHandler:输出日志时如果出现异常就交给该handler处理 -->
<errorHandler class="org.apache.log4j.helpers.OnlyOnceErrorHandler"/>
<!-- immediateFlush:每来一条日志就刷新到文件中-->
<param name="immediateFlush" value="true"/>
</appender>
</log4j:configuration>
RollingFileAppender
在日志文件达到一定大小时对其进行备份
java
package com.matio.log4j.appender;
import org.apache.log4j.Logger;
import org.apache.log4j.helpers.Loader;
import org.apache.log4j.xml.DOMConfigurator;
import java.util.Random;
public class RollingFileAppenderTest {
public static void main(String[] args) throws InterruptedException {
// 加载resources/log4j-rollingfileappender.xml文件
DOMConfigurator.configure(Loader.getResource("log4j-rollingfileappender.xml"));
Logger logger = Logger.getLogger("aaa");
int index = 0;
while (true) {
logger.info("test" + (++index));
Thread.sleep(new Random().nextInt(1000));
}
}
}
log4j-rollingfileappender.xml文件如下:
xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration debug="false" xmlns:log4j='http://jakarta.apache.org/log4j/'>
<logger name="aaa" additivity="false">
<appender-ref ref="xxx"/>
<level value="info"/>
</logger>
<!-- RollingFileAppender:在日志文件达到一定大小时对其进行备份 -->
<appender name="xxx" class="org.apache.log4j.RollingFileAppender">
<!-- maxBackupIndex:最多允许存在多少个备份,默认1个 -->
<param name="maxBackupIndex" value="2"/>
<!-- maxFileSize:当日志文件超过阈值后备份,默认阈值为10M -->
<param name="maxFileSize" value="1024"/>
<!-- file:日志文件位置 -->
<param name="file" value="D:/test/bis-rolling.log"/>
<!-- append:是否以追加的方式记录日志,默认true -->
<param name="append" value="true"/>
<!-- bufferedIO:是否启用缓冲区,这时日志并不会立即刷新到文件中,可以会存在延迟或程序停止后丢失(因为日志还在缓冲区中),默认false -->
<param name="bufferedIO" value="false"/>
<!-- bufferedIO:当bufferedIO=true时有效,指定缓冲区的大小,默认8k -->
<param name="bufferSize" value="1024"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{dd HH:mm:ss,SSS\} %-5p] [%t] %c{2\} - %m%n"/>
</layout>
<!-- threshold:日志级别 -->
<param name="threshold" value="debug"/>
<!-- encoding:文件内容编码 -->
<param name="encoding" value="UTF-8"/>
<!-- errorHandler:输出日志时如果出现异常就交给该handler处理 -->
<errorHandler class="org.apache.log4j.helpers.OnlyOnceErrorHandler"/>
<!-- immediateFlush:每来一条日志就刷新到文件中-->
<param name="immediateFlush" value="true"/>
</appender>
</log4j:configuration>
ConsoleAppender
输出日志到console
java
package com.matio.log4j.appender;
import org.apache.log4j.Logger;
import org.apache.log4j.helpers.Loader;
import org.apache.log4j.xml.DOMConfigurator;
import java.util.Random;
public class ConsoleAppenderTest {
public static void main(String[] args) throws InterruptedException {
// 加载resources/log4j-consoleappender.xml文件
DOMConfigurator.configure(Loader.getResource("log4j-consoleappender.xml"));
Logger logger = Logger.getLogger("aaa");
int index = 0;
while (true) {
logger.info("test" + (++index));
Thread.sleep(new Random().nextInt(1000));
}
}
}
log4j-consoleappender.xml文件如下:
xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration debug="false" xmlns:log4j='http://jakarta.apache.org/log4j/'>
<logger name="aaa" additivity="false">
<appender-ref ref="consoleAppender1"/>
</logger>
<!-- consoleAppender:日志输出到console上 -->
<appender name="consoleAppender1" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{dd HH:mm:ss,SSS\} %-5p] [%t] %c{2\} - %m%n"/>
</layout>
<!-- 设置该appender的threshold -->
<param name="threshold" value="info"/>
<!-- immediateFlush:默认true
如果为true,则appender将在每次输出日志时进行刷新;
如果为false,那么底层流可以将写入物理介质的时间推迟到以后,避免在每次追加结束时执行刷新操作,可以获得10%到20%的性能增益。
然而,跳过flush会带来安全方面的权衡。事实上,当跳过flush时,当应用程序退出时,最后几个日志事件很可能不会记录在磁盘上。
-->
<param name="immediateFlush" value="true"/>
<!-- encoding:内容编码 -->
<param name="encoding" value="UTF-8"/>
<!-- param:System.out(默认)或者System.err-->
<param name="target" value="System.out"/>
<!-- follow:确定该appender是否接受在配置后重新分配的System.out或System.err -->
<param name="follow" value="true"/>
</appender>
</log4j:configuration>
ExternallyRolledFileAppender
启动一个serversocket监听指定port,当收到RollOver命令后才会备份日志
java
package com.matio.log4j.appender;
import org.apache.log4j.Logger;
import org.apache.log4j.helpers.Loader;
import org.apache.log4j.varia.ExternallyRolledFileAppender;
import org.apache.log4j.xml.DOMConfigurator;
import java.io.*;
import java.net.Socket;
import java.util.Random;
public class ExternallyRolledFileAppenderTest {
public static void main(String[] args) {
// 每隔5s备份一次日志
new Thread(() -> {
while (true) {
try {
// 5s后启动一个socket客户端发送RollOver命令
Thread.sleep(5000);
connect();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
// 加载resources/log4j-externallyrolledfileappender.xml文件
DOMConfigurator.configure(Loader.getResource("log4j-externallyrolledfileappender.xml"));
Logger logger = Logger.getLogger("aaa");
int index = 0;
while (true) {
logger.info("test" + (++index));
try {
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// 启动一个socket客户端发送RollOver命令
private static void connect() throws IOException {
Socket socket = new Socket("localhost", 55555);
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
// 发生备份命令
dos.writeUTF(ExternallyRolledFileAppender.ROLL_OVER);
dos.flush();
System.out.println("Send: " + ExternallyRolledFileAppender.ROLL_OVER);
// 接收响应
DataInputStream dis = new DataInputStream(socket.getInputStream());
String respone = dis.readUTF();
System.out.println("Received: " + respone);
dos.close();
dis.close();
}
}
log4j-externallyrolledfileappender.xml文件如下:
xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration debug="false" xmlns:log4j='http://jakarta.apache.org/log4j/'>
<logger name="aaa" additivity="false">
<appender-ref ref="xxx"/>
<level value="info"/>
</logger>
<!-- ExternallyRolledFileAppender:启动一个serversocket监听指定port,当收到RollOver命令后才会备份日志 -->
<appender name="xxx" class="org.apache.log4j.varia.ExternallyRolledFileAppender">
<!-- port:启动serversocket监听该端口 -->
<param name="port" value="55555"/>
<!-- maxBackupIndex:最多允许存在多少个备份,默认1个 -->
<param name="maxBackupIndex" value="3"/>
<!-- maxFileSize:当日志文件超过阈值后备份,默认阈值为10M -->
<param name="maxFileSize" value="1024"/>
<!-- file:日志文件位置 -->
<param name="file" value="D:/test/bis-ext.log"/>
<!-- append:是否以追加的方式记录日志,默认true -->
<param name="append" value="true"/>
<!-- bufferedIO:是否启用缓冲区,这时日志并不会立即刷新到文件中,可能会存在延迟或程序停止后丢失(因为日志还在缓冲区中),默认false -->
<param name="bufferedIO" value="false"/>
<!-- bufferedIO:当bufferedIO=true时有效,指定缓冲区的大小,默认8k -->
<param name="bufferSize" value="1024"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{dd HH:mm:ss,SSS\} %-5p] [%t] %c{2\} - %m%n"/>
</layout>
<!-- threshold:日志级别 -->
<param name="threshold" value="debug"/>
<!-- encoding:文件内容编码 -->
<param name="encoding" value="UTF-8"/>
<!-- errorHandler:输出日志时如果出现异常就交给该handler处理 -->
<errorHandler class="org.apache.log4j.helpers.OnlyOnceErrorHandler"/>
<!-- immediateFlush:默认true
如果为true,则appender将在每次输出日志时进行刷新;
如果为false,那么底层流可以将写入物理介质的时间推迟到以后,避免在每次追加结束时执行刷新操作,可以获得10%到20%的性能增益。
然而,跳过flush会带来安全方面的权衡。事实上,当跳过flush时,当应用程序退出时,最后几个日志事件很可能不会记录在磁盘上。
-->
<param name="immediateFlush" value="true"/>
</appender>
</log4j:configuration>
AsyncAppender
异步输出日志
该类在被实例化的时候会启动一个守护线程Dispatcher, 在该appender收到日志的时候会将这条日志优先放进缓冲区(ArrayList)中,如果这个缓冲区满了就会阻塞(可配置), 然后异步线程Dispatcher去缓冲区中取出日志交给真正的appender去输出日志。所以它依赖真正输出日志的appender
java
package com.matio.log4j.appender;
import org.apache.log4j.*;
import org.apache.log4j.helpers.Loader;
import org.apache.log4j.xml.DOMConfigurator;
public class AsyncAppenderTest {
public static void main(String[] args) throws InterruptedException {
// testAsyncAppender();
readXmlConfig();
}
private static void readXmlConfig() throws InterruptedException {
// 加载绝对路径下文件
// DOMConfigurator.configure("E:/WorkspaceIdea/01src/log/matio-log4j/src/main/resources/log4j-asyncappender.xml");
// 加载resources/log4j-asyncappender.xml文件
DOMConfigurator.configure(Loader.getResource("log4j-asyncappender.xml"));
Logger logger = Logger.getLogger("com.matio.log4j");
logger.info("测试INFO日志1");
logger.info("测试INFO日志2");
int index = 1;
while (true) {
logger.info("测试INFO日志" + (index++));
Thread.sleep(100);
if (index >= 100) {
break;
}
}
}
private static void testAsyncAppender() {
// LogLog.setQuietMode(false);
// LogLog.setInternalDebugging(true);
Logger logger = Logger.getLogger("test");
AsyncAppender asyncAppender = new AsyncAppender();
asyncAppender.setThreshold(Level.DEBUG);
ConsoleAppender consoleAppender1 = new ConsoleAppender(new PatternLayout(), "System.out");
consoleAppender1.setName("consoleAppender1");
consoleAppender1.setThreshold(Level.INFO);
consoleAppender1.setEncoding("UTF-8");
consoleAppender1.setImmediateFlush(true);
asyncAppender.addAppender(consoleAppender1);
logger.addAppender(asyncAppender);
logger.debug("debug");
logger.warn("warn");
logger.info("info");
logger.error("error");
}
}
log4j-asyncappender.xml文件如下:
xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration debug="false" xmlns:log4j='http://jakarta.apache.org/log4j/'>
<logger name="com.matio.log4j" additivity="false">
<appender-ref ref="asyncAppender1"/>
</logger>
<!-- AsyncAppender:该类在被实例化的时候会启动一个守护线程Dispatcher,
在该appender收到日志的时候会将这条日志优先放进缓冲区(ArrayList)中,如果这个缓冲区满了就会阻塞(可配置),
然后异步线程Dispatcher去缓冲区中取出日志交给真正的appender去输出日志。所以它依赖真正输出日志的appender
-->
<appender name="asyncAppender1" class="org.apache.log4j.AsyncAppender">
<!-- AsyncAppender其实他只负责将日志保存到缓冲区中,
再由异步线程去缓冲区中取出日志交给真正的appender去输出日志
-->
<appender-ref ref="consoleAppender1"/>
<!-- blocking:默认true,
如果为true,当缓冲区满了的时候,是否会阻塞
如果为false,在缓冲区满的时候会将日志放到一个map中,步线程Dispatcher也会去这个map中取出日志
-->
<param name="blocking" value="true"/>
<!-- bufferSize:缓冲区能存放的最大日志数,默认128
如果缓冲区满了,看看blocking解释
如果bufferSize<=0,记录日志的时候就不会先将日志存放到缓冲区,而是直接把日志交给它依赖的appender去处理,相当于关闭异步功能
-->
<param name="bufferSize" value="128"/>
<!-- locationInfo:如果true,可以通过LoggingEvent捕获请求调用的位置,默认false -->
<param name="locationInfo" value="false"/>
</appender>
<!-- consoleAppender:必须要设置layout -->
<appender name="consoleAppender1" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{dd HH:mm:ss,SSS\} %-5p] [%t] %c{2\} - %m%n"/>
</layout>
<!-- 设置该appender的日志级别 -->
<param name="threshold" value="info"/>
<!-- immediateFlush:默认true
如果为true,则appender将在每次输出日志时进行刷新;
如果为false,那么底层流可以将写入物理介质的时间推迟到以后,避免在每次追加结束时执行刷新操作,可以获得10%到20%的性能增益。
然而,跳过flush会带来安全方面的权衡。事实上,当跳过flush时,当应用程序退出时,最后几个日志事件很可能不会记录在磁盘上。
-->
<param name="immediateFlush" value="true"/>
<param name="encoding" value="UTF-8"/>
<!-- param:System.out(默认)或者System.err-->
<param name="target" value="System.out"/>
<!-- follow:确定该appender是否接受在配置后重新分配的System.out或System.err -->
<param name="follow" value="true"/>
</appender>
</log4j:configuration>
JDBCAppender
将日志保存到db中
java
package com.matio.log4j.appender;
import org.apache.log4j.Logger;
import org.apache.log4j.helpers.Loader;
import org.apache.log4j.jdbc.JDBCAppender;
import org.apache.log4j.xml.DOMConfigurator;
public class JDBCAppenderTest {
public static void main(String[] args) {
// test();
readXmlConfig();
}
private static void readXmlConfig() {
// 加载resources/log4j-jdbcappender.xml文件
DOMConfigurator.configure(Loader.getResource("log4j-jdbcappender.xml"));
Logger logger = Logger.getLogger("com.matio.log4j.jdbcappender");
logger.info("测试info");
// 因为我们在xml文件设置缓冲区大小为128,所以需要我们手动刷新缓冲区中的数据保存到db中
JDBCAppender jdbcAppender1 = (JDBCAppender) logger.getAppender("jdbcAppender1");
jdbcAppender1.close();
}
private static void test() {
JDBCAppender jdbcAppender = new JDBCAppender();
jdbcAppender.setDriver("com.mysql.cj.jdbc.Driver");
jdbcAppender.setURL("jdbc:mysql://192.168.30.13:3306/things_test?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B0");
jdbcAppender.setUser("shuncom");
jdbcAppender.setPassword("sh_clighting");
jdbcAppender.setBufferSize(100); // 当日志数达到100条时再执行flushBuffer(),否则日志都会存储在一个ArrayList中
// 将日志保存到test_log4j表中
jdbcAppender.setSql("insert into test_log4j(log) values('%m');");
jdbcAppender.setLocationInfo(false);
Logger logger = Logger.getLogger(JDBCAppenderTest.class);
logger.setAdditivity(false);
logger.addAppender(jdbcAppender);
logger.info("你好2");
jdbcAppender.flushBuffer();
}
}
log4j-jdbcappender.xml文件如下:
xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration debug="false" xmlns:log4j='http://jakarta.apache.org/log4j/'>
<logger name="com.matio.log4j.jdbcappender" additivity="false">
<appender-ref ref="jdbcAppender1"/>
</logger>
<!-- jdbcAppender:可以将日志保存到db中 -->
<appender name="jdbcAppender1" class="org.apache.log4j.jdbc.JDBCAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{dd HH:mm:ss,SSS\} %-5p] [%t] %c{2\} - %m%n"/>
</layout>
<param name="driver" value="com.mysql.cj.jdbc.Driver"/>
<param name="URL" value="jdbc:mysql://192.168.30.13:3306/things_test?useSSL=false&useUnicode=true&characterEncoding=UTF-8"/>
<param name="user" value="shuncom"/>
<param name="password" value="sh_clighting"/>
<!-- sql:当缓冲区满后调用flushBuffer()去执行这个sql -->
<param name="sql" value="insert into test_log4j(log) values('%m');"/>
<!-- bufferSize:当缓冲区日志条数达到bufferSize时再执行flushBuffer(),否则日志都会存储在这个缓冲区中。默认为1 -->
<param name="bufferSize" value="128"/>
<!-- locationInfo:捕获日志记录请求调用的位置,默认false -->
<param name="locationInfo" value="true"/>
<!-- threshold:设置该appender的level -->
<param name="threshold" value="info"/>
<!-- errorHandler:默认是OnlyOnceErrorHandler-->
<errorHandler class="org.apache.log4j.helpers.OnlyOnceErrorHandler"/>
<!-- filter:一个appender中可以关联多个filter,它们以单向链表的形式存在-->
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<!-- levelMin:最低级别,默认无下限-->
<param name="levelMin" value="debug"/>
<!-- levelMax:最高级别,默认无上限-->
<param name="levelMax" value="warn"/>
<!-- acceptOnMatch:默认false
如果true:必须立即记录日志事件,而无需咨询链表中后续的过滤器(如果有的话)。
如果为false:事件对此筛选器是可以的;交给后续的filter过滤
-->
<param name="acceptOnMatch" value="true"/>
</filter>
</appender>
</log4j:configuration>
其他Appender
其他appender的DEMO也已经上传到gitee上,附上链接:gitee.com/sss123a/log...
Layout(布局)
配置日志信息的格式 (常用格式:org.apache.log4j.PatternLayOut)
org.apache.log4j.HTMLLayout(以HTML表格形式布局) org.apache.log4j.PatternLayout(可以灵活地指定布局模式), org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串) org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
输出格式
日志信息格式中几个符号所代表的含义:
- -X号: X信息输出时左对齐;
- %p: 输出日志信息优先级,即DEBUG,INFO,WARN,ERROR,FATAL,
- %d: 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921
- %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"输出日志信息换行
可以在%与模式字符之间加上修饰符来控制其最小宽度、最大宽度、和文本的对齐方式。如:
- %20c:指定输出category的名称,最小的宽度是20,如果category的名称小于20的话,默认的情况下右对齐。
- %-20c: 指定输出category的名称,最小的宽度是20,如果category的名称小于20的话,"-"号指定左对齐。
- %.30c: 指定输出category的名称,最大的宽度是30,如果category的名称大于30的话,就会将左边多出的字符截掉,但小于30的话也不会有空格。
- %20.30c: 如果category的名称小于20就补空格,并且右对齐,如果其名称长于30字符,就从左边较远输出的字符截掉。