首页 > 其他分享 >logack 简介

logack 简介

时间:2023-05-15 13:45:22浏览次数:61  
标签:logack logging 简介 boot glmapper spring 日志 logger

转载:

https://juejin.cn/post/6844903641535479821

之前在 日志?聊一聊slf4j吧 这篇文章中聊了下slf4j。本文也从实际的例子出发,针对logback的日志配置进行学习。

logack 简介

logback 官网:https://logback.qos.ch/

目前还没有看过日志类框架的源码,仅限于如何使用。所以就不说那些“空话”了。最直观的认知是:

  • logbacklog4j是一个人写的
  • springboot默认使用的日志框架是logback
  • 三个模块组成
    • logback-core
    • logback-classic
    • logback-access
  • 其他的关于性能,关于内存占用,关于测试,关于文档详见源码及官网说明

logback-core 是其它模块的基础设施,其它模块基于它构建,显然,logback-core 提供了一些关键的通用机制。logback-classic 的地位和作用等同于 Log4J,它也被认为是 Log4J 的一个改进版,并且它实现了简单日志门面 SLF4J;而 logback-access 主要作为一个与 Servlet 容器交互的模块,比如说tomcat或者 jetty,提供一些与 HTTP 访问相关的功能。

配置文件详解

这部分主要来学习下logback配置文件的一些配置项。

configuration

先来看这张图,这个结构就是整个logback.xml配置文件的结构。

对应来看下配置文件:

<configuration scan="true" scanPeriod="60 seconds" debug="false">  
    <property name="glmapper-name" value="glmapper-demo" /> 
    <contextName>${glmapper-name}</contextName> 
    
    
    <appender>
        //xxxx
    </appender>   
    
    <logger>
        //xxxx
    </logger>
    
    <root>             
       //xxxx
    </root>  
</configuration>  

ps:想使用spring扩展profile支持,要以logback-spring.xml命名,其他如property需要改为springProperty

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

contextName

每个logger都关联到logger上下文,默认上下文名称为“default”。但可以使用contextName标签设置成其他名字,用于区分不同应用程序的记录

property

用来定义变量值的标签,property标签有两个属性,namevalue;其中name的值是变量的名称,value的值时变量定义的值。通过property定义的值会被插入到logger上下文中。定义变量后,可以使“${name}”来使用变量。如上面的xml所示。

logger

用来设置某一个包或者具体的某一个类的日志打印级别以及指定appender

root

根logger,也是一种logger,且只有一个level属性

appender

负责写日志的组件,下面会细说

filter

filter其实是appender里面的子元素。它作为过滤器存在,执行一个过滤器会有返回DENY,NEUTRAL,ACCEPT三个枚举值中的一个。

  • DENY:日志将立即被抛弃不再经过其他过滤器
  • NEUTRAL:有序列表里的下个过滤器过接着处理日志
  • ACCEPT:日志会被立即处理,不再经过剩余过滤器

案例分析

首先来配置一个非常简单的文件。这里申请下,我使用的是 logback-spring.xml。和 logback.xmlproperties上有略微差别。其他都一样。

工程:springboot+web

先来看下项目目录

properties中就是指定了日志的打印级别和日志的输出位置:

#设置应用的日志级别
logging.level.com.glmapper.spring.boot=INFO
#路径
logging.path=./logs

通过控制台输出的log

logback-spring.xml的配置如下:

<configuration>
    <!-- 默认的控制台日志输出,一般生产环境都是后台启动,这个没太大作用 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>%d{HH:mm:ss.SSS} %-5level %logger{80} - %msg%n</Pattern>
        </encoder>
    </appender>
    
    <root level="info">
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>

打印日志的controller

private static final Logger LOGGER =
LoggerFactory.getLogger(HelloController.class);
@Autowired
private TestLogService testLogService;

@GetMapping("/hello")
public String hello(){
    LOGGER.info("GLMAPPER-SERVICE:info");
    LOGGER.error("GLMAPPER-SERVICE:error");
    testLogService.printLogToSpecialPackage();
    return "hello spring boot";
}

验证结果:

01:50:39.633 INFO  com.glmapper.spring.boot.controller.HelloController
- GLMAPPER-SERVICE:info
01:50:39.633 ERROR com.glmapper.spring.boot.controller.HelloController
- GLMAPPER-SERVICE:error

