log4j/Logback/SLF4j

1.概念

JUL、JCL、Jboss-logging、logback、log4j、log4j2、slf4j....等等很多,一般我们使用SLF4j作为日志的抽象层,Logback或者Log4j2作为实现类,log4j自身由于效率问题被淘汰,Logback与log4j与SLF4j是同一个人写的,springboot默认使用SLF4j+Logback

2.SLF4j

官网  https://www.slf4j.org/

依赖

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.25</version>
</dependency>

基本使用

 @Test
    public  void testLog4J(){
        Logger logger=LoggerFactory.getLogger(MvcDemoApplicationTests.class);
        logger.warn("警告");//保存日志级别warn,还有info,error,fatal,debug,与level级别一致
    }

3. SLF4j统一日志的原理

即使是别的框架也统一使用slf4j进行输出

原理:先要排除别的日志的依赖,然后使用相应的SLF4j的jar替换掉原来的jar,然后倒入相应的实现或者适配包以及实现,原理图如下

相应的SLF4j的jar有下图可知是采用偷梁换柱的方式修改了相应的日志类

排除日志包的依赖

<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<exclusions>
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				</exclusion>
			</exclusions>
</dependency>

4. spring与springboot的日志记录

SpringBoot能自动适配所有的日志(原因是假如了相应的适配包),底层使用slf4j+logback的方式记录日志,引入其他框架的时候,只需要把这个框架依赖的日志框架排除掉即可;

logback-spring.xml:添加-spring后,日志框架就不直接加载日志的配置项,而是由SpringBoot解析加载,可以使用SpringBoot的高级Profile功能,假如没有-spring,那么由logback会直接加载

spring使用自动适配所有的日志时需要的依赖

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring‐boot‐starter‐logging</artifactId>
</dependency>

 添加上述依赖后的依赖关系图

springboot的Logback文件的配置(spring-boot-1.5.17.RELEASE.jar下)

假如需要对日志配置文件进行修改见Logback

5. Logback

Logback与Log4J对比

相对Logback 执行更快,更充分的测试,原生实现了 SLF4J API(有上述可知Log4J 还需要有一个中间转换层),内容更丰富的文档,支持 XML 或者 Groovy 方式配置,配置文件自动热加载,从 IO 错误中优雅恢复,自动删除日志归档,自动压缩日志成为归档文件,支持 Prudent 模式,使多个 JVM 进程能记录同一个日志文件,支持配置文件中加入条件判断来适应不同的环境,更强大的过滤器,支持 SiftingAppender(可筛选 Appender),异常栈信息带有包信息。

Logback的日志级别

TRACE < DEBUG < INFO < WARN < ERROR

Logback配置说明

<?xml version="1.0" encoding="UTF-8"?>
<!-- scan:当该属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。 scanPeriod:设置监测配置文件是否修改的时间间隔,如果没有给出时间单位,默认单位是毫秒,默认的时间间隔为1分钟,当scan为true时,此属性生效 debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="60 seconds" debug="false"> <!-- 定义日志的根目录 --> <property name="LOG_HOME" value="/app/log" /> <!-- 定义日志文件名称 --> <property name="appName" value="SkyTest"></property>
<!-- ch.qos.logback.core.ConsoleAppender 表示控制台输出,     ch.qos.logback.core.FileAppender 输出到文件      ch.qos.logback.core.rolling.RollingFileAppender回滚 -->
<!----------------------------------------------------------------------------------> <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
   <!--编码-->   <Encoding>UTF-8</Encoding>    <!--    日志输出格式:%d表示日期时间,%thread表示线程名,%-5level:级别从左显示5个字符宽度    %logger{50} 表示logger名字最长50个字符,否则按照句点分割。 %msg:日志消息,%n是换行符    -->    <layout class="ch.qos.logback.classic.PatternLayout">   <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>   </layout> </appender> <!----------------------------------------------------------------------------------> <!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 --> <appender name="appLogAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">

   <!-- 过滤器,只记录WARN级别的日志 ,不常用-->
   <filter class="ch.qos.logback.classic.filter.LevelFilter">
       <level>ERROR</level>
       <onMatch>ACCEPT</onMatch>
       <onMismatch>DENY</onMismatch>
   </filter>
