springboot的logback.xml配置和日志记录

最近在研究springboot的日志,因此记录一下,作一下总结。php

几篇关于日志的文章:html

介绍日志:https://blog.csdn.net/gwd1154978352/article/details/78344091java

     https://www.cnblogs.com/bigdataZJ/p/springboot-log.htmlweb

记录日志:https://blog.csdn.net/heweimingming/article/details/76423186spring

 

日志,一般不会在需求阶段做为一个功能单独提出来,也不会在产品方案中看到它的细节。可是,这丝绝不影响它在任何一个系统中的重要的地位。sql

为了保证服务的高可用,发现问题必定要即便,解决问题必定要迅速,因此生产环境一旦出现问题,预警系统就会经过邮件、短信甚至电话的方式实施多维轰炸模式,确保相关负责人不错过每个可能的bug。shell

预警系统判断疑似bug大部分源于日志。好比某个微服务接口因为各类缘由致使频繁调用出错,此时调用端会捕获这样的异常并打印ERROR级别的日志,当该错误日志达到必定次数出现的时候,就会触发报警。apache

try {     调用某服务 } catch(Exception e) {     LOG.error("错误信息", e); } 

因此日志相当重要,这篇就来介绍下在Spring Boot如何配置日志。springboot

Spring Boot默认日志系统

Spring Boot默认使用LogBack日志系统,若是不须要更改成其余日志系统如Log4j2等,则无需多余的配置,LogBack默认将日志打印到控制台上。bash

一、若是要使用LogBack,原则上是须要添加dependency依赖的

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-logging</artifactId>
</dependency>
可是由于新建的Spring Boot项目通常都会引用spring-boot-starter或者spring-boot-starter-web,而这两个起步依赖中都已经包含了对于spring-boot-starter-logging的依赖,
因此,无需额外添加依赖,配置logback-spring.xml就能够了。以logback-spring.xml命名,spring会自动识别加载。
spring-boot-starterspring-boot-starter-webspring-boot-starter-logging

 

二、若是须要切换Log4j2,那么在pom.xml中须要排除springboot自带的commons‐logging,而后再引入log4j2的依赖:

<!--排除 commons‐logging-->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
   <exclusions>
      <exclusion>
      <groupId>commons‐logging</groupId>
      <artifactId>commons‐logging</artifactId>
      </exclusion>
   </exclusions>
</dependency>

<!--引入log4j2 -->
<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
而后再引入log4j.properties文件就能够了。

log4j.properties:
### set log levels ###
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 =  %d{ABSOLUTE} ===== %5p %c{ 1 }:%L - %m%n

#### 输出到日志文件 ###
#log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
#log4j.appender.D.File = logs/log.log
#log4j.appender.D.Append = true
#log4j.appender.D.Threshold = DEBUG ## 输出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
#
#### 保存异常信息到单独文件 ###
#log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
#log4j.appender.D.File = logs/error.log ## 异常日志文件名
#log4j.appender.D.Append = true
#log4j.appender.D.Threshold = ERROR ## 只输出ERROR级别以上的日志!!!
#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

 

日志级别

日志级别由低到高: trace < debug < info < warm < error ,设置的级别越低显示的日志级别的信息越多。
例如:若是设置的日志级别是info,那么此时,低于info级别的trace,debug日志不会显示。



springboot在不对日志进行任何设置的状况下,默认日志root级别是INFO,输出的是INFO级别以上的日志。

package com.ll;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootCacheApplicationTests {
    
    private static final Logger log = LoggerFactory.getLogger(SpringbootCacheApplicationTests.class);
    
    /**
      *   测试 日志级别:
     *    级别由低到高: trace < debug < info < warm < error  设置的级别越低显示的日志信息越多。
     *    能够调整输出的日志级别,只会显示高于设置级别的日志。
     */
    @Test
    public void testLog() {
        log.trace("这是track日志。。。");
        log.debug("这是debug日志。。。");
        //spring 默认设置的级别是info级别,没有指定级别的状况下,会使用spring默认的root级别(显示的是info级别的信息)
        log.info("这是info日志。。。");
        log.warn("这是warm日志。。。");
        log.error("这是error日志。。。");
    }     

}

控制台信息:

只会输出INFO级别以上的日志信息,开发环境中,要显示打印sql语句等debug调试信息,要对日志级别进行设置。

 

日志的组成部分:

  • 时间日期:精确到毫秒
  • 日志级别:ERROR, WARN, INFO, DEBUG or TRACE
  • 进程ID
  • 分隔符:— 标识实际日志的开始
  • 线程名:方括号括起来(可能会截断控制台输出)
  • Logger名:一般使用源代码的类名
  • 日志内容

 