上面的就是通过控制台打印出来的,这个时候因为我们没有指定日志文件的输出,因为不会在工程目录下生产logs文件夹。

控制台不打印,直接输出到日志文件

先来看下配置文件:

<configuration>
    <!-- 属性文件:在properties文件中找到对应的配置项 -->
    <springProperty scope="context" name="logging.path"  source="logging.path"/>
    <springProperty scope="context" name="logging.level" source="logging.level.com.glmapper.spring.boot"/>
    <!-- 默认的控制台日志输出,一般生产环境都是后台启动,这个没太大作用 -->
    <appender name="STDOUT"
        class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>%d{HH:mm:ss.SSS} %-5level %logger{80} - %msg%n</Pattern>
        </encoder>
    </appender>
    
    <appender name="GLMAPPER-LOGGERONE"
    class="ch.qos.logback.core.rolling.RollingFileAppender">
        <append>true</append>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>${logging.level}</level>
        </filter>
        <file>
            ${logging.path}/glmapper-spring-boot/glmapper-loggerone.log
        </file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-loggerone.log.%d{yyyy-MM-dd}</FileNamePattern>
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    
    <root level="info">
        <appender-ref ref="GLMAPPER-LOGGERONE"/>
    </root>
</configuration>

这里我们appender-ref指定的appenderGLMAPPER-LOGGERONE,因为之前没有名字为GLMAPPER-LOGGERONEappender,所以要增加一个nameGLMAPPER-LOGGERONEappender

注意上面这个配置,我们是直接接将rootappender-ref直接指定到我们的GLMAPPER-LOGGERONE这个appender的。所以控制台中将只会打印出bannar之后就啥也不打印了,所有的启动信息都会被打印在日志文件glmapper-loggerone.log中。

但是实际上我们不希望我的业务日志中会包括这些启动信息。所以这个时候我们就需要通过logger标签来搞事情了。将上面的配置文件进行简单修改:

<logger name="com.glmapper.spring.boot.controller" level="${logging.level}"
        additivity="false">
    <appender-ref ref="GLMAPPER-LOGGERONE" />
</logger>

<root level="${logging.level}">
    <appender-ref ref="STDOUT"/>
</root>

root指向控制台输出;logger负责打印包com.glmapper.spring.boot.controller下的日志。

验证结果

还是通过我们的测试controller来打印日志为例,但是这里不会在控制台出现日志信息了。期望的日志文件在./logs/glmapper-spring-boot/glmapper-loggerone.log

logger和appender的关系

上面两种是一个基本的配置方式,通过上面两个案例,我们先来了解下logger/appender/root之间的关系,然后再详细的说下loggerappender的配置细节。

在最前面介绍中提到,root是根logger,所以他两是一回事;只不过root中不能有nameadditivity属性,是有一个level

appender是一个日志打印的组件,这里组件里面定义了打印过滤的条件、打印输出方式、滚动策略、编码方式、打印格式等等。但是它仅仅是一个打印组件,如果我们不使用一个logger或者rootappender-ref指定某个具体的appender时,它就没有什么意义。

因此appender让我们的应用知道怎么打、打印到哪里、打印成什么样;而logger则是告诉应用哪些可以这么打。例如某个类下的日志可以使用这个appender打印或者某个包下的日志可以这么打印。

appender 配置详解

这里以上面案例中的名为GLMAPPER-LOGGERONEappender说明:

<appender name="GLMAPPER-LOGGERONE"
    class="ch.qos.logback.core.rolling.RollingFileAppender">
    <append>true</append>
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
        <level>${logging.level}</level>
    </filter>
    <file>
        ${logging.path}/glmapper-spring-boot/glmapper-loggerone.log
    </file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-loggerone.log.%d{yyyy-MM-dd}</FileNamePattern>
        <MaxHistory>30</MaxHistory>
    </rollingPolicy>
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        <charset>UTF-8</charset>
    </encoder>
</appender>

appender 有两个属性 nameclass;name指定appender名称,class指定appender的全限定名。上面声明的是名为GLMAPPER-LOGGERONEclassch.qos.logback.core.rolling.RollingFileAppender的一个appender