<Encoding>UTF-8</Encoding>
<!-- 指定日志文件的名称,<property> 有两个属性,name和value;其中name的值是变量的名称,value的值时变量定义的值。通过<property>定义的值会被插入到logger上下文中。 定义变量后,可以使“${}”来使用变量。 --> <file>${LOG_HOME}/${appName}.log</file>
<!--     rollingPolicy回滚策略:    TimeBasedRollingPolicy: 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动。 --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
     <!--     滚动时产生的文件的存放位置及文件名称 %d{yyyy-MM-dd}:按天进行日志滚动     %i:当文件大小超过maxFileSize时,按照i进行文件滚动       -->      <fileNamePattern>${LOG_HOME}/${appName}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>      <!--       可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件。假设设置每天滚动,      且maxHistory是365,则只保存最近365天的文件,删除之前的旧文件。注意,删除旧文件是,      那些为了归档而创建的目录也会被删除。      -->     <MaxHistory>365</MaxHistory>
        <!--      当日志文件超过maxFileSize指定的大小时,根据上面提到的%i进行日志文件滚动,注意此处配置SizeBasedTriggeringPolicy是无法实现按文件大小进行滚动的,
        必须配置timeBasedFileNamingAndTriggeringPolicy     -->
   <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">    <maxFileSize>100MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy>
<!--    日志输出格式:%d表示日期时间,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %logger{50} 表示logger名字最长50个字符,否则按照句点分割。 %msg:日志消息,%n是换行符 --> <layout class="ch.qos.logback.classic.PatternLayout"> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [ %thread ] - [ %-5level ] [ %logger{50} : %line ] - %msg%n</pattern> </layout>
</appender>

<!----------------------------------------------------------------------------------> <!-- logger主要用于存放日志对象,也可以定义日志类型、级别 name:表示匹配的logger类型前缀,也就是包的前半部分 level:要记录的日志级别,包括 TRACE < DEBUG < INFO < WARN < ERROR additivity:是否向上级loger传递打印信息。默认是true。<loger>可以包含零个或多个<appender-ref>元素,标识这个appender将会添加到这个logger。 --> <!-- hibernate logger --> <logger name="org.hibernate" level="error" />
<!-- Spring framework logger --> <logger name="org.springframework" level="error" additivity="false"></logger> <logger name="com.creditease" level="info" additivity="true"> <appender-ref ref="appLogAppender" /> </logger> <!-- root与logger是父子关系,没有特别定义则默认为root,任何一个类只会和一个logger对应,有匹配的logger则为logger,没有则为默认的root --> <root level="info"> <appender-ref ref="stdout" /><!--stdouty与appender的name保持一致--> <appender-ref ref="appLogAppender" /> </root> <!-- show parameters for hibernate sql 专为 Hibernate 定制 --> <logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE" /> <logger name="org.hibernate.type.descriptor.sql.BasicExtractor" level="DEBUG" /> <logger name="org.hibernate.SQL" level="DEBUG" /> <logger name="org.hibernate.engine.QueryParameters" level="DEBUG" /> <logger name="org.hibernate.engine.query.HQLQueryPlan" level="DEBUG" /> <!--日志异步到数据库 --> <appender name="DB" class="ch.qos.logback.classic.db.DBAppender"> <!--日志异步到数据库 --> <connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource"> <!--连接池 --> <dataSource class="com.mchange.v2.c3p0.ComboPooledDataSource"> <driverClass>com.mysql.jdbc.Driver</driverClass> <url>jdbc:mysql://127.0.0.1:3306/databaseName</url> <user>root</user> <password>root</password> </dataSource> </connectionSource> </appender> </configuration>
<!--
  <encoder>:对日志进行格式化。//都有
  <target>:字符串 System.out 或者 System.err ,默认 System.out //控制台
  <file>:被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建,没有默认值。 //文件,回滚日志
  <append>:如果是 true,日志被追加到文件结尾,如果是 false,清空现存文件,默认是true。//文件,回滚日志
  <prudent>:如果是 true,日志会被安全的写入文件,即使其他的FileAppender也在向此文件做写入操作,效率低,默认是 false。//文件,回滚日志
  <rollingPolicy>:当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名。 //回滚日志
  <triggeringPolicy >: 告知 RollingFileAppender 合适激活滚动  //回滚日志
-->

 logback-spring.xml:添加-spring后,日志框架就不直接加载日志的配置项,而是由SpringBoot解析加载,可以使用SpringBoot的高级Profile功能,假如没有-spring,那么由logback会直接加载

6.log4j的配置(LOG4J.xml放在类路径下会自动加载)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
 
