ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Logback使用总结

2022-01-25 21:02:12  阅读:208  来源: 互联网

标签:总结 分割 MM Logback 附加 yyyy 使用 日志 logback


Logback使用总结


前言

整理了下logback的常用点功能,并记录了一些在使用过程中的疑问,和问题的排错过程,防止自己再犯类似错误,也希望对路过的你有所帮助。

一、logback如何使用

任何框架的使用都是三步走:
1.导入jar包
2.配置文件
3.开始使用
对于logback自然也是不例外的,这里简单说下,不做过多的赘述。springboot默认集成了logback,所以若是建立springboot项目千万别在导入logback的jar包了,不然就会有问题。
对于配置文件的管理,会在第二部分详细介绍这块。
使用的话就比较简单了,直接增加注解@Slf4j,然后使用log.info就可以正常使用了。

二、知识点

1.logback简单模板

以下是logback的简单模板(其实生产系统也是这一套),涵盖了logback的常用配置,日常使用这些配置也就够了,基于这个配置来总结下logback的使用:

<?xml version="1.0" encoding="UTF-8"  ?>
<configuration debug="false"><!--debug=false表示不打印logback的debug信息-->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%date{yyyy-MM-dd HH:mm:ss.sss}  %-5level  %class{30}  行:%line   %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="RollingFileInfo" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>./logs/info.log</file>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>info</level>
        </filter>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>error</level>
            <onMatch>DENY</onMatch>
            <onMismatch>ACCEPT</onMismatch>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>./logs/%d{yyyy-MM, aux}/info.%d{yyyy-MM-dd}.log.gz</fileNamePattern>
            <maxHistory>30</maxHistory>
            <totalSizeCap>5GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <pattern>%date{yyyy-MM-dd HH:mm:ss.sss}  %-5level  %-60class{60}  行:%-5line  %msg%n</pattern>
        </encoder>
    </appender>


    <appender name="RollingFileError" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>./logs/error.log</file>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>./logs/%d{yyyy-MM,aux}/error.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
            <maxFileSize>50MB</maxFileSize>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%date{yyyy-MM-dd HH:mm:ss.sss}  %-5level  %-60class{60}  行:%-5line  %msg%n</pattern>
        </encoder>
    </appender>


    <root level="info">
        <appender-ref ref="STDOUT" />
        <appender-ref ref="RollingFileInfo"/>
        <appender-ref ref="RollingFileError"/>
    </root>
</configuration>

2.解析主要标签

1.configuration标签
它是根标签,包含下面三个属性
scan: 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
debug: 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
scanPeriod: 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
使用解读:一般这三个属性都是使用默认配置,无需更改。


2.root标签

该标签只能有一个,用来声明根记录器root的一些属性它有一个属性level用来声明日志等级:trace< debug< info< warn< error,此外所有的appender都需要告诉root根记录器,常用配置如下:

	<root level="info"> <!-- 声明日志级别,这里声明将作用于所有记录器-->
	    <appender-ref ref="STDOUT" /> <!-- 声明附加器引用-->
	    <appender-ref ref="RollingFileInfo"/>
	    <appender-ref ref="RollingFileError"/>
	</root>

3.appender标签
该标签用来定义附加器,所谓附加器就是日志附着的方式,该标签与root标签同级,它包含2个属性
name:该属性指定附加器的名称与root标签中保持一致。
class:指定日志的附加方式,常用的附加器有:

        控制台附加器:ch.qos.logback.core.ConsoleAppender
		文件附加器:ch.qos.logback.core.FileAppender
		滚动文件附加器:ch.qos.logback.core.rolling.RollingFileAppender

三种附加器的区别,显而易见。 控制台附加器将日志输出到控制台,文件附加器将日志输出到文件,滚动文件附加器将日志输出到文件,滚动文件附加器支持文件的分割而文件附加器不支持。所以基本都是用:控制台附加器、滚动文件附加器。