appender 的种类

  • ConsoleAppender:把日志添加到控制台
  • FileAppender:把日志添加到文件
  • RollingFileAppender:滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件。它是FileAppender的子类

append 子标签

<append>true</append>

如果是 true,日志被追加到文件结尾,如果是false,清空现存文件,默认是true

filter 子标签

在简介中提到了filter;作用就是上面说的。可以为appender 添加一个或多个过滤器,可以用任意条件对日志进行过滤。appender 有多个过滤器时,按照配置顺序执行。

ThresholdFilter

临界值过滤器,过滤掉低于指定临界值的日志。当日志级别等于或高于临界值时,过滤器返回NEUTRAL;当日志级别低于临界值时,日志会被拒绝。

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

LevelFilter

级别过滤器,根据日志级别进行过滤。如果日志级别等于配置级别,过滤器会根据onMath(用于配置符合过滤条件的操作) 和 onMismatch(用于配置不符合过滤条件的操作)接收或拒绝日志。

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

关于NEUTRALACCEPTDENY 见上文简介中关于filter的介绍。

file 子标签

file 标签用于指定被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建,没有默认值。

<file>
    ${logging.path}/glmapper-spring-boot/glmapper-loggerone.log
</file>

这个表示当前appender将会将日志写入到${logging.path}/glmapper-spring-boot/glmapper-loggerone.log这个目录下。

rollingPolicy 子标签

这个子标签用来描述滚动策略的。这个只有appenderclassRollingFileAppender时才需要配置。这个也会涉及文件的移动和重命名(a.log->a.log.2018.07.22)。

TimeBasedRollingPolicy

最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动。这个下面又包括了两个属性:

  • FileNamePattern
  • maxHistory
<rollingPolicy 
    class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    <!--日志文件输出的文件名:按天回滚 daily -->
    <FileNamePattern>
        ${logging.path}/glmapper-spring-boot/glmapper-loggerone.log.%d{yyyy-MM-dd}
    </FileNamePattern>
    <!--日志文件保留天数-->
    <MaxHistory>30</MaxHistory>
</rollingPolicy>

上面的这段配置表明每天生成一个日志文件,保存30天的日志文件

FixedWindowRollingPolicy

根据固定窗口算法重命名文件的滚动策略。

encoder 子标签

对记录事件进行格式化。它干了两件事:

  • 把日志信息转换成字节数组
  • 把字节数组写入到输出流
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
    <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}
    - %msg%n</pattern>
    <charset>UTF-8</charset>
</encoder>

目前encoder只有PatternLayoutEncoder一种类型。

定义一个只打印error级别日志的appcener

 <!-- 错误日志 appender : 按照每天生成日志文件 -->
<appender name="ERROR-APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <append>true</append>
    <!-- 过滤器,只记录 error 级别的日志 -->
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
        <level>error</level>
    </filter>
    <!-- 日志名称 -->
    <file>${logging.path}/glmapper-spring-boot/glmapper-error.log</file>
    <!-- 每天生成一个日志文件,保存30天的日志文件 -->
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!--日志文件输出的文件名:按天回滚 daily -->
        <FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-error.log.%d{yyyy-MM-dd}</FileNamePattern>
        <!--日志文件保留天数-->
        <MaxHistory>30</MaxHistory>
    </rollingPolicy>
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
        <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        <!-- 编码 -->
        <charset>UTF-8</charset>
    </encoder>
</appender>

定义一个输出到控制台的appender

<!-- 默认的控制台日志输出,一般生产环境都是后台启动,这个没太大作用 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
        <Pattern>%d{HH:mm:ss.SSS} %-5level %logger{80} - %msg%n</Pattern>
    </encoder>
</appender>

logger 配置详解

<logger name="com.glmapper.spring.boot.controller"
        level="${logging.level}" additivity="false">
    <appender-ref ref="GLMAPPER-LOGGERONE" />
</logger>