日志配置:

日志能够经过两种方式配置:

1、application.properties或者application.yml文件配置:

这种方式须要把全部的日志配置写在properties或者yml文件里面,配置迁移不方便,写的感受也有点乱,很繁杂,对log4j2的支持也很差。推荐用第二种,logback的xml配置方便比较好,配置迁移复制粘贴,而后改一下里面的配置就行了。

简单列举一下:

 

logging.level.* = LEVEL

  logging.level:日志级别控制前缀,*为包名或Logger名

  LEVEL:选项TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF

举例说明:

logging.level.com.ll=DEBUG  表示com.ll包下全部class以DEBUG级别输出(包含mapper所在的包,会打印sql语句)

logging.level.root=INFO    表示root日志以INFO级别输出

 

logging.path    该属性用来配置日志文件的路径

logging.file    该属性用来配置日志文件名,若是该属性不配置,默认文件名为spring.log

logging.path=/springboot/log          在当前磁盘的根路径下建立spring文件夹和里面的log文件夹;若是不配置,使用 spring.log 做为默认文件

logging.file=E:/springboot/log/spring.log    能够指定完整的路径(logging.path和logging.file 配置一个便可)        

 

另外还有日志的打印位置设置:

logging.pattern.console=%d{yyyy/MM/dd-HH:mm:ss} [%thread] %-5level %logger- %msg%n

logging.pattern.file=%d{yyyy/MM/dd-HH:mm} [%thread] %-5level %logger- %msg%n

logging.pattern.console

该属性用于定制日志输出格式。上述配置的编码中,对应符号的含义以下:

%d{HH:mm:ss.SSS}——日志输出时间  %thread——输出日志的进程名字,这在Web应用以及异步任务处理中颇有用  %-5level——日志级别,而且使用5个字符靠左对齐  %logger- ——日志输出者的名字  %msg——日志消息  %n——平台的换行符

appliacation.properties

# com.ll包下全部class以DEBUG级别输出(包含mapper所在的包,会打印sql语句)
logging.level.com.ll=DEBUG  
# root日志以INFO级别输出
logging.level.root=INFO

# 在当前磁盘的根路径下建立spring文件夹和里面的log文件夹;若是不配置,使用 spring.log 做为默认文件
#logging.path=/springboot/log
#
能够指定完整的路径(logging.path和logging.file 配置一个便可)
logging.file=E:/springboot/log/spring.log     
#控制台日志格式 logging.pattern.console=%d{yyyy/MM/dd-HH:mm:ss} [%thread] %-5level %logger- %msg%n #文件日志格式 logging.pattern.file=%d{yyyy/MM/dd-HH:mm} [%thread] %-5level %logger- %msg%n

 

 

2、logback的xml文件配置:

因为日志服务通常都在ApplicationContext建立前就初始化了,它并非必须经过Spring的配置文件控制。所以经过系统属性和传统的Spring Boot外部配置文件依然能够很好的支持日志控制和管理。

根据不一样的日志系统,你能够按以下规则组织配置文件名,就能被正确加载:

Logback:logback-spring.xml, logback-spring.groovy, logback.xml, logback.groovy
Log4j:log4j-spring.properties, log4j-spring.xml, log4j.properties, log4j.xml
Log4j2:log4j2-spring.xml, log4j2.xml
JDK (Java Util Logging):logging.properties
Spring Boot官方推荐优先使用带有-spring的文件名做为你的日志配置(如使用logback-spring.xml,而不是logback.xml),命名为logback-spring.xml的日志配置文件,spring boot能够为它添加一些spring boot特有的配置项(下面会提到)。

上面是默认的命名规则,而且放在src/main/resources下面便可。

 

若是你即想彻底掌控日志配置,但又不想用logback.xml做为Logback配置的名字,能够经过logging.config属性指定自定义的名字:ogging.config=classpath:logging-config.xm

虽然通常并不须要改变配置文件的名字,可是若是你想针对不一样运行时Profile使用不一样的日志配置,这个功能会颇有用。

 

