log4j.properties配置文件、logback-spring.xml配置文件以及log4j升级到log4j2

几种常见的日志
Log4j:是最早的日志框架,是apach旗下的,可以单独使用,也可配合日志框架JCL使用;
Log4j2:apach旗下的关于log4j的升级版;
Logback:是基于slf4j接口实现的一套日志框架组件;(Logback是由log4j创始人设计的又一个开源日志组件。)
JUL(java utillog):仿log4j实现的日志框架,是sun旗下的,(也就是在我们普遍使用的jdk中);
Commons loggin:是一套日志接口(apache);
Slf4j:也是一套日志接口;

一、log4j.properties配置文件详解

Log4j支持两种配置文件格式,一种是XML格式的文件,一种是properties(key=value)文件,其中properties格式的配置文件最为常用,其有一个固定的文件名log4j.properties,下面我们介绍使用properties文件做为配置文件的方法:
Log4j框架主要的工作内容围绕着三个功能:

  1. 产生日志信息
  2. 将日志信息输出到指定位置
  3. 调整输出样式
    而Log4j的配置文件主要就是对这三种功能的实现方式进行设置

1.配置rootLogger

rootLogger的配置方式:

log4j.rootLogger=INFO,CONSOLE, R

level是日志记录的优先级,分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者自定义的级别,默认优先级:ALL < DEBUG < INFO <WARN < ERROR < FATAL < OFF

Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的级别,可以控制到应用程序中相应级别的日志信息的开关。比如在这里定义了INFO级别,则应用程序中所有DEBUG级别的日志信息将不被打印出来

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

appenderName是日志信息输出位置,可以同时指定多个输出目的地

Appender的配置方式

log4j.appender.appenderName = Log4j提供的appender类
log4j.appender.appenderName.属性名 = 属性值

Log4j提供的appender有以下5种,分别可以将日志信息输出到5个不同的平台

Appender的配置详解

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

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:每周滚动一次文件,即每周产生一个新的文件。
当然也可以指定按月、周、天、时和分。即对应的格式如下:
1)”.”yyyy-MM: 每月
2)”.”yyyy-ww: 每周
3)”.”yyyy-MM-dd: 每天
4)”.”yyyy-MM-dd-a: 每天两次
5)”.”yyyy-MM-dd-HH: 每小时
6)”.”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:指定可以产生的滚动文件的最大数。

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

日志信息格式的配置方式:

log4j.appender.appenderName.layout = Log4j提供的layout类
log4j.appender.appenderName.layout.属性 =

日志信息格式的配置详解
Log4j提供的layout有以下几种:

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

HTMLLayout
LocationInfo=true:默认值是false,输出java文件名称和行号
Title=my app file:默认值是 Log4J Log Messages

PatternLayout
ConversionPattern=%m%n:指定怎样格式化指定的消息。
例如:
在这里插入图片描述

XMLLayout
LocationInfo=true:默认值是false,输出java文件和行号
Log4J采用类似C语言中的printf函数的打印格式格式化日志信息,打印参数如下:

og4j.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},输出类似: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”输出日志信息换行

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

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字符,就从左边交远销出的字符截掉

log4j.properties配置文件示例