上面的这个配置文件描述的是:com.glmapper.spring.boot.controller这个包下的${logging.level}级别的日志将会使用GLMAPPER-LOGGERONE来打印。logger有三个属性和一个子标签:

  • name:用来指定受此logger约束的某一个包或者具体的某一个类。
  • level:用来设置打印级别(TRACE, DEBUG, INFO, WARN, ERROR, ALLOFF),还有一个值INHERITED或者同义词NULL,代表强制执行上级的级别。如果没有设置此属性,那么当前logger将会继承上级的级别。
  • addtivity:用来描述是否向上级logger传递打印信息。默认是true

appender-ref则是用来指定具体appender的。

不同日志隔离打印案例

在前面的例子中我们有三种appender,一个是指定包约束的,一个是控制error级别的,一个是控制台的。然后这小节我们就来实现下不同日志打印到不同的log文件中。

根据包进行日志文件隔离

这个例子里我们将com.glmapper.spring.boot.controller中的日志输出到glmapper-controller.log;将com.glmapper.spring.boot.service中的日志输出到glmapper-service.log

<!--打印日志到glmapper-service.log的appender-->
<appender name="GLMAPPER-SERVICE"
          class="ch.qos.logback.core.rolling.RollingFileAppender">
    <append>true</append>
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
        <level>${logging.level}</level>
    </filter>
    <file>
        ${logging.path}/glmapper-spring-boot/glmapper-service.log
    </file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-service.log.%d{yyyy-MM-dd}</FileNamePattern>
        <MaxHistory>30</MaxHistory>
    </rollingPolicy>
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        <charset>UTF-8</charset>
    </encoder>
</appender>

<!--打印日志到glmapper-controller.log的appender-->
<appender name="GLMAPPER-CONTROLLER"
          class="ch.qos.logback.core.rolling.RollingFileAppender">
    <append>true</append>
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
        <level>${logging.level}</level>
    </filter>
    <file>
        ${logging.path}/glmapper-spring-boot/glmapper-controller.log
    </file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-controller.log.%d{yyyy-MM-dd}</FileNamePattern>
        <MaxHistory>30</MaxHistory>
    </rollingPolicy>
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        <charset>UTF-8</charset>
    </encoder>
</appender>

<!--此logger约束将.controller包下的日志输出到GLMAPPER-CONTROLLER,错误日志输出到GERROR-APPENDE;GERROR-APPENDE见上面-->
<logger name="com.glmapper.spring.boot.controller" level="${logging.level}" additivity="false">
    <appender-ref ref="GLMAPPER-CONTROLLER" />
    <appender-ref ref="GERROR-APPENDER" />
</logger>

<!--此logger约束将.service包下的日志输出到GLMAPPER-SERVICE,错误日志输出到GERROR-APPENDE;GERROR-APPENDE见上面-->
<logger name="com.glmapper.spring.boot.service" level="${logging.level}" additivity="false">
    <appender-ref ref="GLMAPPER-SERVICE" />
    <appender-ref ref="GERROR-APPENDER" />
</logger>

来看运行结果

1、glmaper-controller

2、glmapper-service

3、glmapper-error

满足我们的预期,但是这里有个小问题。在info日志里出现了error,当然这是正常的。假如我们不想在info里面出现error怎么办呢?很简单,我们以APPENDER-SERVICE为例,将filter过滤器进行修改:

将下面的:

<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
    <level>${logging.level}</level>
</filter>

修改为:

<filter class="ch.qos.logback.classic.filter.LevelFilter">
    <level>ERROR</level>
    <!-- 如果命中就禁止这条日志 -->
    <onMatch>DENY</onMatch>  
    <!-- 如果没有命中就使用这条规则 -->
    <onMismatch>ACCEPT</onMismatch>  
</filter>

这里同时要注意的是,在loggerlevel需要设置为info级别。

根据类进行日志文件隔离

这个其实也是和上面那个差不过,只不过粒度更细一点,一般情况下比如说我们有个定时任务类需要单独来记录其日志信息,这样我们就可以考虑使用基于类维度来约束打印。

<!--特殊功能单独appender 例如调度类的日志-->
<appender name="SCHEDULERTASKLOCK-APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <append>true</append>
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
        <level>${logging.level}</level>
    </filter>
    <file>${logging.path}/glmapper-spring-boot/scheduler-task-lock.log</file>
    <!-- 每天生成一个日志文件,保存30天的日志文件 -->
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!--日志文件输出的文件名:按天回滚 daily -->
        <FileNamePattern>${logging.path}/glmapper-spring-boot/scheduler-task-lock.log.%d{yyyy-MM-dd}</FileNamePattern>
        <!--日志文件保留天数-->
        <MaxHistory>30</MaxHistory>
    </rollingPolicy>
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
        <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        <!-- 编码 -->
        <charset>UTF-8</charset>
    </encoder>