4.encoder标签
编码器,用来声明日志的格式,常用方式如下

	<encoder>
	    <pattern>%date{yyyy-MM-dd HH:mm:ss.sss}  %-5level  %-60class{60}  行:%-5line  %msg%n</pattern>
	</encoder>

常用的信息获取方式如下:
1)%date 获取当前日期,也可以指定更具体的格式比如:%date{yyyy-MM–dd HH:mm:ss.sss}
2)%level 获取当前日志等级
3)%msg 获取打印的日志信息,也就是通过代码中通过记录器打印的日志
4)%n 换行,日志在pattern都是要加的,这样日志在输出时才会正确换行
5)%logger 获取当前的记录器,还可以指定记录器的最长显示长度,比如:%logger{50},注意这个长度只是限制打印出的记录器的名字的长度
6)%class 获取当前类名,与logger类似,class也可以指明长度,比如:%class{40}
7)%line 获取打印日志的语句所处代码的行数。
8)%thread 获取当前线程名称
9)%10class 不足10位前面补空格
10%-10class 不足10位后面补空格


5.file标签
该标签比较简单用来声明日志文件,比较简单。


6.filter标签
改标签为过滤器,常用的过滤器有两种都是基于日志级别的过滤:
级别过滤器:ch.qos.logback.classic.filter.LevelFilter
当输出日志匹配到level时,就会返回onMatch中的信息,不匹配时返回onMismatch中的信息。
若是返回DENY则是拒绝输出,返回ACCEPT则是输出,此外还可以返回NEUTRAL保持中立,下面过滤器的作用是:若是日志是error则不输出日志,否则输出日志。

	<filter class="ch.qos.logback.classic.filter.LevelFilter">
	    <level>error</level>
	    <onMatch>DENY</onMatch>
	    <onMismatch>ACCEPT</onMismatch>
	</filter>

阈值过滤器:ch.qos.logback.classic.filter.ThresholdFilter
若是输出的日志级别高于level中声明的级别则会输出,否则不会输出。高于info的也就是warn和error了。

	<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
	    <level>info</level>
	</filter>

7.rollingPolicy标签
这个标签内容会多一些,这里主要是定义日志的分割行为的。用官方话说就是定义日志的滚动策略。常用的滚动策略有两种:
基于时间的滚动策略:ch.qos.logback.core.rolling.TimeBasedRollingPolicy
他的常用配置如下main所示了,fileNamePattern用来声明日志分割的具体策略,%d{yyyy-MM, aux}这里需要特别注意,fileNamePattern中只允许一个日期不声明aux,其他都必须声明为aux,这样logback才知道是以哪个时间为基准来分割日志。maxHistory标识日志存放的时间,这个时间的单位就是fileNamePattern中日志分割的时间单位。totalSizeCap标识所有日志文件的最大大小,超过这个值,logback会清理掉最初的日志,以满足这个限制。

	<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
	    <fileNamePattern>./logs/%d{yyyy-MM, aux}/info.%d{yyyy-MM-dd}.log.gz</fileNamePattern>
	    <maxHistory>30</maxHistory>
	    <totalSizeCap>5GB</totalSizeCap>
	</rollingPolicy>

基于大小和时间的滚动策略:ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy
这个比上面的多了个maxFileSize,这个是限制文件大小的。当日志达到这个限制就会被分割。此外需要特别注意的是,若是指定的大小未达到,即使指定的时间达到了日志也不会分割,必须是日志大小达到了日志才会分割。这种分割场景比较适合日志量特别大的系统,因为此时一天只能日志可能需要多次分割,若是日志量不大的系统日志一天一分割即可,此时使用上面的基于时间分割的策略为最优。这里还两点需要注意%i,这个是分割日志时标注日志需要所用,必须要有。后面跟的点gz,是用来压缩文件的。fileNamePattern语句最后跟gz或者zip时,logback都会自动识别将文件进行压缩。

<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
    <fileNamePattern>./logs/%d{yyyy-MM,aux}/error.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
    <maxFileSize>50MB</maxFileSize>
    <maxHistory>30</maxHistory>