logback-spring.xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<!--
scan:当此属性设置为true时,配置文件若是发生改变,将会被从新加载,默认值为true。
scanPeriod:设置监测配置文件是否有修改的时间间隔,若是没有给出时间单位,默认单位是毫秒当scan为true时,此属性生效。默认的时间间隔为1分钟。
debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
-->
<configuration scan="false" scanPeriod="60 seconds" debug="false">
    <!-- 定义日志的根目录 -->
    <property name="LOG_HOME" value="/app/log" />
    <!-- 定义日志文件名称 -->
    <property name="appName" value="ll-springboot"></property>
    <!-- ch.qos.logback.core.ConsoleAppender 表示控制台输出 -->
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <!--
        日志输出格式:
            %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">
        <!-- 指定日志文件的名称 -->
        <file>${LOG_HOME}/${appName}.log</file>
        <!--
        当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名
        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>
        <!-- 日志输出格式: -->
        <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:做用在于children-logger是否使用 rootLogger配置的appender进行输出,
        false:表示只用当前logger的appender-ref,
        true:表示当前logger的appender-ref和rootLogger的appender-ref都有效
    -->
    <!--
        logger是记录Logger对象输出的日志级别的
          sercvice实现类引入日志对象能够查看方法的报错信息以及打印sql语句,public static final Logger logger = LoggerFactory.getLogger(SysUserServiceImpl.class);
      生产环境:
       通常把level设为error,能够记录错误的日志信息,毕竟主要是要记录错误信息进行错误定位。
     开发环境:
       类中引入了logger日志对象时,level级别用info,debug均可以,都有错误信息输出。
   -->
    <!-- hibernate logger -->
    <logger name="com.ll" level="info" />
    <!-- Spring framework logger -->
    <logger name="org.springframework" level="debug" additivity="false"></logger>



    <!-- 
    root与logger是父子关系,没有特别定义则默认为root,任何一个类只会和一个logger对应,
    要么是定义的logger,要么是root,判断的关键在于找到这个logger,而后判断这个logger的appender和level。 
    -->
  <!-- 通常用默认的info就能够 -->
    <root level="info">
        <!-- 控制台输出日志-->
        <appender-ref ref="stdout" />
        <!--
        开发环境:
            不须要往文件记录日志,能够把这个appender-ref ref="appLogAppender"注释,上面那个往文件写日志的appender也要注释,否则天天都产生一个空文件;
        生产环境:
            须要往文件记录日志,此时appender-ref ref="appLogAppender"就不能注释了,否则没日志记录到文件,上面那个往文件写日志的appender也要放开。
         -->
        <appender-ref ref="appLogAppender" />
    </root>
</configuration> 

 

配置完logback-spring.xml,接下来须要作的就是在把Logger对象引入到须要记录日志的类了。

public static final Logger logger = LoggerFactory.getLogger(SysUserServiceImpl.class);

下面列举一个记录批量保存方法记录错误日志的例子:

 

package com.ll.service.impl;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.ll.bean.SysUser;
import com.ll.mapper.SysUserMapper;
import com.ll.service.SysUserService;
import com.ll.utils.MyException;


@Service
public class SysUserServiceImpl implements SysUserService {

    public static final Logger logger = LoggerFactory.getLogger(SysUserServiceImpl.class);
    
    @Autowired
    SysUserMapper sysUserMapper;


    //开启事务
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,rollbackFor = MyException.class)
    @Override
    public int batchInsertUser(List<SysUser> userList) throws MyException {
        //
        try {
            sysUserMapper.batchInsertUser(userList);
        } catch (Exception e) {
       /**推荐printStackTrace()打印堆栈错误信息这个方法保留,红色错误提示,开发的时候更方便查看错误信息*/ 
            e.printStackTrace();
            /**logger.error方法把异常错误e记录进日志文件,开发环境用logger.error方法结合printStackTrace()打印堆栈错误信息的方法就能够了*/
            logger.error("method:batchInsertUser,error:",e);
            /**由于logback-spring.xml的logger的level级别设置为error时,logger.info的消息不会打印,也不会记录进日志文件,因此不要用logger.info方法,开发环境用printStackTrace()打印堆栈错误信息便可。*/
            //logger.info("method:batchInsertUser",e);
           
            throw new MyException("批量新增失败!",e.getCause());
        }
        return 1;
    }
    

}                    

 

 

 

 

有时候logger.error不能彻底地打印出网站的错误堆栈信息,只能打印这个错误是一个什么错误。

 

 

为何?

 

看Logger.error源码

 

public void error(String msg, Throwable t);

 

public void error(String msg);

 

 

 

若是只传一个参数e进去,那么e就被认为是String类型(会自动调toString()方法把Exception转成String),而不是Exception类型。

 

若是想打印堆栈信息,那么必须传两个或以上参数,实际上就是为了调用public void error(String msg, Throwable t);

 

 

 

因此咱们的写法能够是:

 

Logger.error(“xxx出错”,e); //第二个参数是e

 

而不是:

 

Logger.error(“xxx出错:”+e) 或 logger.error(e) 或logger.error(e.getMessage);

到此,springboot的slf4j简单日志门面,默认使用的logback-spring.xml配置和日志记录就完成了~~~~~~~

相关文章
相关标签/搜索