</appender>

<!--这里指定到了具体的某一个类-->
<logger name="com.glmapper.spring.boot.task.TestLogTask" level="${logging.level}" additivity="true">
        <appender-ref ref="SCHEDULERTASKLOCK-APPENDER" />
        <appender-ref ref="ERROR-APPENDER" />
    </logger>

最终TestLogTask中的日志将会被打印到这个自己独立的log文件中。如下所示:

根据自定义 logger 的 name 进行日志文件隔离

loggername除了类、包等约束之外,当然还可以这样来玩。。。

在进行案例之前,这里先把前面案例中logger声明的代码贴一下,以作对比,以TestLogTask类中的日志为例:

 private static final Logger LOGGER =
 LoggerFactory.getLogger(TestLogTask.class);

getLogger中我们是将当前对象的class作为参数的,这个是为了打印时获取其全限定名的(见下面3-)。

1-2018-07-21 11:15:42.003 [pool-1-thread-1] 
2-INFO  
3-com.glmapper.spring.boot.task.TestLogTask -
4-com.glmapper.spring.boot.task:info

业务类定义

我们同样是service包下定义一个类TestLogNameServiceImpl

package com.glmapper.spring.boot.service;

@Service("testLogNameService")
public class TestLogNameServiceImpl implements TestLogNameService {

    private static final Logger LOGGER =
    LoggerFactory.getLogger("GLMAPPER-TEST-LOG");

    @Override
    public void print() {
        LOGGER.info("GLMAPPER-TEST-LOG:this is special logger-----info");
        LOGGER.error("GLMAPPER-TEST-LOG:this is special logger-------error");
    }
}

appender和logger配置

<appender name="ROOT-APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <append>true</append>
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
        <level>${logging.level}</level>
    </filter>
    <file>${logging.path}/glmapper-spring-boot/glmapper-test.log</file>
    <!-- 每天生成一个日志文件,保存30天的日志文件 -->
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!--日志文件输出的文件名:按天回滚 daily -->
        <FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-test.log.%d{yyyy-MM-dd}
        </FileNamePattern>
        <!--日志文件保留天数-->
        <MaxHistory>30</MaxHistory>
    </rollingPolicy>
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
        <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        <!-- 编码 -->
        <charset>UTF-8</charset>
    </encoder>
</appender>

<!--这里的name和业务类中的getLogger中的字符串是一样的-->
<logger name="GLMAPPER-TEST-LOG" level="${logging.level}" additivity="true">
        <appender-ref ref="ROOT-APPENDER" />
        <appender-ref ref="ERROR-APPENDER" />
    </logger>

我们这个预期的是TestLogNameServiceImpl中的日志不打印到glmapper-service.log中,而是打印到glmapper-test.log中。

1、glmapper-test.log

2、glmapper-service.log

满足我们的预期。

如何使用logback打印mybatis的sql语句

这个还是比较坑的。为什么。看下这个:

<settings>
    <setting name="logImpl" value="slf4j" />
</settings>

mybatis-configration.xml中,我们通过这样一个配置项来关联到具体的日志组件。但是logImpl的实现中是没有logback的。那么怎么办呢?这里只能通过slf4j的方式桥接到logback

然后在我们的logback-spring.xml中进行如下配置:

 <!-- 将sql语句输出到具体的日志文件中 -->
<logger name="com.alipay.sofa.cloudplatform.common.dao" level="${logging.sql.level}" additivity="false">
    <appender-ref ref="SQL-APPENDER"/>
</logger>

这里有几个点需要注意的。首先是${logging.sql.level}这个必须是debug,这个是由mybatis本身实现决定的。而这里的name设定的com.alipay.sofa.cloudplatform.common.dao值就是我们dao接口的包路径。

网上看了一个比较典型的案例,这种方式只能输出到控制台,并不能将文件输出到日志文件;它是根据内部的一个实现机制偷了个懒。mybatis用logback日志不显示sql的解决办法