<log4j:configuration>
    <!--STDOUT表示输出  org.apache.log4j.ConsoleAppender 表示输出的类,这里表示输出到控制台-->
    <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
        <!--表达式输出的字符集-->
        <param name="Encoding" value="UTF-8"/>
        <!--org.apache.log4j.PatternLayout 对象和与之相关的格式化的日志记录信息转换模式,这里表示表达式-->
        <layout class="org.apache.log4j.PatternLayout">
            <!--ConversionPattern格式 -->
            <param name="ConversionPattern" value="%-5p %d{yyyy/MM/dd HH:mm:ss,SSS} %m  %c (%F:%L) \n"/>
        </layout>
    </appender>
 
    <!--org.apache.log4j.ConsoleAppender(控制台)-->
    <!--org.apache.log4j.FileAppender(文件)-->
    <!--org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)-->
    <!--org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)-->
    <!--org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)-->
    <appender name="file" class="org.apache.log4j.FileAppender">
        <!--表达式输出的字符集-->
        <param name="Encoding" value="UTF-8"/>
        <!--Threshold=debug:指定日志消息的输出最低层次。-->
        <param name="Threshold" value="debug"/>
        <!--append:默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定的文件内容-->
        <param name="append" value="true"/>
        <!--File指定消息输出到mylog.txt文件。-->
        <param name="File" value="D:/logs/log4j.log"/>
        <!--ImmediateFlush:默认值是true,意谓着所有的消息都会被立即输出。-->
        <param name="ImmediateFlush" value="true"/>
        <!--org.apache.log4j.PatternLayout 对象和与之相关的格式化的日志记录信息转换模式,这里表示表达式-->
        <layout class="org.apache.log4j.PatternLayout">
            <!--ConversionPattern格式
            %c: 输出日志信息所属的类目,通常就是所在类的全名
            %d: 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyyy/MM/dd HH:mm:ss,SSS},
            输出类似:2018/10/06 14:16:41,429
            %p: 输出日志信息优先级,即DEBUG,INFO,WARN,ERROR,FATAL,
            %F: 输出日志消息产生时所在的文件名称
            %L: 输出代码中的行号
            "-"号指定左对齐。
            %m: 输出代码中指定的消息,产生的日志具体信息
            \n  换行
            %r: 输出自应用启动到输出该log信息耗费的毫秒数
            -->
            <param name="ConversionPattern" value="%-5p %d{yyyy/MM/dd HH:mm:ss,SSS} %m  %c (%F:%L) \n"/>
        </layout>
    </appender>
 
  <!--  <appender name="rolling" class="org.apache.log4j.FileAppender">
        其他参数
         在name="file"的基础上增加了如下两个参数
         MaxFileSize=200KB: 后缀可以是KB, MB 或者是 GB. 在日志文件到达该大小时,将会自动滚动,即将原来的内容移到mylog.log.1文件。
         MaxBackupIndex=5:指定可以产生的滚动文件的最大数。
    </appender>-->
 
   <!--
    properties与xml的配置类似,只是在properties中用的是点,而在xml中是节点
    # 应用于socket
    log4j.appender.socket=org.apache.log4j.RollingFileAppender
    log4j.appender.socket.RemoteHost=localhost
    log4j.appender.socket.Port=5001
    log4j.appender.socket.LocationInfo=true
    # Set up for Log Factor 5
    log4j.appender.socket.layout=org.apache.log4j.PatternLayout
    log4j.appender.socket.layout.ConversionPattern=[%-5p] %d(%r) –> [%t] %l: %m %x %n
    # Log Factor 5 Appender
    log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender
    log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000
    # 发送日志到指定邮件
    log4j.appender.mail=org.apache.log4j.net.SMTPAppender
    log4j.appender.mail.Threshold=FATAL
    log4j.appender.mail.BufferSize=10
    log4j.appender.mail.From = xxx@mail.com
    log4j.appender.mail.SMTPHost=mail.com
    log4j.appender.mail.Subject=Log4J Message
    log4j.appender.mail.To= xxx@mail.com
    log4j.appender.mail.layout=org.apache.log4j.PatternLayout
    log4j.appender.mail.layout.ConversionPattern=[%-5p] %d(%r) –> [%t] %l: %m %x %n
    # 应用于数据库
    log4j.appender.database=org.apache.log4j.jdbc.JDBCAppender
    log4j.appender.database.URL=jdbc:mysql://localhost:3306/test
    log4j.appender.database.driver=com.mysql.jdbc.Driver
    log4j.appender.database.user=root
    log4j.appender.database.password=
    log4j.appender.database.sql=INSERT INTO LOG4J (Message) VALUES('=[%-5p] %d(%r) –> [%t] %l: %m %x %n')
    log4j.appender.database.layout=org.apache.log4j.PatternLayout
    log4j.appender.database.layout.ConversionPattern=[%-5p] %d(%r) –> [%t] %l: %m %x %n
-->
    <!--指定包名下的输出级别-->
    <logger name="cn.mybaties.dao">
        <level value="debug"/>
    </logger>
 
    <!--STDOUT的所有的输出级别  fatal(致命错误) > error (错误) > warn (警告) > info(普通信
息) > debug(调试信息)    如下为相应的name添加级别-->
    <root>
        <level value="warn"/>
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="file"/>
    </root>
</log4j:configuration>
posted @ 2018-10-07 09:43  fatale  阅读(189)  评论(0编辑  收藏  举报