</rollingPolicy>

8.property标签

用来定义变量值,它有两个属性name和value,通过property定义的值会在配置文件中都可以正常获取,可以使“${}”来使用变量。

	<configuration scan="true" scanPeriod="60 seconds" debug="false"> 
	   <property name="APP_Name" value="myAppName" /> 
	   <contextName>${APP_Name}</contextName> 
	</configuration>

三、问题和排错

这里记录下使用时碰到的一些问题,有些问题很白痴,但是还是记录下防止自己再犯好了。


1.描述:只引入logback的依赖,启动工程时报错:Failed to load class “org.slf4j.impl.StaticLoggerBinder”.
解决:增加一个依赖,该依赖应该是上方类的实现了,如下:

 <dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-simple</artifactId>
  <version>1.6.6</version>
</dependency>

增加该依赖后使用代码可以正常获取记录器,但是配置文件还是不行,其实报上面这个错最根本的原因还是springboot默认已经集成了logback,无需在引入了,取消引入就ok了。


2.描述:logback配置文件不生效,直接在classpath下增加了logback.xml或者logback-spring.xml都是不生效的。
解决:测试了很多方法,更换jar包,文件位置不对的都不行,现在测试以下降低springboot的版本,当前使用是springboot2.6.3降到2.5.9最后发现也不是springboot版本的问题,而是因为springboot默认集成了logback,无需再手动引入该依赖,引入了就是多余操作,jar包多余了,删除掉引用发现正常。


3.描述:使用springboot默认的logback,发现增加配置文件后日志在控制台全部不打印了
解决:这里是因为使用了配置文件,默认都从配置文件读取配置,但是又没有指定这块配置就导致了这样的结果。
这里需要指定日志输出到控制台,并且为其指定一个appender,这样就ok了,详细配置如下:

	<?xml version="1.0" encoding="UTF-8" ?>
	<configuration>
	    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
		<encoder>
		    <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
		</encoder>
	    </appender>
	    <root level="debug">
		<appender-ref ref="STDOUT" />
	    </root>
	</configuration>

4.问题:附加器和各个记录器之间的关系?
解答:可以在记录器中声明附加器,记录器中声明的附加器会被记录器的子记录器通过继承来获得吗,我感觉可能是可以的,如果可以那我的日志为什么不生效呢,理论上根记录器有了附加器那其他的子记录器也应该有了附加器,都应该可以正常输出的啊,奇怪。
再测试下,之前的encoder中的pattern是否有日志输出
结论:父记录器的附加器确实可以被子记录器来获取,因此我们在声明附着器时是可以只在根记录器声明可以了。另外刚刚碰到的问题自己加的pattern日志没有出现,原来是因为日志忘了加%n进行换行,所有日志都输出到了一行。


5.问题:滚动文件附加器在使用基于时间的滚动分割时,文件不会自动分割。
解答:两个原因:
1).需要指定日志输出文件,并且分割文件的位置也要指定(不然会在项目的根目录里)
2).必须要有日志正在打印才会分割,若是日志文件是空的,即使满足基于时间的分割要求,日志也是不会发生分割的。


6.问题:在滚动文件附加器中使用基于大小和时间的滚动策略,若是项目重启,对待之前存在的日志文件maxHistory还能生效吗?
经验证还是生效的,所以重启并不会影响到文件备份的整体性。


7.问题:日志的分割是以fileNamePattern中的哪个值来分割的
解答:经测试,是以指定文件名的最后的%d{}来进行分割,不过其他的%d都需要使用aux来声明,如%d{yyyy-MM,aux}


8.问题;配置了logback是否还需要使用nohup命令来指定日志的输出文件?
解答:猜测是不需要的,测试下。经验证是不需要,启动命令中将控制台日志输出到黑洞即可,>/dev/null &。


9.问题:lombok中如何使用logback
解答:直接使用注解 @Slf4j即可,不过需要idea中预先装好lombok。