https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Falipay%2Fsofa-boot "https://github.com/alipay/sofa-boot")

Demo

pom.xml

<dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.1.11</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.1.11</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-access</artifactId>
            <version>1.1.8</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.janino</groupId>
            <artifactId>janino</artifactId>
            <version>3.0.7</version>
        </dependency>

application.yml

#logging:
#  config: classpath:logback-spring.xml

my:
  logging.level.com.glmapper.spring.boot: INFO
#  #??
  loggingpath: ./logs

logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 属性文件:在properties文件中找到对应的配置项 -->
    <springProperty scope="context" name="logging.path" source="my.loggingpath"/>

    <springProperty scope="context" name="logging.level"  source="my.logging.level.com.glmapper.spring.boot"/>

    <springProperty scope="context" name="sls.endpoint" source="sls.endpoint"/>
    <springProperty scope="context" name="sls.accessKeyId" source="sls.accessKeyId"/>
    <springProperty scope="context" name="sls.accessKeySecret" source="sls.accessKeySecret"/>


    <!-- 默认的控制台日志输出,一般生产环境都是后台启动,这个没太大作用 -->
    <appender name="STDOUT"
              class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>%d{HH:mm:ss.SSS} %-5level %logger{80} - %msg%n</Pattern>
        </encoder>
    </appender>



    <appender name="GLMAPPER-LOGGERONE"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <append>true</append>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>${logging.level}</level>
        </filter>
        <file>
            ${logging.path}/glmapper-spring-boot/glmapper-loggerone.log
        </file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-loggerone.log.%d{yyyy-MM-dd}</FileNamePattern>
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- 错误日志 appender : 按照每天生成日志文件 -->
    <appender name="ERROR-APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <append>true</append>
        <!-- 过滤器,只记录 error 级别的日志 -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>error</level>
        </filter>
        <!-- 日志名称 -->
        <file>${logging.path}/glmapper-spring-boot/glmapper-error.log</file>
        <!-- 每天生成一个日志文件,保存30天的日志文件 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名:按天回滚 daily -->
            <FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-error.log.%d{yyyy-MM-dd}</FileNamePattern>
            <!--日志文件保留天数-->
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <!-- 编码 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!--打印日志到glmapper-service.log的appender-->
    <appender name="GLMAPPER-SERVICE"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <append>true</append>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>${logging.level}</level>
        </filter>
        <file>
            ${logging.path}/glmapper-spring-boot/glmapper-service.log
        </file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-service.log.%d{yyyy-MM-dd}</FileNamePattern>
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!--打印日志到glmapper-controller.log的appender-->
    <appender name="GLMAPPER-CONTROLLER"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <append>true</append>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>${logging.level}</level>
        </filter>
        <file>
            ${logging.path}/glmapper-spring-boot/glmapper-controller.log
        </file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${logging.path}/glmapper-spring-boot/glmapper-controller.log.%d{yyyy-MM-dd}</FileNamePattern>
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!--此logger约束将.controller包下的日志输出到GLMAPPER-CONTROLLER,错误日志输出到GERROR-APPENDE;GERROR-APPENDE见上面-->
    <logger name="com.glmapper.spring.boot.controller" level="${logging.level}" additivity="false">
        <appender-ref ref="GLMAPPER-CONTROLLER" />
        <appender-ref ref="GERROR-APPENDER" />
    </logger>

    <!--此logger约束将.service包下的日志输出到GLMAPPER-SERVICE,错误日志输出到GERROR-APPENDE;GERROR-APPENDE见上面-->
    <logger name="com.glmapper.spring.boot.service" level="${logging.level}" additivity="false">
        <appender-ref ref="GLMAPPER-SERVICE" />
        <appender-ref ref="GERROR-APPENDER" />
    </logger>




    <logger name="com.glmapper.spring.boot.controller"
            level="${logging.level}" additivity="false">
        <appender-ref ref="ERROR-APPENDER" />
    </logger>


    <logger name="com.example.demolog.controller" level="${logging.level}" additivity="false">
        <appender-ref ref="GLMAPPER-LOGGERONE" />
    </logger>

    <root level="${logging.level}">
        <appender-ref ref="STDOUT"/>
    </root>


