JavaWinner 2019-12-09
程序中记录日志一般有两个目的,第一个目的是做故障定位,第二个目的是显示程序运行状态。
好的日志记录方式可以提供给我们足够多的定位问题的依据。
我们这里引用Logback组件进行日志的记录。
- logback-access
这个模块是与service容器集成,提供通过http访问日志的功能。
就是第三方软件可以通过logback-access这个模块来访问到我们的logback里面记录的日志。kibana这些都会用到logback-access这个模块。
- logback-classic
它是log4j的一个改良版本,优化了里面很多功能。同时它完整的实现了slf4j的api,使你可以很方便的更换成其他日志系统。比如log4j,因为logback是由开发log4j的作者开发的。
- logback-core
这个模块为前两个模块提供了基础的服务,它也是logback的主要模块。
只需记住三个标签就ok了
logger作为日志的记录器,主要是存放日志对象,也可以定义日志的类型还有级别等。
主要用于指定日志输出的目的地,也就是输出的媒介。我们的媒介可以是控制台,可以是文件,可以是远程套接字服务器等。
它是用来格式化我们的日志信息的输出的。
程序在运行的时候它会去按照一定的顺序去加载logback的配置文件。
它的加载顺序是,如果我们在配置里面指定了logback-configurationfile这个属性,那么我们将熟用这个属性的地址去找相关的配置文件。
比如说我们的程序都会按照这样的方式去执行,
就是java -xxxx什么的
如: java -Dlogback.configurationFile=xxxxxx/xxx.xml
这个时候可以给它传入一个参数叫-Dlogback.configurationFile,指定配置文件的路径,它在启动的时候就会去优先加载这个配置里面的路径。
如果我们没有配置这个属性的话,它将会去加载我们的这个classpath里面的这个logback.groovy这个文件。
如果也没找到这个logback.groovy这个文件,它还会加载到同级目录下的logback-test.xml这个文件。
如果也没有它就会加载logback.xml这个文件,这个文件也是在classpath之下。
如果都没找到,jdk版本如果是1.6以上它就会调用serviceloader去查找一个叫做com.qos.logback.classic.spi.Configurator这个接口的第一个实现类。
如果以上还都没有,它会去自动使用ch.qos.logback.classic.BasicConfigurator这个实现类,这个实现类的功能就是直接在控制台输出日志了,就是appender直接指定在控制台。
就是说如果我们不做相关的配置它也不会报错。
创建一个logback.xml的配置文件,因为我们前面的配置都没做,它自然而然就加载到这个配置文件里面了。
<?xml version="1.0" encoding="UTF-8"?> <configuration scan="true" scanPeriod="60 seconds" debug="false"> </configuration>
第一个标签是configuration,顾名思义就是配置。
给它一个属性scan等于true,scan的意思是当scan的值设置为true的时候,配置文件如果发生改变,它将会会被重新加载,默认值为true。
scanPeriod属性,它是设置检测配置文件是否有修改时间的时间间隔。如果没有给出单位,那么默认单位是毫秒,当scan为true的时候scanPeriod就生效了,默认的时间间隔是每分钟。每分钟去扫描一下配置文件有没有变化,有变化就重新加载一下配置。这样就不需要每次修改配置都要去重启服务器。这里我们给值这只为60 seconds,指的是60秒去扫描一次。
还有个属性是debug,我们给它设置为false,这个属性如果设置为true的话,它就会打印出logback内部的日志信息,实时查看logback的运行状态,这里我们不需要,因为logback已经很稳定了,我们不需要这些信息来干扰到我们业务日志的信息。
<?xml version="1.0" encoding="UTF-8"?> <configuration scan="true" scanPeriod="60 seconds" debug="false"> <property name="log.level" value="debug"></property> <property name="log.maxHistory" value="30"></property> <property name="log.filePath" value="${catalina.base}/logs/webapps/"></property> <property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS}[%thead]%-5level%logger{50} - %msg%n"></property> </configuration>
在configuration下面先定义一些参数常量,也就是全局变量
log.level 日志级别,对应的value设置为debug
日志会分级别去显示,对于logback来说有以下几个级别:
TRACE<DEBUG<INFO<WARN<ERROR级别从小到大
logback日志是这样显示的,在程序里面它会这样记录:
我们new出一个logger实例,然后可以logger.trace(),logger.debug()..这样记录日志。
如果我们指定logger的级别为INFO的话,这些记录TRACE和DEBUG的这些日志都是没有办法在logger里面显示的,这个logger就会显示logger.info()、logger.warn()、logger.error()里面记录的内容。
在实际的项目当中,我们不需要划分那么多个级别的日志通常只用这三类,第一是DEBUG,第二是INFO,第三是ERROR。就这三个级别的日志分别存储在三个不同的文件当中。
log.maxHistory 日志文件保留时间,这里设置30天
log.filePath 变量值标识日志存储的根路径,${catalina.base}里面存储的是tomcat实例的根目录
log.pattern 日志展现的格式:
%d标识的是时间格式,{yyyy-MM-dd HH:mm:ss.SSS}格式为年月日时分秒毫秒
[%thead]标识程序是哪个线程执行的
%-5level 是什么级别,缩进五位,从左显示五个字符宽度来显示我们的level
%logger{50} - %msg 日志相关信息,哪个package下面的哪个类里面的信息,%msg信息
%n 作为换行符
<?xml version="1.0" encoding="UTF-8"?> <configuration scan="true" scanPeriod="60 seconds" debug="false"> <property name="log.level" value="debug"></property> <property name="log.maxHistory" value="30"></property> <property name="log.filePath" value="${catalina.base}/logs/webapps/"></property> <property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS}[%thread]%-5level%logger{50} - %msg%n"></property> <!--控制台设置--> <!-- appender主要用来指定输出介质是什么,设置consoleAppender媒介,指定输出到控制台--> <!-- 相当于一个layout(将envent事件转换为byte数组),但是它即负责转换字符串,也负责输入到日志文件中 --> <appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <!-- 定义格式 (引用变量)--> <pattern>${log.pattern}</pattern> </encoder> </appender> <!-- DEBUG--> <!--设置日志文件随着size的增大会滚动出新的文件,或者随着时间推移按天、按月生成新的文件--> <appender name="debugAppender" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!--文件路径--> <file>${log.filePath}/debug.log</file> <!--设置滚动策略,这里设置为基于时间滚动, 这里设置为天--> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy" ></rollingPolicy> <!-- 文件名称--> <fileNamePattern>${log.filePath}/debug/debug.%d{yyyy-MM-dd}.log.gz</fileNamePattern> <!--文件最大保存历史数量 设置保存30个--> <maxHistory>${log.maxHistory}</maxHistory> <encoder> <pattern>${log.pattern}</pattern> </encoder> <!-- 过滤器 过滤level为DEBUG的日志信息 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>DEBUG</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- INFO--> <!--设置日志文件随着size的增大会滚动出新的文件,或者随着时间推移按天、按月生成新的文件--> <appender name="infoAppender" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!--文件路径--> <file>${log.filePath}/info.log</file> <!--设置滚动策略,这里设置为基于时间滚动, 这里设置为天--> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy" ></rollingPolicy> <!-- 文件名称--> <fileNamePattern>${log.filePath}/info/info.%d{yyyy-MM-dd}.log.gz</fileNamePattern> <!--文件最大保存历史数量--> <maxHistory>${log.maxHistory}</maxHistory> <encoder> <pattern>${log.pattern}</pattern> </encoder> <!-- 过滤器 过滤level为INFO的日志信息 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>INFO</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- ERROR--> <!--设置日志文件随着size的增大会滚动出新的文件,或者随着时间推移按天、按月生成新的文件--> <appender name="errorAppender" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!--文件路径--> <file>${log.filePath}/error.log</file> <!--设置滚动策略,这里设置为基于时间滚动, 这里设置为天--> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy" ></rollingPolicy> <!-- 文件名称--> <fileNamePattern>${log.filePath}/error/error.%d{yyyy-MM-dd}.log.gz</fileNamePattern> <!--文件最大保存历史数量 --> <maxHistory>${log.maxHistory}</maxHistory> <encoder> <pattern>${log.pattern}</pattern> </encoder> <!-- 过滤器 过滤level为INFO的日志信息 --> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>ERROR</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- 主要用来存放日志对象,同时告诉logback需要关注哪个package下面的日志信息--> <!--name指定关注那个package,我们设置整个工程下--> <!--level告诉logback只记录哪个level以上的信息--> <!-- 指定记录的package,${log.level}指定哪个level以上,addtivity默认为true, 会将父类root里的appender-ref也会放到自己的logger中 --> <!-- 注:一个类只能定义一个logger --> <logger name="com.cxsn" level="${log.level}" additivity="true"> <!-- 和Appender绑定--> <appender-ref ref="debugAppender"></appender-ref> <appender-ref ref="infoAppender"></appender-ref> <appender-ref ref="errorAppender"></appender-ref> </logger> <!-- 特殊的logger,如果logger的level没有指定,默认会继承root的level --> <root level="info"> <appender-ref ref="consoleAppender"></appender-ref> </root> </configuration>