10.问题:文件的路径到底使用斜杠还是反斜杠
解答:好像是绝对路径使用反斜杠,相对路径使用斜杠。
经测试,无论是相对路径还是绝对路径斜杠和反斜杠在windows中都可以使用,且无区别。
但是在linux服务器上测试时,发现相对路径用反斜杠不好使,还得用斜杠。


11.问题:logback能不能直接将日志进行压缩打包,这样可以节省很多空间
解答:网上说直接在分割文件末尾加.gz即可。项目上好像也是这么用的,测试一下。
验证后确实可以,其实在末尾加.zip也是可以的,logback支持这两种声明方式进行压缩。


12.问题:加上.gz以后,日志没有正常按时间进行切分
猜测:因为加了大小1mb限制,时间是以分钟来切割。那么会不会必须先达到1mb大小才会按照时间来切割。如果这样的话就是说必须以最大的限制条件来进行切割的,若是以分钟切割,一分钟内不达到最大的文件大小是不会切割的,达不到就会达到设定的最大值才来切割,若是达到了则会 按大小来切割。那么是不是可以说,其实基于时间和大小的滚动策略,其实基础是以大小来切割的,时间只是辅助。
验证下:验证确实如此。和加.gz没有任何关系。


13.问题:若是使用logback记录日志的话,那么启动不能使用nohup来记录日志了,那启动命令该怎么写?
解答:java -server -jar -Xss1m -server -Xms512m -Xmx2048m -Xmn128m -XX:MetaspaceSize=128M -XX:+UseConcMarkSweepGC mdm-project-server-biz.jar >/dev/null &
本地测试都正常使用该命令,在uat启动时发现日志并没有正常输出。
经历了一次深刻的教训,使用jenkinsn打包发布时,因为ssh到目标服务器以后,默认路径是你登录的用户工作路径。在这里执行上面的命令就会将脚本中创建的文件在这里创建,而不是以jar包所在的路径为相对路径进行创建这个问题前后解决了3小时,深痛教训,在jenkins中写脚本时,ssh以后一定要先cd再操作。


14.问题:以时间为基准的滚动策略对比以大小和时间为基准的滚动策略
解答:时间为基准的滚动策略:指定滚动时间,就只会以时间为大小往下滚动,但是还可以为他加上这个限制:

 <timeBasedFileNamingAndTriggeringPolicy  class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
 	<!-- maxFileSize:这是活动文件的大小,默认值是10MB,测试时可改成1KB看效果 -->
 	 <maxFileSize>3kb</maxFileSize>
 </timeBasedFileNamingAndTriggeringPolicy>

这样的话,滚动效果就是和基于大小合和时间的滚动策略一模一样了。他们都是先看大小是否达到,大小达到了就会以时间进行分割日志文件,如果大小未达到是不会分割文件的。经验值加上他的效果和以大小时间为基础的滚动策略基本一致。


15.问题:fileNamePattern日志输出路径(绝对路径)增加了%{yyyy-MM}后,日志不能正常分割
解答:经验证,加了该路径后再windows系统中不能正常生产当前日期的文件夹。
下面测试下相对路径增加这个路径是否可行:不可行,在windows系统中无论是绝对路径还是相对路径增加这个文件夹都失败了。
可是记得之前是可以的,很奇怪。
再验证下linux系统中的情况:好像突然也不行了。
是不是和这个有关:%d{yyyy-MM-dd, aux}:经检查这个配置是告诉logback不是以这个时间进行分割的,一个fileNamePattern中除了指定的分割的日期,其他的日期都是需要加上这个aux的。
验证后发现确实和这个配置有关,问题解决。


总结

这是自己学习logback的总结,同时纪录了自己解决学习过程中问题的思路,logback东西不多这些基本就够用了,至于控制台的彩色日志,没啥用也就没研究。在这里记录下希望可以帮到想要学习的人。

标签:总结,分割,MM,Logback,附加,yyyy,使用,日志,logback
来源: https://blog.csdn.net/m0_46897923/article/details/122690277

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有