springBoot(九)整合之整合logging-logback(打日志姿势)

最近有用到了springboot下需要日志的需求,然后就顺带做个笔记,正常操作,直接上代码

借鉴:http://blog.csdn.net/tianyaleixiaowu/article/details/73321610

    http://blog.csdn.net/wangdongsong1229/article/details/17463113


打日志的方式:之前,我们需要知道什么时候需要打日志,打的有格式,有逻辑,而不能像开始入门一样随便是不是都打日志,过分的日志会适得其反


什么时候打日志


1、当你遇到问题的时候,只能通过debug功能来确定问题,你应该考虑打日志,良好的系统,是可以通过日志进行问题定为的。


2、当你碰到if…else 或者 switch这样的分支时,要在分支的首行打印日志,用来确定进入了哪个分支


3、经常以功能为核心进行开发,你应该在提交代码前,可以确定通过日志可以看到整个流程


格式与注意

1、最基本的:(利用了{}作参数隔离,可读性高)
logger.debug("Processing trade with id:[{}] and symbol : [{}] ", id, symbol);


2、对于Debug的日志,必须先判断再打:
if (logger.isDebugEnabled()) {
    logger.debug("Processing trade with id: " +id + " symbol: " + symbol);
}


不要进行字符串拼接,那样会产生很多String对象,占用空间,影响性能。(反例)
logger.debug("Processing trade with id: " + id + " symbol: " + symbol);


不同级别使用

ERROR:

影响到程序正常运行、当前请求正常运行的异常情况:
1、打开配置文件失败
2、所有第三方对接的异常(包括第三方返回错误码)
3、所有影响功能使用的异常,包括:SQLException和除了业务异常之外的所有异常(RuntimeException和Exception)

如果进行了抛出异常操作,请不要记录error日志,由最终处理方进行处理:

反例(不要这么做):

try{
    ....
}catch(Exception ex){
  String errorMessage=String.format("Error while reading information of user [%s]",userName);
  logger.error(errorMessage,ex);
  throw new UserServiceException(errorMessage,ex);
}


WARN
不应该出现但是不影响程序、当前请求正常运行的异常情况:


1、有容错机制的时候出现的错误情况

2、找不到配置文件,但是系统能自动创建配置文件


当接口抛出业务异常时,应该记录此异常,或者某值接近临界值的时候;


INFO

       一般系统运行信息

1、Service方法中对于系统/业务状态的变更

2、主要逻辑中的分步骤


        外部接口部分

1、客户端请求参数(REST/WS)

2、调用第三方时的调用参数和调用结果


说明:

1、 并不是所有的service都进行出入口打点记录,单一、简单service是没有意义的(job除外,job需要记录开始和结束,)。

反例(不要这么做):

public List listByBaseType(Integer baseTypeId) {
 
    log.info("开始查询基地");
BaseExample ex=new BaseExample();
BaseExample.Criteria ctr = ex.createCriteria();
ctr.andIsDeleteEqualTo(IsDelete.USE.getValue());
Optionals.doIfPresent(baseTypeId, ctr::andBaseTypeIdEqualTo);
    log.info("查询基地结束");
return baseRepository.selectByExample(ex);
}

2、 对于复杂的业务逻辑,需要进行日志打点,以及埋点记录,比如电商系统中的下订单逻辑,以及OrderAction操作(业务状态变更)。

3、对于整个系统的提供出的接口(REST/WS),使用info记录入参

4、如果所有的service为SOA架构,那么可以看成是一个外部接口提供方,那么必须记录入参。

5、 调用其他第三方服务时,所有的出参和入参是必须要记录的(因为你很难追溯第三方模块发生的问题)

DEBUG

1、可以填写所有的想知道的相关信息(但不代表可以随便写,debug信息要有意义,最好有相关参数)
2、生产环境需要关闭DEBUG信息
3、如果在生产情况下需要开启DEBUG,需要使用开关进行管理,不能一直开启。


如何使用Logback————————————————————