### 设置###
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 = [%-5p] %d{
    
    yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
 
### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = 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
 
### 输出ERROR 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log 
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR 
log4j.appender.E.layout = org.apache.log4j.PatternLayout

##下面是配置将日志信息插入数据库,
##配置输出目标为数据库(假如要将日志在控制台输出,配置为log4j.appender. stdout =org.apache.log4j.ConsoleAppender;将日志写入文件,配置为log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender
##这样的配置在许多地方都要有,需要可查有关资料),当然你也可以自己扩展org.apache.log4j.jdbc.JDBCAppender这个类,只需要在这里配置就可以了例如我们配置我自己扩展的MyJDBCAppender,配置为#log4j.appender.db=com.neam.commons.MyJDBCAppender
#log4j.appender.datasource=org.apache.log4j.jdbc.JDBCAppender
#log4j.appender.datasource.layout=org.apache.log4j.PatternLayout
#log4j.appender.datasource.driver=com.mysql.jdbc.Driver
##定义什么级别的错误将写入到数据库中
#log4j.appender.datasource.BufferSize=1
##设置缓存大小,就是当有1条日志信息是才忘数据库插一次,我设置的数据库名和表名均为user
#
#log4j.appender.datasource.URL=jdbc:mysql://116.62.13.104:3306/countdown?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF8
#log4j.appender.datasource.user=root
#log4j.appender.datasource.password=123456
#log4j.appender.datasource.sql=INSERT INTI logs (class,method,create_time,log_level,log_line,msg) values ('%C','%M','%d{yyyy-MM-dd HH:mm:ss}','%p','%l','%m')


二、log4j.properties 文件与Spring整合

logback-spring.xml配置文件示例

application.yml配置文件

logback:
  path: /data/wxpublic/logs/
  zip.path: /data/wxpublic/logs/zip
  maxFileSize: 10MB
  maxHistory: 15
  totalSizeCap: 1000MB
  level: INFO
<?xml version="1.0" encoding="UTF-8"?>


<!-- scan:当此属性设置为true时,配置文档如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文档是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。
	当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<configuration scan="true">

	<springProperty scope="context" name="logback.path"
					source="logback.path" />
	<springProperty scope="context" name="logback.zip.path"
					source="logback.zip.path" />
	<springProperty scope="context"
					name="logback.maxFileSize" source="logback.maxFileSize" />
	<springProperty scope="context"
					name="logback.totalSizeCap" source="logback.totalSizeCap" />
	<springProperty scope="context"
					name="logback.maxHistory" source="logback.maxHistory" />
	<springProperty scope="context" name="logback.level"
					source="logback.level" />
	<!-- 控制台日志配置 --><!--1. 输出到控制台-->
	<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
		<encoder>
			<!-- 格式化 -->
			<pattern>%d{
    
    yyyy-MM-dd HH:mm:ss} [%p] [%t] %c{
    
    36} - %m%n</pattern>
			<!-- 设置字符集 -->
			<charset>UTF-8</charset>
		</encoder>
	</appender>

	<!-- info级别日志控制 --><!--2. 输出到文档-->
	<appender name="FILE_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
		<!-- 文件路径 -->
		<file>${
    
    logback.path}/info.log</file>
		<!-- 是否追加 默认为true -->
		<append>true</append>
		<!-- 滚动策略 日期+大小 策略 -->
		<rollingPolicy
				class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
			<fileNamePattern>${
    
    logback.zip.path}/%d{
    
    yyyy-MM-dd}/info/info-%i.zip</fileNamePattern>
			<!-- 单个日志大小 -->
			<maxFileSize>${
    
    logback.maxFileSize}</maxFileSize>
			<!-- 日志保存周期 -->
			<maxHistory>${
    
    logback.maxHistory}</maxHistory>
			<!-- 总大小 -->
			<totalSizeCap>${
    
    logback.totalSizeCap}</totalSizeCap>
		</rollingPolicy>
		<!-- 格式化 -->
		<encoder>
			<pattern>%d{
    
    yyyy-MM-dd HH:mm:ss} [%p] [%t] %c{
    
    36} - %m%n</pattern>
		</encoder>
		<!-- 级别过滤 -->
		<filter class="ch.qos.logback.classic.filter.LevelFilter">
			<level>INFO</level>
			<onMatch>ACCEPT</onMatch>
			<onMismatch>DENY</onMismatch>
		</filter>
	</appender>

	<!-- warn级别日志控制 -->
	<appender name="WARN_INFO"
			  class="ch.qos.logback.core.rolling.RollingFileAppender">
		<!-- 文件路径 -->
		<file>${
    
    logback.path}/warn.log</file>
		<!-- 是否追加 默认为true -->
		<append>true</append>
		<!-- 滚动策略 日期+大小 策略 -->
		<rollingPolicy
				class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
			<fileNamePattern>${
    
    logback.zip.path}/%d{
    
    yyyy-MM-dd}/warn/warn-%i.zip</fileNamePattern>
			<!-- 单个日志大小 -->
			<maxFileSize>${
    
    logback.maxFileSize}</maxFileSize>
			<!-- 日志保存周期 -->
			<maxHistory>${
    
    logback.maxHistory}</maxHistory>
			<!-- 总大小 -->
			<totalSizeCap>${
    
    logback.totalSizeCap}</totalSizeCap>
		</rollingPolicy>
		<!-- 格式化 -->
		<encoder>
			<pattern>%d{
    
    yyyy-MM-dd HH:mm:ss} [%p] [%t] %c{
    
    36} - %m%n</pattern>
		</encoder>
		<!-- 级别过滤 -->
		<filter class="ch.qos.logback.classic.filter.LevelFilter">
			<level>WARN</level>
			<onMatch>ACCEPT</onMatch>
			<onMismatch>DENY</onMismatch>
		</filter>
	</appender>

	<!-- ERROR级别日志控制 -->
	<appender name="ERROR_INFO"
			  class="ch.qos.logback.core.rolling.RollingFileAppender">
		<!-- 文件路径 -->
		<file>${
    
    logback.path}/error.log</file>
		<!-- 是否追加 默认为true -->
		<append>true</append>
		<!-- 滚动策略 日期+大小 策略 -->
		<rollingPolicy
				class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
			<fileNamePattern>${
    
    logback.zip.path}/%d{
    
    yyyy-MM-dd}/error/error-%i.zip</fileNamePattern>
			<!-- 单个日志大小 -->
			<maxFileSize>${
    
    logback.maxFileSize}</maxFileSize>
			<!-- 日志保存周期 -->
			<maxHistory>${
    
    logback.maxHistory}</maxHistory>
			<!-- 总大小 -->
			<totalSizeCap>${
    
    logback.totalSizeCap}</totalSizeCap>
		</rollingPolicy>
		<!-- 格式化 -->
		<encoder>
			<pattern>%d{
    
    yyyy-MM-dd HH:mm:ss} [%p] [%t] %c{
    
    36} - %m%n</pattern>
		</encoder>
		<!-- 级别过滤 -->
		<filter class="ch.qos.logback.classic.filter.LevelFilter">
			<level>ERROR</level>
			<onMatch>ACCEPT</onMatch>
			<onMismatch>DENY</onMismatch>
		</filter>
	</appender>

	<root level="${logback.level}">
		<appender-ref ref="CONSOLE" />
		<appender-ref ref="FILE_INFO" />
		<appender-ref ref="WARN_INFO" />
		<appender-ref ref="ERROR_INFO" />
	</root>

	
</configuration>

2.同步日志到mysql数据库

pom依赖

		<dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
     <!--引入数据库连接池-->
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>commons-pool</groupId>
            <artifactId>commons-pool</artifactId>
            <version>1.6</version>
        </dependency>

logback-spring.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>


<!-- scan:当此属性设置为true时,配置文档如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文档是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。
	当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<configuration scan="true">

	<springProperty scope="context" name="logback.path"
					source="logback.path" />
	<springProperty scope="context" name="logback.zip.path"
					source="logback.zip.path" />
	<springProperty scope="context"
					name="logback.maxFileSize" source="logback.maxFileSize" />
	<springProperty scope="context"
					name="logback.totalSizeCap" source="logback.totalSizeCap" />
	<springProperty scope="context"
					name="logback.maxHistory" source="logback.maxHistory" />
	<springProperty scope="context" name="logback.level"
					source="logback.level" />
	<!-- 控制台日志配置 --><!--1. 输出到控制台-->
	<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
		<encoder>
			<!-- 格式化 -->
			<pattern>%d{
    
    yyyy-MM-dd HH:mm:ss} [%p] [%t] %c{
    
    36} - %m%n</pattern>
			<!-- 设置字符集 -->
			<charset>UTF-8</charset>
		</encoder>
	</appender>

	<!-- info级别日志控制 --><!--2. 输出到文档-->
	<appender name="FILE_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
		<!-- 文件路径 -->
		<file>${
    
    logback.path}/info.log</file>
		<!-- 是否追加 默认为true -->
		<append>true</append>
		<!-- 滚动策略 日期+大小 策略 -->
		<rollingPolicy
				class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
			<fileNamePattern>${
    
    logback.zip.path}/%d{
    
    yyyy-MM-dd}/info/info-%i.zip</fileNamePattern>
			<!-- 单个日志大小 -->
			<maxFileSize>${
    
    logback.maxFileSize}</maxFileSize>
			<!-- 日志保存周期 -->
			<maxHistory>${
    
    logback.maxHistory}</maxHistory>
			<!-- 总大小 -->
			<totalSizeCap>${
    
    logback.totalSizeCap}</totalSizeCap>
		</rollingPolicy>
		<!-- 格式化 -->
		<encoder>
			<pattern>%d{
    
    yyyy-MM-dd HH:mm:ss} [%p] [%t] %c{
    
    36} - %m%n</pattern>
		</encoder>
		<!-- 级别过滤 -->
		<filter class="ch.qos.logback.classic.filter.LevelFilter">
			<level>INFO</level>
			<onMatch>ACCEPT</onMatch>
			<onMismatch>DENY</onMismatch>
		</filter>
	</appender>

	<!-- warn级别日志控制 -->
	<appender name="WARN_INFO"
			  class="ch.qos.logback.core.rolling.RollingFileAppender">
		<!-- 文件路径 -->
		<file>${
    
    logback.path}/warn.log</file>
		<!-- 是否追加 默认为true -->
		<append>true</append>
		<!-- 滚动策略 日期+大小 策略 -->
		<rollingPolicy
				class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
			<fileNamePattern>${
    
    logback.zip.path}/%d{
    
    yyyy-MM-dd}/warn/warn-%i.zip</fileNamePattern>
			<!-- 单个日志大小 -->
			<maxFileSize>${
    
    logback.maxFileSize}</maxFileSize>
			<!-- 日志保存周期 -->
			<maxHistory>${
    
    logback.maxHistory}</maxHistory>
			<!-- 总大小 -->
			<totalSizeCap>${
    
    logback.totalSizeCap}</totalSizeCap>
		</rollingPolicy>
		<!-- 格式化 -->
		<encoder>
			<pattern>%d{
    
    yyyy-MM-dd HH:mm:ss} [%p] [%t] %c{
    
    36} - %m%n</pattern>
		</encoder>
		<!-- 级别过滤 -->
		<filter class="ch.qos.logback.classic.filter.LevelFilter">
			<level>WARN</level>
			<onMatch>ACCEPT</onMatch>
			<onMismatch>DENY</onMismatch>
		</filter>
	</appender>

	<!-- ERROR级别日志控制 -->
	<appender name="ERROR_INFO"
			  class="ch.qos.logback.core.rolling.RollingFileAppender">
		<!-- 文件路径 -->
		<file>${
    
    logback.path}/error.log</file>
		<!-- 是否追加 默认为true -->
		<append>true</append>
		<!-- 滚动策略 日期+大小 策略 -->
		<rollingPolicy
				class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
			<fileNamePattern>${
    
    logback.zip.path}/%d{
    
    yyyy-MM-dd}/error/error-%i.zip</fileNamePattern>
			<!-- 单个日志大小 -->
			<maxFileSize>${
    
    logback.maxFileSize}</maxFileSize>
			<!-- 日志保存周期 -->
			<maxHistory>${
    
    logback.maxHistory}</maxHistory>
			<!-- 总大小 -->
			<totalSizeCap>${
    
    logback.totalSizeCap}</totalSizeCap>
		</rollingPolicy>
		<!-- 格式化 -->
		<encoder>
			<pattern>%d{
    
    yyyy-MM-dd HH:mm:ss} [%p] [%t] %c{
    
    36} - %m%n</pattern>
		</encoder>
		<!-- 级别过滤 -->
		<filter class="ch.qos.logback.classic.filter.LevelFilter">
			<level>ERROR</level>
			<onMatch>ACCEPT</onMatch>
			<onMismatch>DENY</onMismatch>
		</filter>
	</appender>


	<!-- 将日志写入数据库 -->
	<appender name="DB-CLASSIC-MYSQL-POOL" class="ch.qos.logback.classic.db.DBAppender">
		<connectionSource class="ch.qos.logback.core.db.DataSourceConnectionSource">
			<dataSource class="org.apache.commons.dbcp.BasicDataSource">
				<driverClassName>com.mysql.jdbc.Driver</driverClassName>
				<url>jdbc:mysql://116.62.13.104:3306/countdown?characterEncoding=UTF-8</url>
				<username>root</username>
				<password>123456</password>
			</dataSource>
		</connectionSource>
		<!--这里设置日志级别为error-->
		<filter class="ch.qos.logback.classic.filter.LevelFilter">
			<level>info</level>
			<onMatch>ACCEPT</onMatch>
			<onMismatch>DENY</onMismatch>
		</filter>
	</appender>

	<root level="${logback.level}">
		<appender-ref ref="CONSOLE" />
		<appender-ref ref="FILE_INFO" />
		<appender-ref ref="WARN_INFO" />
		<appender-ref ref="ERROR_INFO" />
		<appender-ref ref="DB-CLASSIC-MYSQL-POOL" />
	</root>

</configuration>

mysql建表

BEGIN;
DROP TABLE IF EXISTS logging_event_property;
DROP TABLE IF EXISTS logging_event_exception;
DROP TABLE IF EXISTS logging_event;
COMMIT;
 
BEGIN;
CREATE TABLE logging_event 
  (
    timestmp         BIGINT NOT NULL,
    formatted_message  TEXT NOT NULL,
    logger_name       VARCHAR(254) NOT NULL,
    level_string      VARCHAR(254) NOT NULL,
    thread_name       VARCHAR(254),
    reference_flag    SMALLINT,
    arg0              VARCHAR(254),
    arg1              VARCHAR(254),
    arg2              VARCHAR(254),
    arg3              VARCHAR(254),
    caller_filename   VARCHAR(254) NOT NULL,
    caller_class      VARCHAR(254) NOT NULL,
    caller_method     VARCHAR(254) NOT NULL,
    caller_line       CHAR(4) NOT NULL,
    event_id          BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY
  );
COMMIT;
 
 
BEGIN;
CREATE TABLE logging_event_property
  (
    event_id       BIGINT NOT NULL,
    mapped_key        VARCHAR(254) NOT NULL,
    mapped_value      TEXT,
    PRIMARY KEY(event_id, mapped_key),
    FOREIGN KEY (event_id) REFERENCES logging_event(event_id)
  );
COMMIT;
 
 
BEGIN;
CREATE TABLE logging_event_exception
  (
    event_id         BIGINT NOT NULL,
    i                SMALLINT NOT NULL,
    trace_line       VARCHAR(254) NOT NULL,
    PRIMARY KEY(event_id, i),
    FOREIGN KEY (event_id) REFERENCES logging_event(event_id)
  );
COMMIT;

效果

我设置了info级别 ,可以设置error级别 只打印错误日志。
在这里插入图片描述
另外 ,如果想要存入自定义表中需要重写DBAppender类

重写DBAppender类为MyDBAppender类

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

package com.me.study.springboot02mybatis.config;

import ch.qos.logback.classic.spi.CallerData;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.db.DBAppenderBase;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;

@Configuration
public class LogDBAppender extends DBAppenderBase<ILoggingEvent> {
    
    

    protected static final Method GET_GENERATED_KEYS_METHOD;
    //插入sql
    protected String insertSQL;
    // message 日志内容
    static final int MESSAGE = 1;
    // level_string
    static final int LEVEL_STRING = 2;
    // created_time 时间
    static final int CREATE_TIME = 3;
    // logger_name 全类名
    static final int LOGGER_NAME = 4;

    static final StackTraceElement EMPTY_CALLER_DATA = CallerData.naInstance();

    static {
    
    
        // PreparedStatement.getGeneratedKeys() method was added in JDK 1.4
        Method getGeneratedKeysMethod;
        try {
    
    
            // the
            getGeneratedKeysMethod = PreparedStatement.class.getMethod("getGeneratedKeys", (Class[]) null);
        } catch (Exception ex) {
    
    
            getGeneratedKeysMethod = null;
        }
        GET_GENERATED_KEYS_METHOD = getGeneratedKeysMethod;
    }

    @Override
    public void start() {
    
    
        // 将写好的sql语句赋值给insertSQL
        insertSQL = buildInsertSQL();
        super.start();
    }

    // 自己写新增sql语句
    private static String buildInsertSQL() {
    
    
        return "INSERT INTO `logging`(`message`,`level_string`,`created_time`,`logger_name`)" +
                "VALUES (?,?,?,?)";
    }

    @Override
    protected Method getGeneratedKeysMethod() {
    
    
        return GET_GENERATED_KEYS_METHOD;
    }

    @Override
    protected String getInsertSQL() {
    
    
        return insertSQL;
    }

    /**
     * 主要修改的方法
     *
     * @param stmt
     * @param event
     * @throws SQLException
     */
    private void bindLoggingEventWithInsertStatement(PreparedStatement stmt, ILoggingEvent event) throws SQLException {
    
    
        // event.getFormattedMessage() 日志打印内容
        String message = event.getFormattedMessage();
        // 如果只想存储自己打印的日志,可以这样写日志:logger.info("- XXXX")
        if(message.startsWith("-")){
    
     // 判断日志消息首字母为 - 的日志,记录到数据库表
            stmt.setString(MESSAGE, message);
            // event.getLevel().toString() 日志级别
            stmt.setString(LEVEL_STRING, event.getLevel().toString());
            // new Timestamp(event.getTimeStamp()) 时间
            stmt.setTimestamp(CREATE_TIME, new Timestamp(event.getTimeStamp()));
            // event.getLoggerName() 全类名
            stmt.setString(LOGGER_NAME, event.getLoggerName());
        }

    }

    @Override
    protected void subAppend(ILoggingEvent eventObject, Connection connection, PreparedStatement statement) throws Throwable {
    
    
        bindLoggingEventWithInsertStatement(statement, eventObject);
        // This is expensive... should we do it every time?
        int updateCount = statement.executeUpdate();
        if (updateCount != 1) {
    
    
            addWarn("Failed to insert loggingEvent");
        }
    }

    @Override
    protected void secondarySubAppend(ILoggingEvent eventObject, Connection connection, long eventId) throws Throwable {
    
    
    }
}

三、log4j升级到log4j2

1.pom依赖升级

 		 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

2.log4j2.xml配置文件

log4j采用同步输出模式,当遇到高并发&日志输出过多情况,可能导致线程阻塞,消耗时间过大
log4j无法实现自动删除按照日期产生的日志,现有项目都采用定时脚本删除日志。
log4j2采用异步输出,并且能通过配置实现自动删除日志。

配置文件节点解析:

1.根节点Configuration有两个属性:status和monitorinterval,有两个子节点:Appenders和Loggers(表明可以定义多个Appender和Logger)。

status用来指定log4j本身的打印日志的级别。monitorinterval用于指定log4j自动重新配置的监测间隔时间,单位是s,最小是5s。

2.Appenders节点,常见的有三种子节点:Console、RollingFile、File,本章中还使用了JDBC节点。
Console节点用来定义输出到控制台的Appender。
属性
name:指定Appender的名字。
target:SYSTEM_OUT 或 SYSTEM_ERR,一般只设置默认:SYSTEM_OUT。

子节点
PatternLayout:输出格式,不设置默认为:%m%n。
格式举例:<PatternLayout pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n"/>

File节点用来定义输出到指定位置的文件的Appender。
属性
name:指定Appender的名字。
fileName:指定输出日志的目的文件带全路径的文件名。

子节点
PatternLayout:输出格式,不设置默认为:%m%n。

RollingFile节点用来定义超过指定大小自动删除旧的创建新的的Appender。
属性
name:指定Appender的名字。
fileName:指定输出日志的目的文件带全路径的文件名。

filePattern:指定新建日志文件的名称格式。
子节点
PatternLayout:输出格式,不设置默认为:%m%n。
Policies:指定滚动日志的策略,就是什么时候进行新建日志文件输出日志。基于时间的触发策略。该策略主要是完成周期性的log文件封存工作。
有两个参数:interval,integer型,指定两次封存动作之间的时间间隔。单位:以日志的命名精度来确定单位,比如yyyy-MM-dd-HH 单位为小时,yyyy-MM-dd-HH-mm 单位为分钟
modulate,boolean型,说明是否对封存时间进行调制。若modulate=true,则封存时间将以0点为边界进行偏移计算。
比如,modulate=true,interval=4hours,那么假设上次封存日志的时间为03:00,则下次封存日志的时间为04:00,之后的封存时间依次为08:00,12:00,16:00
Policies的子节点
TimeBasedTriggeringPolicy:基于时间的滚动策略,interval属性用来指定多久滚动一次,默认是1 hour。modulate=true用来调整时间:比如现在是早上3am,interval是4,那么第一次滚动是在4am,接着是8am,12am…而不是7am.
SizeBasedTriggeringPolicy:基于指定文件大小的滚动策略,size属性用来定义每个日志文件的大小.
DefaultRolloverStrategy:用来指定同一个文件夹下最多有几个日志文件时开始删除最旧的,创建新的(通过max属性)。

JDBC节点用来配置日志输出到数据库
属性
name:指定Appender的名字。
tableName:日志存储表的名称。
子节点
ConnectionFactory:两个属性class:连接库的类,method:类中的连接方法。
Column:数据库表字段。 name:字段名称。pattern:写入值。isEventTimestamp:日期格式是否使用时间戳,不和pattern一起出现。

3.Loggers节点,常见的有两种:Root和Logger.
Root节点用来指定项目的根日志,如果没有单独指定Logger,那么就会默认使用该Root日志输出
level:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF.
AppenderRef:Root的子节点,用来指定该日志输出到哪个Appender.
Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。
level:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF.
name:用来指定该Logger所适用的类或者类所在的包全路径,继承自Root节点.
AppenderRef:Logger的子节点,用来指定该日志输出到哪个Appender,如果没有指定,就会默认继承自Root.如果指定了,那么会在指定的这个Appender和Root的Appender中都会输出,此时我们可以设置Logger的additivity="false"只在自定义的Appender中进行输出。

日志level级别定义:

All:最低等级的,用于打开所有日志记录.
Trace:是追踪,就是程序推进以下,你就可以写个trace输出,所以trace应该会特别多,不过没关系,我们可以设置最低日志级别不让他输出.
Debug:指出细粒度信息事件对调试应用程序是非常有帮助的.
Info:消息在粗粒度级别上突出强调应用程序的运行过程.
Warn:输出警告及warn以下级别的日志.
Error:输出错误信息日志.
Fatal:输出每个严重的错误事件将会导致应用程序的退出的日志.
OFF:最高等级的,用于关闭所有日志记录.

自定义格式:
%t:线程名称
%p:日志级别
%c:日志消息所在类名
%m:消息内容
%M:输出执行方法
%d:发生时间,%d{yyyy-MM-dd HH:mm:ss.SSS}
%x: 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。
%L:代码中的行数
%n:换行

log4j2.xml配置文件示例

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <Properties>
        <Property name="LOG_HOME">${
    
    sys:user.dir}/logs</Property>
        <Property name="LOG_FILE">@logging.file-web@</Property>
    </Properties>

    <Appenders>
        <Console name="console_appender" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} %p [%t] %C.%M(%L) | %m%n"/>
        </Console>
        <RollingFile  name="file_appender" immediateFlush="true" fileName="${LOG_HOME}/${LOG_FILE}"
                      filePattern="${LOG_HOME}/${LOG_FILE}.%d{yyyy-MM-dd}">
            <PatternLayout>
                <pattern>%d{
    
    yyyy-MM-dd HH:mm:ss.SSS} %p [%t] %C.%M(%L) | %m%n</pattern>
            </PatternLayout>
            <Policies>
                <TimeBasedTriggeringPolicy modulate="true" interval="1"/>
            </Policies>
            <DefaultRolloverStrategy max="30"/>
        </RollingFile >
    </Appenders>

    <Loggers>
        <logger name="com.ibatis.common.jdbc.SimpleDataSource" level="debug"/>
        <logger name="java.sql.Connection" level="debug"/>
        <logger name="com.ibatis" level="debug"/>
        <logger name="com.ibatis.common.jdbc.ScriptRunner" level="debug"/>
        <logger name="com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate" level="debug"/>
        <logger name="java.sql.Statement" level="debug"/>
        <logger name="java.sql.PreparedStatement" level="debug">
            <appender-ref ref="console_appender"/>
        </logger>
        <Root level="INFO">
            <appender-ref ref="console_appender"/>
            <appender-ref ref="file_appender"/>
        </Root>
    </Loggers>
</configuration>

bug

在这里插入图片描述
如果只看这两句的话我们可能会认为是我们的日志文件log4j2-dev.xml配置错了,或者路径找不到,其实不然。正解是我们pom文件配置的有问题,jar包存在冲突。
我们现在要解决jar包冲突的问题是不是需要每个包下都排除默认引用的logger日志呢,理论上是完全没有问题的,但是那样岂不是很费事,解决办法:

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

在这里插入图片描述
项目正常启动。

猜你喜欢

转载自blog.csdn.net/DreamsArchitects/article/details/109077988