springboot 日志【转】【补】

 

市面上的日志框架

日志门面 (日志的抽象层)日志实现
JCL(Jakarta Commons Logging)(2014) SLF4j(Simple Logging Facade for Java) jboss-logging Log4j     JUL(java.util.logging)    Log4j2    Logback

补充说明:Logback, Log4j , Log4j2都出于同一作者之手, 但Logback更新。

在使用日志时, 都是选一个左边门面(抽象层)、再选一个右边的实现;该用方法时只用右边门面方法 , 

Spring框架选用JCL日志,需要引用commons-logging.jar ,  SpringBoot框架选用 SLF4j和logback;

每一个日志的实现框架都有自己的配置文件。就算使用slf4j门面,日志实现框架用的还是自己本身的配置文件;

 

 

 

如何让系统中所有的日志都统一到slf4j;

1、将系统中其他日志框架先排除出去 (比如删除log4j.jar;

2、用中间包来替换原有的日志框架 (比如添加log4j-over-slf4j.jar);

3、我们导入slf4j其他的实现 

 

 

为什么还要jcl-over-slf4j.jar ,log4j-over-slf4j.jar, jul-to-slf4j.jar?

这是一个历史遗留问题  , 因为一个项目只一般不可能只有一个日志框架 , 比如Spring 使用commons-logging , hibernate使用 jboss-logging , MyBatis , XXX等其它框架又用了各自的日志框架, 那么为了把各种框架都整合到一个日志中去输出 , 所以有了这些需要替换原始功能的jar包

 

SpringBoot日志关系

SpringBoot使用它来做日志功能;

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

 

底层依赖关系图

 

总结:

1)、SpringBoot底层也是使用slf4j+logback的方式进行日志记录;

2)、SpringBoot也把其他的日志都替换成了slf4j;

3)、中间替换包(以jck-over-slf4j.jar为例),其实内部被换成了SLF4JLogFactory

@SuppressWarnings("rawtypes")
public abstract class LogFactory {
    static String UNSUPPORTED_OPERATION_IN_JCL_OVER_SLF4J = "http://www.slf4j.org/codes.html#unsupported_operation_in_jcl_over_slf4j";
    static LogFactory logFactory = new SLF4JLogFactory();

 

4)、如果我们要引入其他框架?一定要把这个框架的默认日志依赖移<exclusion>除掉,比如Spring框架用的是commons-logging;

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

 

日志测试

logback测试用例

@RunWith(SpringRunner.class)
@SpringBootTest
public class LoggingTest {
    Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    ApplicationContext ac;//注入上下文

    @Test
    public void contextLoads() {
        //日志的级别;
        //由低到高   trace<debug<info<warn<error
        //可以调整输出的日志级别;日志就只会在这个级别以以后的高级别生效
        logger.trace("这是trace日志...");
        logger.debug("这是debug日志...");
        //SpringBoot默认给我们使用的是info级别的,没有指定级别的就用SpringBoot默认规定的级别;root级别(用了info级别)
        logger.info("这是info日志...");
        logger.warn("这是warn日志...");
        logger.error("这是error日志...");
    }
    public ApplicationContext getAc() {
        return ac;
    }
    public void setAc(ApplicationContext ac) {
        this.ac = ac;
    }
}

 

application.properties配置文件

# springboot日志的配置文件,本处由application.properties中的spring.profiles.active=logging来启用本文件
# 指定log文件,也可以写固定的绝对路径, 如果file和path都指定了,那么file优先级更高
#logging.file=springboot02.log
# 指定log路径,默认使用使用spring.log作为文件名, 如果以/开头,则在当前磁盘的根目录下创建路径,如果不以/开头,则在当前应用目录下创建日志路径
logging.path=/springbootlog01/logs

# 日志占位符说明
# %d表示日期时间
# %thread表示线程名
# %-5level:级别从左显示5个字符宽度,左对齐
# %logger{50} 表示logger包路径加类名字最长50个字符
# %msg:日志消息
# %n是换行符