1、pom.xml  

		<dependency>
			<groupId>commons-logging</groupId>
			<artifactId>commons-logging</artifactId>
			<version>1.1.1</version>
		</dependency>

2、打开哥们的spring-boot-1.X.X.RELEASE.jar

开始是想用到log4j,发现网上那堆东西都跑不通。然后就走起了打开依赖包的狗血之路



       显然,你们是看到log4j2的,然而我尝试过一次就搜索不行,这东西就得自己玩另一个(既然有)

然后认真的老铁会发现,其实两个的构成是相似的

4、按时间自动滚动的日志文件:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />
    <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/spring.log}"/>
    <include resource="org/springframework/boot/logging/logback/console-appender.xml" />
    <!-- 按照时间滚动 -->
     <appender name="TIME_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder>
            <pattern>${FILE_LOG_PATTERN}</pattern>
        </encoder>
        <file>${LOG_FILE}</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i</fileNamePattern>
            <maxHistory>365</maxHistory>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
     </appender>
     <root level="INFO">
        <appender-ref ref="CONSOLE" /> 
        <appender-ref ref="TIME_FILE" />
     </root>
</configuration>

4.1参数意味

%p: 输出日志信息优先级,即DEBUG,INFO,WARN,ERROR,FATAL,
%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"输出日志信息换行
%d: 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式


5、测试

 private static final Logger logger = LoggerFactory.getLogger(AdminServiceImpl.class);  
//AdminServiceImpl是一个类名
方法内填入:其中{}是为了填入后面的参数,会自动填入的,有多少个{}自定义,就应该加入多少个参数在后面。
logger.info("method : {} ",MethodList.AdminModfiy,"updateSysUser--username:"+sysUser.getUsername());
 
  
测试方法:
 
 
结果:
2017-12-04 12:27:19.709  INFO 9392 --- [nio-8088-exec-5] com.**.service.impl.AdminServiceImpl  : method : 1 



logback配置详解

一:根节点<configuration>包含的属性:
scan:   当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
 
     scanPeriod:   设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
   
  debug:   当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。

    <configuration scan="true" scanPeriod="60 seconds" debug="false">    
          <!-- 其他配置省略-->    
    </configuration>  

二:根节点<configuration>的子节点:

configuration
|
————————————--
| |   |
appender logger root

设置上下文名称:<contextName>

每个logger都关联到logger上下文,默认上下文名称为default。但可以使用<contextName>设置成其他名字,用于区分不同应用程序的记录。一旦设置,不能修改
<!-- lang: xml-->  
<configuration scan="true" scanPeriod="60 seconds" debug="false">    
      <contextName>myAppName</contextName>    
      <!-- 其他配置省略-->    
</configuration> 

设置变量: <property>

用来定义变量值的标签,<property> 有两个属性name和value;

  • name: 变量的名称
  • value: 的值时变量定义的值。

通过<property>定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量

例如使用<property>定义上下文名称,然后在<contentName>设置logger上下文时使用。

    <!-- lang: xml-->  
 <configuration scan="true" scanPeriod="60 seconds" debug="false">    
        <property name="APP_Name" value="myAppName" />     
        <contextName>${APP_Name}</contextName>    
          <!-- 其他配置省略-->    
 </configuration> 

获取时间戳字符串:<timestamp>

  • key: 标识此<timestamp> 的名字;
  • datePattern: 设置将当前时间(解析配置文件的时间)转换为字符串的模式,遵循java.txt.SimpleDateFormat的格式。

例如将解析配置文件的时间作为上下文名称

    <!-- lang: xml-->  
    <configuration scan="true" scanPeriod="60 seconds" debug="false">    
          <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/>     
          <contextName>${bySecond}</contextName>    
          <!-- 其他配置省略-->    
    </configuration>  




已经用在生产环境,如果有什么疑问或问题,欢迎指出一起讨论

猜你喜欢

转载自blog.csdn.net/coffeeandice/article/details/78708296
今日推荐