</configuration>


标签:logack,logging,简介,boot,glmapper,spring,日志,logger
From: https://www.cnblogs.com/firsthelloworld/p/17401618.html

相关文章

  • 第十三篇——通达信指标公式绘图函数简介——自定义指标颜色、线型等(从零起步编写通达
    内容提要:本文简单介绍了通达信指标公式绘图函数的三种类型——画线函数、标记函数、修饰函数。 在之前的8篇文章中,介绍了通达信指标公式编写常用的18个函数。开始讲的几个函数比较简单,到后面一些函数理解起来都比较困难,更别说使用了,大家在看文章的时候可能也是云里雾里。学......
  • ADAS功能简介
    1.主动控制类ADAS:(1)自适应巡航控制系统AdapTIveCruiseControl(ACC)(2)自动紧急制动AutonomousEmergencyBraking(AEB)(3)智能大灯控制AdapTIveFrontLights(AFL)(4)智能车速控制IntelligentSpeedAdaptaTIon(ISA)(5)行人检测系统PedestrianDetecTIonSystem(PDS)2.预警类ADAS:BS......
  • docker简介
    docker是什么?解决了运行环境和配置问题的软件容器,方便做持续集成并有助于整体发布的容器虚拟化技术传统虚拟机和容器的对比传统虚拟机虚拟机就是带环境安装的这一种解决方案。它可以在一种操作系统里面运行另一种操作系统,比如在Windows10系统里面运行Linux系统Centos7。应......
  • Qt Designer 简介
    1.设计窗口默认形式: 2.设计窗口默认形式_2: 3.窗口按钮和编辑框: 4.对输入框输入提示: 5.修改窗口名: 6.窗体---》预览,查看设计的窗口: 6_1.窗体---》预览,查看设计的窗口: 7.界面设计好以后要进行`保存`: ......
  • Java设计模式简介(总结)
    Java设计模式简介(总结)什么是设计模式Java设计模式是一组经过验证的解决特定问题的编程技术,这些技术可以帮助开发人员快速、有效地开发高质量的软件。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。设计模式分类设计模式一般分为三大类:创建型、结构......
  • 【Spring 事务】【一】 Spring 事务简介
    1 前言本节我们开始来看看Spring事务哈,大家看之前首先要看过IOC、AOP、甚至代理哈,如果这些你不知道原理,你看任何东西都会很费劲,比如Bean的生命周期、AOP的切入时机、什么时候创建代理以及执行时机,这些不知道的话,你就看事务的话,会很懵,当然前提是大家是带着思考看的哈,单纯看不......
  • Redis 简介
    (一)NoSQL简介1.数据库应用的演变历程单机数据库时代一个应用,一个数据库实例Memcached时代读写分离时代分表分库时代(集群)nosql时代2.NoSQL数据库NoSQL=NotOnlySQL(不仅仅是SQL),泛指non-relational(非关系型数据库)。今天随着互联网web2.0网站的兴起,比......
  • Zookeeper_java_API的简介
    1.Zookeeper_java_API的简介1.1)org.apache.zookeeper.ZookeeperZookeeper是在Java客户端主类,负责建立与zookeeper集群的会话,并提供方法进行操作。1.2)org.apache.zookeeper.WatcherWatcher接口表示一个标准的事件处理器,其定义了事件通知相关的逻辑,包含KeeperState和EventType两......
  • 个人简介
    \(\color{black}\text{昵称是某游戏随机的,因为}\stackrel{\text{懒得再想}}{\text{觉得有纪念价值}}\text{就沿用了}\)\(|\)\(头像来源\)\(Waifu\)\(Labs\)noip考纲(迫真)工具栏(完善中)粉福\(\Huge↓欢迎光临我的哔哩哔哩账号↓\)↓WelcometomyBilibiliaccount......
  • 树形文件目录简介
    与文件管理系统和文件集合相关联的是文件目录,它包含有关文件的信息,包括属性、位置和所有权等,这些信息主要是由操作系统进行管理。首先我们来看目录管理的基本要求: 从用户的角度看,目录在用户(应用程序)所需要的文件名和文件之间提供一种映射,所以目录管理要实现“按名存取”;目录存......