#  在控制台输出的日志的格式
logging.pattern.console=%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n
# 指定文件中日志输出的格式
logging.pattern.file=%d{yyyy-MM-dd} [%thread] %-5level %logger{50} - %msg%n

# 指定com下的所有日志输出级别为trace
logging.level.com=trace

 

 

logback默认配置位于该目录: spring-boot-1.5.14.RELEASE.jar!/org/springframework/boot/logging/logback/defaults.xml和base.xml

 

 

日志配置

给类路径下放上每个日志框架自己的配置文件即可;SpringBoot就不使用他默认配置的了

日志系统自定义文件说明 
Logback logback.xml 直接被日志框架识别,不经过springboot , 不支持SpringBoot的profile功能.  
Logback logback-spring.xml 日志框架就不直接加载日志的配置项,由SpringBoot解析日志配置,可以使用SpringBoot的高级Profile功能  
Log4j2 log4j2.xml    
Log4j2 log4j2-spring.xml    
JDK (Java Util Logging) logging.properties    

 

logback-spring.xml 使用SpringBoot的profile功能如下:

<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">
            <springProfile name="dev">
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ----> [%thread] ---> %-5level %logger{50} - %msg%n</pattern>
            </springProfile>
            <springProfile name="!dev">
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ==== [%thread] ==== %-5level %logger{50} - %msg%n</pattern>
            </springProfile>
        </layout>
    </appender>

 

 日志切换

  slf4j+log4j的方式 (已亲测)  processon地图 log4j2 (未亲测)  
pom.xml内容 

 

 

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <!--排队具体的日志实现logback-->
                <exclusion>
                    <groupId>ch.qos.logback</groupId>
                    <artifactId>logback-classic</artifactId>
                </exclusion>
                <!--排队log4j的替换包-->
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>log4j-over-slf4j</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!--使用log4j的适配层,它底层依赖log4j.jar,所以不用再导log4j.jar了,在classpath根目录放一个log4j.properties即可 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
        </dependency>

 

 

 

 

 

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>spring-boot-starter-logging</artifactId>
                    <groupId>org.springframework.boot</groupId>
                </exclusion>
            </exclusions>
        </dependency>

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

 

 

 
 说明  此处直接去掉了slf4j的实现 , 必须换成log4j的实现  此处引用的是spring-boot-starter-log4j2场景启动器,替换了spring-boot-starter-logging场景启动器的功能  
       

 

自己喜欢的简易风

日志配置

#  在控制台输出的日志的格式
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss}\t↓%n%msg%n

 

日志格式

2019-12-04 09:59:37    ↓
Root WebApplicationContext: initialization completed in 813 ms
2019-12-04 09:59:38    ↓
Initializing ExecutorService 'applicationTaskExecutor'
2019-12-04 09:59:38    ↓
Tomcat started on port(s): 8080 (http) with context path '/es'
2019-12-04 09:59:38    ↓

 

在日志上打印请求唯一log标识

 

重点语句

org.slf4j.MDC;
MDC.put(TRACE_ID, traceId);
MDC.remove(TRACE_ID);

使用拦截器实现

package com.interceptors.logtag.interceptor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;

/**
 * <p>日志拦截器</p>
 *
 * @author zetting
 * @date 2018/8/27 11:18
 */
@Component
public class LogInterceptor extends HandlerInterceptorAdapter {
    private Logger log = LoggerFactory.getLogger(this.getClass());
    /**
     * 日志跟踪标识
     */
    private static final String TRACE_ID = "TRACE_ID";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String traceId = UUID.randomUUID().toString();
        if (StringUtils.isEmpty(MDC.get(TRACE_ID))) {
            MDC.put(TRACE_ID, traceId);
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
        MDC.remove(TRACE_ID);
    }
}

 

 

【Springboot之搜索日志妙招】在日志上打印请求唯一log标识==>https://www.jianshu.com/p/b74ade8bbb57

posted @ 2018-05-11 09:29  苦涩泪滴  阅读(133)  评论(0编辑  收藏  举报