日志logback详解

【Logback】Logback 的配置文件 首先,DefaultJoranConfigurator 会尝试查找“logback.configurationFile” 系统属性上指定的文件。如果可以找到该文件,则会读取并解释该文件,然后进行配置。如果没有找到上述文件,DefaultJoranConfigurator 将尝试在类路径上查找配置文件 “logback-test.xml” 。如果可以找到该文件,则会读取并解释该文件,然后进行配置。 如果没有找到上述文件,配置器将继续尝试在类路径中查找配置文件 阅读详情

这篇博客是我参考了很多资料总结出来的,内容很多,希望能帮助到你^_^

可以先看下目录了解下大体内容: 

一、日志框架发展史

二、日志规范

三、日志级别

四、Logback

4.1 Maven引入

4.2 logback-spring.xml是在哪里加载的?

4.3 logback.xml和logback-spring.xml区别

五、logback-spring.xml格式详解

5.1 完整格式

5.2 configuration

5.2.1 定时器是如何生效的?

5.3 contextName

5.4 property和springProperty

5.5 timestamp

5.6.logger和root

5.6.1 说明

5.6.2.appender-ref

5.7 appender

5.7.1 ConsoleAppender

5.7.2 FileAppender

5.7.3 RollingFileAppender

5.7.3.1 TimeBasedRollingPolicy

5.7.3.2 SizeBasedTriggeringPolicy

5.7.3.3 FixedWindowRollingPolicy

5.7.3.4 SizeAndTimeBasedRollingPolicy

5.8 encoder说明

5.8.1 %n

5.8.2 %c %lo %logger

 5.8.3 %C %class

5.8.4.%d %date

5.8.5.%caller

5.8.6.%L %line

5.8.7 %m %msg %message

5.8.8.%M %method

5.8.9 %p %le %level

5.8.10 %r %relative

5.8.11.%t %thread

5.8.12 %replace

6.8.13 宽度设置

5.8.14.显示设置

5.8.14.1.%clr和defaults.xml

5.8.14.2.支持的颜色

 5.9 filter过滤规则

5.9.1 LevelFilter

5.9.2 ThresholdFilter

5.9.3 EvaluatorFilter

5.9.4 自定义过滤器

六、优化异常堆栈stack日志打印

6.1 未优化前

6.2.优化后


一、日志框架发展史

参考博客:

【精选】Java日志框架的发展历史,你不想了解一下吗_java日志历史-优快云博客 [Java日志框架的发展历史,你不想了解一下吗]

第1阶段:只有System.out 与System.error

第2阶段:Apache大佬Ceki Gülcü 搞了个 Log4j,爆火

第3阶段:Sun眼红Log4j, 自己制定一套标准JUL  (Java Util Logging),没啥人用

第4阶段:Apache不服,也自己制定一套标准JCL (Jakarta Commons Logging), 可以在Log4j和JUL之间切换,但存在问题。

第5阶段,大佬Ceki Gülcü离开Apache公司,觉得JCL不好用,自己搞了个Slf4j (Simple Logging Facade For Java 简单日志门面)。但想要Apache和Sun来对接Slf4j太难,于是弄了桥接包,通过桥接包来帮助Slf4j接口与其他日志库建立关系,这种方式称桥接设计模式。

但仍然存在一个问题:日志配置文件未做统一,假如你的系统使用了Slf4j作为日志接口,使用Log4j作为日志产品,则配置文件需要配2份。

Ceki Gülcü发话: 没事,大家都选择用Slf4j统一吧,我来帮大家统一,没有事是桥接包解决不了的,有的话,那就再来个。

第6阶段:Ceki Gülcü 巨佬觉得市场上的日志标准库都是间接实现Slf4j接口,也就是说每次都需要配合桥接包,也就是之前的日志产品都不是正统的Slf4j的实现。

因此在2006年,Ceki Gülcü 基于Slf4j接口写出了Logback日志标准库

第7阶段:Slf4j+Logback的模式,显然很冲击JCL+Log4j,并且本身Logback确实比Log4j性能更优,设计更为合理,所以,老东家Apache可就坐不住了。

   在2012年,Apache直接推出新项目,不是Log4j1.x升级,而是新项目Log4j2,因为Log4j2是完全不兼容Log4j1.x的。

   并且很微妙的,Log4j2几乎涵盖Logback所有的特性(这不是对着干是啥~而且还有抄袭的嫌疑哈哈哈),更甚者的Log4j2也搞了分离的设计,分化成log4j-api和log4j-core,这个log4j-api也是日志接口,log4j-core才是日志产品。

二、日志规范

参考博客

https://www.cnblogs.com/yangyongjie/p/16230247.html [Java日志规范]

1、【强制】应用中不可直接使用日志系统(Log4j、Logback)中的 API,而应依赖使用日志框架 (SLF4J)中的 API,使用门面模式的日志框架。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Component
public class SpringUtil implements ApplicationContextAware {
    private static final Logger log = LoggerFactory.getLogger(SpringUtil.class);
}

或者使用lombok注解:

import lombok.extern.slf4j.Slf4j;
@Component
@Slf4j
public class SpringUtil implements ApplicationContextAware {
}

2、【强制】所有日志文件至少保存15天,因为有些异常具备以“周”为频次发生的特点。日志文件格式为: {logname}.log.{保存日期},日期格式:yyyy-MM-dd,例如info.log.2023-04-21

3、【强制】对 trace/debug/info 级别的日志输出,必须使用条件输出形式或者使用占位符的方式。

错误示例:(如果日志级别是 warn,该日志不会打印,但是会执行字符串拼接操作,如果 symbol 是对象,会执行 toString()方法,浪费了系统资源,但最终日志却没有打印)

log.debug("Processing trade with id: " + id + " and symbol: " + symbol);

解决方法一:打印日志前加上判断:

if (log.isInfoEnabled()) {
    log.info("Processing trade with id: " + id + " and symbol: " + symbol);
}
if (log.isWarnEnabled()) {
    log.warn("Processing trade with id: " + id + " and symbol: " + symbol);
}
if (log.isDebugEnabled()) {
    log.debug("Processing trade with id: " + id + " and symbol: " + symbol);
}

解决方法二(推荐使用):使用参数化形式{}占位,[] 进行参数隔离。因为 String 字符串的拼接会使用 StringBuilder 的 append()方式,有一定的性能损耗。使用占位符仅是替换动作,可以有效提升性能。

log.debug("Processing trade with id: [{}] and symbol: [{}]", id, symbol);

4、【强制】生产环境禁止直接使用 System.out 或 System.err 输出日志或使用 e.printStackTrace()打印异常堆栈。

5、【强制】生产环境禁止打印debug日志

6、【建议】打印日志不要使用JSON.toJSONString()写法,而是通过重写对象的toString()方法(可以使用lombok的 @ToString(callSuper=true))。

错误示例:

log.info("基础数据拉取sc:{},mqJson:{}", dockDTO.getNeighNo(), JSON.toJSONString(amcBaseInfoPo));

正确示例:

log.info("基础数据拉取sc:{},mqJson:{}", dockDTO.getNeighNo(), amcBaseInfoPo);

三、日志级别

参考博客

日志打印的8种级别(很详细)_日志级别-优快云博客[日志打印的8种级别(很详细)]

log4j定义了8个级别的log,优先级从高到低依次为:

OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL
如果日志设置为L,一个级别为P的输出日志只有当P >= L时日志才会输出。

Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。

四、Logback

参考博客:

logback 日志 介绍和配置详解_logback日志配置-优快云博客 [logback 日志 介绍和配置详解]

万字详解logback日志框架,再没这么全的了!-腾讯云开发者社区-腾讯云 [万字详解logback日志框架,再没这么全的了!]

logback详解 - 知乎[logback详解]

(三)Logback中的Appender - 程序员大本营[(三)Logback中的Appender]

Java日志框架:logback详解 - 知乎[Java日志框架:logback详解]

logback -- 配置详解 -- 三 -- <encoder>[logback -- 配置详解 -- 三 -- <encoder>]

logback 配置颜色高亮_黑帽子技术的博客-优快云博客[logback 配置颜色高亮]

LogBack 基本使用_凯凯JAVA的博客-优快云博客[LogBack 基本使用]

(六)Logback中的Filter_logback filter-优快云博客[(六)Logback中的Filter]

logback logback.xml常用配置详解(三) <filter>-优快云博客[logback logback.xml常用配置详解(三) <filter>]

RollingFileAppender详解[RollingFileAppender详解]

logback解析——Appender - 简书[logback解析——Appender]

4.1 Maven引入

Spring Boot 默认使用 SLF4J+Logback 记录日志。

1、springBoot已经帮我们引入了logback包,所以我们不需要再去引用。

2、在项目资源文件夹 resources 下 创建 logback-spring.xml 文件。logback 将会自动读取该配置文件。

logback是springboot自带的日志框架.该框架主要有3个模块:

logback-core:核心代码块

logback-classic:实现了slf4j的api,加入该依赖可以实现log4j的api。

logback-access:访问模块与servlet容器集成提供通过http来访问日志的功能(也就是说不需要访问服务器,直接在网页上就可以访问日志文件,实现HTTP访问日志的功能)。

maven已经帮我们集成好了,只需引用:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.5.RELEASE</version>
    <relativePath/>
</parent>
<dependencies>
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

点击进入spring-boot-starter-web,可以看到:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter</artifactId>
  <version>2.2.5.RELEASE</version>
  <scope>compile</scope>
</dependency>

点击进入spring-boot-starter包,可以看到:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-logging</artifactId>
  <version>2.2.5.RELEASE</version>
  <scope>compile</scope>
</dependency>

点击进入spring-boot-starter-logging,可以看到:

<dependency>
  <groupId>ch.qos.logback</groupId>
  <artifactId>logback-classic</artifactId>
  <version>1.2.3</version>
  <scope>compile</scope>
</dependency>

4.2 logback-spring.xml是在哪里加载的?

参考博客

springboot 源码阅读之 logback-spring.xml 是在哪里加载的?_logback-spring加载流程-优快云博客 [springboot 源码阅读之 logback-spring.xml 是在哪里加载的?]

随便在logback-spring.xml写个错误:

<configuration scan="true" scanPeriod="10 seconds" debug="false">
    <a></a>
</configuration>

启动报错:

Exception in thread "main" java.lang.IllegalStateException: Logback configuration error detected: 
ERROR in ch.qos.logback.core.joran.spi.Interpreter@2:8 - no applicable action for [a], current ElementPath  is [[configuration][a]]
	at org.springframework.boot.logging.logback.LogbackLoggingSystem.loadConfiguration(LogbackLoggingSystem.java:169)
	at org.springframework.boot.logging.AbstractLoggingSystem.initializeWithConventions(AbstractLoggingSystem.java:80)
	at org.springframework.boot.logging.AbstractLoggingSystem.initialize(AbstractLoggingSystem.java:60)
	at org.springframework.boot.logging.logback.LogbackLoggingSystem.initialize(LogbackLoggingSystem.java:118)
	at org.springframework.boot.context.logging.LoggingApplicationListener.initializeSystem(LoggingApplicationListener.java:313)
	at org.springframework.boot.context.logging.LoggingApplicationListener.initialize(LoggingApplicationListener.java:288)
	at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEnvironmentPreparedEvent(LoggingApplicationListener.java:246)
	at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:223)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:127)
	at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:76)
	at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:53)
	at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:345)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:308)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215)
	at com.top.whysu.web.system.SystemWebApplication.main(SystemWebApplication.java:17)

进入LogbackLoggingSystem.java第169行,不断debug发现

1、org.springframework.boot.logging.logback.LogbackLoggingSystem定了4个默认配置文件:

@Override
protected String[] getStandardConfigLocations() {
   return new String[] { "logback-test.groovy", "logback-test.xml", "logback.groovy", "logback.xml" };
}

从这里可以看出来读取顺序是:logback-test.groovy,  logback-test.xml, logback.groovy, logback.xml

2、org.springframework.boot.logging.AbstractLoggingSystem这边先判断4个默认配置文件是否存在,如果不存的话,则加上-spring后缀再查询。

4.3 logback.xml和logback-spring.xml区别

参考博客

logback.xml和logback-spring.xml的区别_logback-spring和logback.xml-优快云博客 [logback.xml和logback-spring.xml的区别]

https://www.cnblogs.com/huangdh/p/16778065.html [logback.xml和logback-spring.xml的区别]

【精选】附加:logback日志组件中,logback.xml和logback-spring.xml的区别;(本篇博客并没有得出明确的结论……)_logback.xml和配置文件的区别’-优快云博客 [附加:logback日志组件中,logback.xml和logback-spring.xml的区别;]

我们使用SLF4J框架记录日志时,会用到 logback.xml 和 logback-spring.xml 两个不同的配置文件。

1、logback-spring.xml 只有在Spring应用程序运行的时候才生效,即带有@SpringBootApplication注解的类启动的时候才会生效。

     如果不是Spring应用程序,而是一个main方法或者一个JUnit的测试方法,要用 logback.xml 来配置。

2、存放的位置不同:

    logback-spring.xml存放的位置是在SpringApplication主类所在的项目的resources目录,也就是application.yml或者application.properties所在的目录

     logback.xml存放的位置是在你启动的那个类所在的项目的resources目录。

3、二者的加载顺序是:logback.xml—>application.properties—>logback-spring.xml。如果你在logback.xml定义了变量,而恰好这个变量又被写在了application.properties中,那么就有可能会获取不到,因为application.properties在logback.xml的后面执行。这也是为什么springboot推荐使用logback-spring.xml来替代logback.xml来配置。

五、logback-spring.xml格式详解

5.1 完整格式

被这张图吓住了?其实很简单的。

<root>和<logger>可以看做一棵树,root就是根节点,logger就是子节点。

<appender>就是用来定义这些节点的规则。

另外<property>和<contextName>就更简单了。

property就是定义变量,

contextName就是你这棵树的名称。

logback的日志配置文件格式如下所示:

<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> 

5.2 configuration

根节点<configuration>,包含下面三个属性:

scan: 默认值为true。当此属性设置为true时,配置文件如果发生改变,将会被重新加载。

scanPeriod: 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。如可以设置为scanPeriod="30 seconds"表示每30秒检测一次。

debug: 默认值false。当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。

<configuration scan="true" scanPeriod="30 seconds" debug="false">
</configuration>

5.2.1 定时器是如何生效的?

把debug设置为true

<configuration scan="true" scanPeriod="30 seconds" debug="true">

发现启动的时候打印了一句:

16:09:09,385 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - Setting ReconfigureOnChangeTask scanning period to 30 seconds

打开类 ch.qos.logback.classic.joran.action.ConfigurationAction;

发现的确有个定时器:

5.3 contextName

<contextName>标签作用是用来设置日志上下文的名称,可以用来区分不用应用程序。

5.4 property和springProperty

1、通过property元素可定义变量。它有name和value两个属性。

可以通过“${name}”来使用变量。

<property name="LOG_HOME" value="/home/smart-community-docking/scd/logs"/>

如果你是在windows上启动的话,然后你的项目在D盘,则日志会生成在D:\home\smart-community-docking\scd\logs目录下。

2、使用springProperty的话,值是可以从配置文件application.properties里面取值的。

例如现在有application.propertis定义了值:

spring.application.name=smart-community-docking

则可以通过springProperty获取到该值:

<configuration scan="true" scanPeriod="30 seconds" debug="false">
    <springProperty scope="context" name="APP_NAME" source="spring.application.name" defaultValue="smart-community-docking"/>
    <contextName>${APP_NAME}</contextName>
</configuration>

5.5 timestamp

用来获取时间戳字符串。这个属性很少使用。

有两个属性key和datePattern。

key: 标识此<timestamp> 的名字;

datePattern: 设置将当前时间(解析配置文件的时间)转换为字符串的模式,遵循 java.txt.SimpleDateFormat的格式。

<configuration scan="true" scanPeriod="30 seconds" debug="false">
   <timestamp key="currentDate" datePattern="yyyy-MM-dd" />
</configuration>

5.6.logger和root

5.6.1 说明

logger:

  • name属性:用来指定logger约束的包或者具体类。
  • level属性:用于设置日志打印级别。RACE,DEBUG,INFO,WARN,ERROR,ALll和OFF还有INHERITED(NULL)。如果没有设置则默认为(null)会继承上级的级别。
  • addtivity属性:是否向上级logger传递打印信息,默认为true。如果设置为true,在输出日志时,你会发现控制台会输出两遍。所以一般设置additivity为false
<!-- 指定包-->
<logger name="com.top.scd.controller"/>
<!-- 指定类-->
<logger name="com.top.scd.controller.UserController" level="DEBUG" additivity="true"/>
  • <root>也是<logger>元素

  • 它的name就是ROOT。所以只能配置level属性

  • level属性的取值范围只能取 TRACE, DEBUG, INFO, WARN, ERROR, ALL, OFF。

  • level默认是DEBUG。

5.6.2.appender-ref

<logger>和<root> 标签下允许有0个或者多个 <appender-ref>

<appender-ref>只有一个ref 用于指定<appender>标签。

5.7 appender

appender用来定义日志的输出格式,过滤规则,以及日志文件如何生成。

有2个属性name 和class。

name当然是appender的名称啦。

class对应的是实现类。目前有如下三种常用的类:ConsoleAppender,FileAppender,RollingFileAppender。你会发现loback-core.jar包下真的有这3个类。

5.7.1 ConsoleAppender

ConsoleAppender:日志输出到控制台,类名ch.qos.logback.core.FileAppender。

属性名

类型

备注

encoder

ch.qos.logback.core.encoder.Encoder

对日志进行格式化。

使用<pattern>指定格式。具体格式见后面章节。

<charset>指定字符编码。

target

String

有效值为System.out或者System.err,默认为System.out。一般不写。

示例:

注意:禁止向除了ConsoleAppender之外的appender配置彩色日志。

<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="1 seconds" debug="false">
<!--${CONSOLE_LOG_PATTERN}在这个文件里面引用的-->
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>debug</level>
        </filter>
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <!-- 设置字符集 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <root level="INFO">
        <appender-ref ref="CONSOLE" />
    </root>
</configuration>

5.7.2 FileAppender

FileAppender:日志输出到文件,类名ch.qos.logback.core.FileAppender。

属性名

类型

备注

file

String

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

append

boolean

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

encoder

ch.qos.logback.core.encoder.Encoder

对日志进行格式化。

使用<pattern>指定格式。具体格式见后面章节。

<charset>指定字符编码。

prudent

boolean

如果是 true,日志会被安全的写入文件(即使其他的FileAppender也在向此文件做写入操作),效率低,默认是 false。

示例:

<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="1 seconds" debug="false">
    <!--定义日志路径,如果是windows启动并且代码在D盘, 则日志会生成于D:\home\smart-community-docking\scd\logs下-->
    <property name="LOG_HOME" value="/home/smart-community-docking/scd/logs"/>
    <appender name="file" class="ch.qos.logback.core.FileAppender">
        <!--日志格式配置-->
        <encoder>
            <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
        </encoder>
        <!--日志输出路径-->
        <file>${LOG_HOME}/logback.log</file>
        <!--默认日志被追加到文件结尾-->
        <append>true</append>
    </appender>
    <root level="INFO">
        <appender-ref ref="file"/>
    </root>
</configuration>

5.7.3 RollingFileAppender

RollingFileAppender:滚动记录文件,FileAppender的子类。

先将日志文件指定到文件,当符合某个条件时,将日志记录到其他文件。

类名:ch.qos.logback.core.rolling.RollingFileAppender。

属性名

类型

备注

file

String

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

append

boolean

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

rollingPolicy

ch.qos.logback.core.rolling.RollingPolicy

当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名。

属性class定义具体的滚动策略类

triggeringPolicy

ch.qos.logback.core.rolling.TriggeringPolicy

告知 RollingFileAppender 何时激活滚动。

这个要配合具体的rollingPolicy使用,不同的rollingPolicy会有所不同。目前有用到的就只有SizeBasedTriggeringPolicy。

encoder

ch.qos.logback.core.encoder.Encoder

对日志进行格式化。

使用<pattern>指定格式。具体格式见后面章节。

<charset>指定字符编码。

prudent

boolean

当为true时,不支持FixedWindowRollingPolicy。支持TimeBasedRollingPolicy,但是有两个限制,1不支持也不允许文件压缩,2不能设置file属性,必须留空。

这里有如下常用的4种滚动策略:

TimeBasedRollingPolicy,SizeBasedTriggeringPolicy,FixedWindowRollingPolicy,SizeAndTimeBasedRollingPolicy

5.7.3.1 TimeBasedRollingPolicy

时间滚动策略  ch.qos.logback.core.rolling.TimeBasedRollingPolicy

可以基于时间滚动按时间生成日志

属性名

类型

备注

fileNamePattern

String

定义了归档日志文件的名字。

1、它的值由文件名和%d的占位转换符组成,如果没有指定时间和日期格式,默认为yyyy-MM-dd。(由java.text.SimpleDateFormat进行格式化)。

2、轮转周期通过fileNamePattern推断出来的。可以指定多个 %d,但是只能有一个是主要的,用于推断轮转周期,其它的 %d 占位符必须通过 'aux' 标记为辅助的。

例如:/var/log/%d{yyyy/MM,aux}/myapplication.%d{yyyy-MM-dd}.log

3、也可以指定时区:%d{yyyy-MM-dd_HH-mm, UTC},如果指定的时区timezone不能被识别或者拼写错误的话,将会根据TimeZone.getTimeZone(String)方法指定为 GMT。

举例:

/foo.%d  默认%d格式是yyyy-MM-dd,按天滚动。

/%d{yyyy/MM}/foo.log 按月滚动

/%d{yyyy-MM-dd_HH}.log  按小时滚动

/%d{yyyy-MM-dd_HH-mm, UTC}.log 按分钟滚动

/%d{yyyy-MM, aux}/%d.log  按天滚动

maxHistory

int

表示日志文件保存的最大数量。

例如:如果根据fileNamePattern判断出来是按天滚动,该值设为30,则日志文件最多保存30天。

totalSizeCap

int

来控制所有归档文件总的大小。当达到这个大小后,旧的归档文件将会被异步的删除。

使用这个属性时还需要设置 maxHistory 属性。而且,maxHistory 将会被作为第一条件,该属性作为第二条件。

cleanHistoryOnStart

boolean

如果设置为 true,那么在 appender 启动的时候,归档文件将会被删除。默认的值为false。

下面是一些例子:

文件命名格式

滚动计划

备注

/wombat/foo.%d

按日滚动

%d默认是yyyy-MM-dd格式。

昨天:/wombat/foo.2023-04-22

今天:/wombat/foo.2023-04-23

如果RollingFileAppender设置了<file>属性,则当前的日志会被打印到file配置的文件中。例如如果<file>值为/wombat/aaaa.txt, 则:

昨天:/wombat/foo.2023-04-22

今天:/wombat/aaaa.txt

TimeBasedRollingPolicy支持归档日志文件自动压缩,如果fileNamePattern的值以.gz或者.zip结尾则可利用该特性。

文件命名格式

滚动计划

备注

/wombat/foo.%d.gz

按日滚动,归档日志文件会自动GZIP压缩

文件格式如下:

昨天:/wombat/foo.2019-05-05.gz

当天:/wombat/foo.2019-05-06

示例:

<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="1 seconds" debug="false">
    <!--定义日志路径,使用${LOG_HOME访问}, 如果是windows启动并且代码在D盘, 则日志会生成于D:\home\smart-community-docking\scd\logs下-->
    <property name="LOG_HOME" value="/home/smart-community-docking/scd/logs"/>
    <!-- 滚动文件的方式生成日志日志文件,文件的存储位置通过file标签指定 -->
    <!-- 通过encoder指定日志的生成格式,每个appender的日志格式都可以自定义,不用相同 -->
    <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/test.log</file>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %5level - %msg%n</pattern>
        </encoder>
        <!--
        通过rollingPolicy设置日志滚动的策略,这是使用按照时间滚动
        fileNamePattern属性设置滚动生成文件的格式,这里设置的精确到天,也就是按照天滚动,如果时间设置精确到秒,就按秒来滚动
        maxHistory属性设定最大的文件数,比如按天滚动,这里设置了30天,在第31天日志生成的时候,第一天的日志就会被删掉
        -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--设置按天来滚动,前一天日志打印到23点59分,然后就一直没有请求日志,直到次日的1点才有新的日志进入。
                    在0点到1点这个时间段,日志文件是不会滚动生成新的日志文件。因为滚动的动作是需要日志写入动作来触发。-->
            <fileNamePattern>${LOG_HOME}/test-%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>30</maxHistory>
            <totalSizeCap>3GB</totalSizeCap>
            <cleanHistoryOnStart>false</cleanHistoryOnStart>
        </rollingPolicy>
    </appender>
    <root level="INFO">
        <appender-ref ref="file"/>
    </root>
</configuration>

5.7.3.2 SizeBasedTriggeringPolicy

观察当前活动文件的大小,如果已经大于了指定的值,它会给 RollingFileAppender 发一个信号触发对当前活动文件的轮转

ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy

属性名

类型

备注

maxFileSize

int

可以为字节,千字节,兆字节,千兆字节,通过在数值后面指定一个后缀 KB,MB 或者 GB。例如,5000000,5000KB,5MB 以及 2GB 都是有效的,前三个是一样的。(默认值是 10 MB)

官方的示例这个要放在<triggeringPolicy>触发策略使用,并且和FixedWindowRollingPolicy一起使用,所以这里先不说。

5.7.3.3 FixedWindowRollingPolicy

基于窗口大小的滚动策略。ch.qos.logback.core.rolling.FixedWindowRollingPolicy

这个听起来可能有点难理解,其实说白了就是将归档日志文件到最大了就写到下一个文件里,而窗口大小就是最多允许多少份日志文件。

属性名

类型

备注

fileNamePattern

String

必须包含“%i”。

假设最小值maxIndex和最大值maxIndex分别为1和2,命名模式为 mylog%i.log,会产生归档文件mylog1.log和mylog2.log。还可以指定文件压缩选项,例如,mylog%i.log.gz 或者log%i.log.zip

minIndex

int

窗口下限。下限一般都是1啦

maxIndex

int

窗口上限。一般我们用上限就可以了。

示例:(官方示例FixedWindowRollingPolic和SizeBasedTriggeringPolicy一起使用:)

<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="1 seconds" debug="false">
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>test.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
            <fileNamePattern>tests.%i.log.zip</fileNamePattern>
            <minIndex>1</minIndex>
            <maxIndex>3</maxIndex>
        </rollingPolicy>
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <maxFileSize>5MB</maxFileSize>
        </triggeringPolicy>
        <encoder>
            <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
        </encoder>
    </appender>
    <root level="DEBUG">
        <appender-ref ref="FILE" />
    </root>
</configuration>

5.7.3.4 SizeAndTimeBasedRollingPolicy

前面介绍的TimeBasedRollingPolicy是根据时间生成日志,SizeBasedTriggeringPolicy是根据大小来生成日志,但很尴尬的一点是这2个类冲突,没法同时使用。

故而官方提供了基于时间和文件大小的滚动策略:

ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy

属性名

类型

备注

fileNamePattern

String

必选参数。

具体介绍可以看TimeBasedRollingPolicy的介绍。

区别点是必须包含 %i

maxFileSize

int

每个文件最大多少。可以指定KB,MB 或者 GB,默认值是 10 MB。

maxHistory

int

表示日志文件保存的最大数量。

例如:如果根据fileNamePattern判断出来是按天滚动,该值设为30,则日志文件最多保存30天。

totalSizeCap

int

可选参数,表示所有归档日志文件的的文件总大小。

假如设置每个日志文件到10mb的时候开始切分,最多保留30天,但最大到20GB,哪怕没到30天但容量达到20G了也要删除多余的日志。

cleanHistoryOnStart

boolean

可选参数,表示appender应用程序启动时是否应进行日志存档清理,默认为false。

示例:(每个文件最多5MB,保存60天的历史记录,但最多20GB。)

<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="1 seconds" debug="false">
    <property name="LOG_HOME" value="/home/smart-community-docking/scd/logs"/>
    <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- rollover daily -->
            <fileNamePattern>${LOG_HOME}/mylog-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 每个文件最多5MB,保存60天的历史记录,但最多20GB -->
            <maxFileSize>5MB</maxFileSize>
            <maxHistory>60</maxHistory>
            <totalSizeCap>20GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <root level="DEBUG">
        <appender-ref ref="file" />
    </root>
</configuration>

5.8 encoder说明

encoder表示对参数进行格式化。

<encoder>是0.9.19版本之后引进的,以前的版本使用<layout>,logback极力推荐的是使用<encoder>而不是<layout>

<encoder>节点负责两件事情:

1、把日志信息转换为字节数组

2、把字节数组写到输出流

目前使用的是ch.qos.logback.classic.encoder.PatternLayoutEncoder (是唯一有用的且默认的encoder ),它有一个<pattern>节点,用来设置日志的输入格式。

使用“%”加“转换符”方式。

如果要输出“%”,则必须用“\”对“\%”进行转义。

5.8.1 %n

转换符

作用

是否避免使用

n

日志换行。

根据使用平台输出\n或\r\n

否

说明:

看到最后一列的标题是"是否避免使用",这是因为这些信息是无法直接拿到的(比如请求行号、调用方法名),logback必须通过一些特殊手段去获取这些数据(比如在日志打印出产生一个堆栈信息),这种操作会比较影响效率,因此除非必要,否则不建议打印这些数据。

5.8.2 %c %lo %logger

转换符

作用

是否避免使用

c{length}

lo{length } 

logger{length}

输出日志的logger名,有一个形参,功能是缩短logger名,设置为0表示只输入logger最右边点符号之后的字符串。

{length} 限制了总输出长度,如果输出长度不够,尽可能显示类名,压缩包名。

否

示例:

例如我在com.top.scd.web.system.controller.module.xmga.XmgaController打印了一行日志

package com.toptop.scd.web.system.controller.module.xmga;
@RestController
@RequestMapping("/dockset/sc_xmga")
@Slf4j
public class XmgaController {
    @GetMapping("/time")
    @ResponseBody
    public String time() {
        log.warn("aaaaa");
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String timeStr = "厦门公安-当前时间:" + format.format(new Date());
        return timeStr;
    }
}

logback-spring.xml中配置:

<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="1 seconds" debug="true">
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%c-%lo-%logger</pattern>
        </encoder>
    </appender>
    <root level="info">
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>

打印结果:

com.toptop.scd.web.system.controller.module.xmga.XmgaController-com.toptop.scd.web.system.controller.module.xmga.XmgaController-com.toptop.scd.web.system.controller.module.xmga.XmgaController

可以注意到点号也是有被算进来的

pattern格式

打印结果

打印长度

%logger

com.toptop.scd.web.system.controller.module.xmga.XmgaController

63

%logger{0}

XmgaController

14

%logger{1}

c.l.s.w.s.c.m.x.XmgaController

30

%logger{14}

c.l.s.w.s.c.m.x.XmgaController

30

%logger{30}

c.l.s.w.s.c.m.x.XmgaController

30

%logger{32}

c.l.s.w.s.c.m.x.XmgaController

30

%logger{33}

c.l.s.w.s.c.m.xmga.XmgaController

33

%logger{38}

c.l.s.w.s.c.module.xmga.XmgaController

38

%logger{47}

c.l.s.w.s.controller.module.xmga.XmgaController

47

%logger{52}

c.l.s.w.system.controller.module.xmga.XmgaController

52

%logger{54}

c.l.s.web.system.controller.module.xmga.XmgaController

54

%logger{56}

c.l.scd.web.system.controller.module.xmga.XmgaController

56

%logger{61}

c.toptop.scd.web.system.controller.module.xmga.XmgaController

61

%logger{63}

com.toptop.scd.web.system.controller.module.xmga.XmgaController

63

%logger{100}

com.toptop.scd.web.system.controller.module.xmga.XmgaController

63

 5.8.3 %C %class

转换符

作用

是否避免使用

C{length}

class{length } 

输出日志调用所在类。

length与%logger(简写%c或%lo)的用法相同。

尽量避免使用,除非执行速度不造成任何问题。

是

(不被推荐使用)

5.8.4.%d %date

转换符

作用

是否避免使用

d{pattern}

date{pattern} 

输出时间格式,模式语法同

java.text.SimpleDateFormat

否

可以指定日期格式精确到毫秒:%d{yyyy-MM-dd HH:mm:ss.SSS}

5.8.5.%caller

转换符

作用

是否避免使用

caller{depth}

输出日志的调用者的位置信息,整数选项表示输出信息深度。

否

<pattern>%caller</pattern>

打印:

Caller+0  at com.toptop.scd.web.system.controller.module.xmga.XmgaController.time(XmgaController.java:49)

Caller+1  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

Caller+2  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

Caller+3  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

Caller+4  at java.lang.reflect.Method.invoke(Method.java:498)

<pattern>%caller{1}</pattern>

打印:

Caller+0  at com.toptop.scd.web.system.controller.module.xmga.XmgaController.time(XmgaController.java:49)

5.8.6.%L %line

转换符

作用

是否避免使用

L

line

输出执行日志请求的行号。

尽量避免使用,除非执行速度不造成任何问题。

是

<pattern>%L</pattern>

5.8.7 %m %msg %message

转换符

作用

是否避免使用

m

msg

message

输出应用程序提供的信息

否

log.warn("aaaaa");
<pattern>%msg</pattern>

打印:

aaaaa

5.8.8.%M %method

转换符

作用

是否避免使用

M

method

数值执行日志请求的方法名。

尽量避免使用,除非执行速度不造成任何问题。

是

public String time() {
    log.warn("aaaaa");
}
<pattern>%method</pattern>

打印:

time

5.8.9 %p %le %level

转换符

作用

是否避免使用

p

le

level

输出日志级别

否

log.warn("aaaaa");
<pattern>%level</pattern>

打印:

WARN

5.8.10 %r %relative

转换符

作用

是否避免使用

r

relative

输出从程序启动到创建日志记录的时间,单位是毫秒

否

<pattern>%r%n</pattern>

多执行几次,打印:

30675581

30676817

30677965

30679104

30680009

5.8.11.%t %thread

转换符

作用

是否避免使用

t

thread

输出产生日志的线程名

否

<pattern>%thread</pattern>

打印:

http-nio-8998-exec-1

5.8.12 %replace

转换符

作用

是否避免使用

replace(p){r,t}

p为日志内容, r是正则表达式, 将p中符合r的内容替换为t

否

log.warn("aaaaa");
<pattern>%replace(%msg){"a", "b"}</pattern>

打印结果:

bbbbb

6.8.13 宽度设置

%20logger:当字符数少于20个字符时,则左侧留空白;
%-20logger:当字符数少于20个字符时,则右侧留空白;
%.30logger:当字符数据大于30个时,则截断;

还可以合起来使用,例如:%-20.20logger     %20.20class

{length}可指定长度,如%logger{36}

log.warn("123456789");
<pattern>%80logger%n%-80logger%n%.20logger</pattern>

5.8.14.显示设置

%highligth(日志内容):突出显示

%green(日志内容):字体显示为指定颜色

%clr(日志内容){颜色} 设置颜色

5.8.14.1.%clr和defaults.xml
<pattern>%clr(%msg){faint}%n</pattern>

这里启动会报错说找不到%clr对应的转换器。

Exception in thread "main" java.lang.IllegalStateException: Logback configuration error detected:

ERROR in ch.qos.logback.core.pattern.parser.Compiler@79145d5a - There is no conversion class registered for composite conversion word [clr]

ERROR in ch.qos.logback.core.pattern.parser.Compiler@79145d5a - Failed to create converter for [%clr] keyword

解决方法一:

引入springboot的默认日志配置:

<include resource="org/springframework/boot/logging/logback/defaults.xml" />

<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="1 seconds" debug="false">
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%clr(%msg){faint}%n</pattern>
        </encoder>
    </appender>
    <root level="INFO">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

解决方法二:或者手动引入需要的配置:

<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="1 seconds" debug="false">
    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%clr(%msg){faint}%n</pattern>
        </encoder>
    </appender>
    <root level="INFO">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

这个文件是怎么冒出来的呢?查看前面的那个default.xml文件就可以看到啦!

5.8.14.2.支持的颜色

%black 黑色

%red 红色

%green 绿色

%yellow 黄色

%blue 蓝色

%magenta 洋红色

%cyan 青色

%white 白色

%gray 灰色

%faint 灰白色

以下为对应加粗的颜色代码

%boldRed

%boldGreen

%boldYellow

%boldBlue

%boldMagenta

%boldCyan

%boldWhite

 %highlight 高亮色

 5.9 filter过滤规则

5.9.1 LevelFilter

<appender>标签里面可以指定<filter>过滤器,

例如ch.qos.logback.classic.filter.LevelFilter,表示根据日志级别进行过滤。

<level>:设置过滤级别

<onMatch>:用于配置符合过滤条件的操作

<onMismatch>:用于配置不符合过滤条件的操作

举例:

<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="1 seconds" debug="true">
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <encoder>
            <pattern>
                %-4relative [%thread] %-5level %logger{30} - %msg%n
            </pattern>
        </encoder>
    </appender>
    <root level="DEBUG">
        <appender-ref ref="CONSOLE"/>
    </root>
</configuration>
public String time() {
    log.trace("====trace====");
    log.debug("====debug====");
    log.info("====info====");
    log.warn("====warn====");
    log.error("====error====");
}

打印结果:

186556 [http-nio-8998-exec-6] INFO  c.l.s.w.s.c.m.x.XmgaController - ====info====

5.9.2 ThresholdFilter

临界值过滤器,过滤掉低于指定临界值的日志。

对应的类是ch.qos.logback.classic.filter.ThresholdFilter。

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

<level>:设置过滤级别

例如:过滤掉所有低于INFO级别的日志:

<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="1 seconds" debug="true">
    <appender name="CONSOLE"
              class="ch.qos.logback.core.ConsoleAppender">
        <!-- 过滤掉低于INFO级别的日志-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
        <encoder>
            <pattern>
                %-4relative [%thread] %-5level %logger{30} - %msg%n
            </pattern>
        </encoder>
    </appender>
    <root level="DEBUG">
        <appender-ref ref="CONSOLE"/>
    </root>
</configuration>
public String time() {
    log.trace("====trace====");
    log.debug("====debug====");
    log.info("====info====");
    log.warn("====warn====");
    log.error("====error====");
}

打印结果:

393494 [http-nio-8998-exec-9] INFO  c.l.s.w.s.c.m.x.XmgaController - ====info====

393494 [http-nio-8998-exec-9] WARN  c.l.s.w.s.c.m.x.XmgaController - ====warn====

393494 [http-nio-8998-exec-9] ERROR c.l.s.w.s.c.m.x.XmgaController - ====error====

5.9.3 EvaluatorFilter

求值过滤器,评估、鉴别日志是否符合指定条件。

对应类是ch.qos.logback.core.filter.EvaluatorFilter。

需要额外的两个JAR包,commons-compiler.jar和janino.jar。

有以下子节点:

<evaluator>鉴别器,常用的鉴别器是ch.qos.logback.classic.boolex.JaninoEventEvaluator

,也是默认的鉴别器。它以任意的java布尔值表达式作为求值条件,求值条件在配置文件解释过成功被动态编译,布尔值表达式返回true就表示符合过滤条件。

<evaluator>有个子标签<expression>,用于配置求值条件

<onMatch>:用于配置符合过滤条件的操作

<onMismatch>:用于配置不符合过滤条件的操作

求值表达式作用于当前日志,logback向求值表达式暴露日志的各种字段:

Name

Type

Description

event

LoggingEvent

与记录请求相关联的原始记录事件,下面所有变量都来自event,例如,event.getMessage()返回下面"message"相同的字符串

message

String

日志的原始消息,例如,设有logger mylogger,"name"的值是"AUB",对于 mylogger.info("Hello {}",name); "Hello {}"就是原始消息。

formatedMessage

String

日志被各式话的消息,例如,设有logger mylogger,"name"的值是"AUB",对于 mylogger.info("Hello {}",name); "Hello Aub"就是格式化后的消息。

logger

String

logger 名。

loggerContext

LoggerContextVO

日志所属的logger上下文。

level

int

级别对应的整数值,所以 level > INFO 是正确的表达式。

timeStamp

long

创建日志的时间戳。

marker

Marker

与日志请求相关联的Marker对象,注意“Marker”有可能为null,所以你要确保它不能是null。

mdc

Map

包含创建日志期间的MDC所有值得map。访问方法是: mdc.get("myKey") 。mdc.get()返回的是Object不是String,要想调用String的方法就要强转,例如,

((String) mdc.get("k")).contains("val") .MDC可能为null,调用时注意。

throwable

java.lang.Throwable

如果没有异常与日志关联"throwable" 变量为 null. 不幸的是, "throwable" 不能被序列化。在远程系统上永远为null,对于与位置无关的表达式请使用下面的变量throwableProxy

throwableProxy

IThrowableProxy

与日志事件关联的异常代理。如果没有异常与日志事件关联,则变量"throwableProxy" 为 null. 当异常被关联到日志事件时,"throwableProxy" 在远程系统上不会为null

EvaluatorFilter支持使用 java 代码来作为过滤标准。但需要导入额外的包:

<!-- janino -->
<dependency>
    <groupId>org.codehaus.janino</groupId>
    <artifactId>janino</artifactId>
    <version>3.1.0</version>
</dependency>
<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="1 seconds" debug="true">
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
            <evaluator> <!-- 默认为 ch.qos.logback.classic.boolex.JaninoEventEvaluator -->
                <expression>return message.contains("info");</expression>
            </evaluator>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <encoder>
            <pattern>
                %-4relative [%thread] %-5level %logger - %msg%n
            </pattern>
        </encoder>
    </appender>
    <root level="INFO">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>
public String time() {
    log.trace("====trace====");
    log.debug("====debug====");
    log.info("====info====");
    log.warn("====warn====");
    log.error("====error====");
}

打印:

21809 [http-nio-8998-exec-1] INFO  com.toptop.scd.web.system.controller.module.xmga.XmgaController - ====info====

5.9.4 自定义过滤器

自定义类:

package com.toptop.scd.base.common.filter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.filter.Filter;
import ch.qos.logback.core.spi.FilterReply;

public class SampleFilter extends Filter<ILoggingEvent> {

    @Override
    public FilterReply decide(ILoggingEvent event) {
        if (event.getMessage().contains("info")) {
            return FilterReply.ACCEPT;
        } else {
            return FilterReply.DENY;
        }
    }
}

日志配置文件指定过滤器

<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="1 seconds" debug="true">
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="com.toptop.scd.base.common.filter.SampleFilter" />
        <encoder>
            <pattern>%-4relative [%thread] %-5level %logger - %msg%n</pattern>
        </encoder>
    </appender>
    <root level="INFO">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

打印结果:

186556 [http-nio-8998-exec-6] INFO  c.l.s.w.s.c.m.x.XmgaController - ====info====

六、优化异常堆栈stack日志打印

6.1 未优化前

try {
    int i = 1/0;
} catch (Exception e) {
    log.error("发生异常", e);
}

打印结果:(打印了很多不需要的堆栈信息)

打印结果:
2023-04-25 10:58:03.757 ERROR 36556 --- [nio-8998-exec-1] c.l.s.w.s.c.module.xmga.XmgaController   : 发生异常

java.lang.ArithmeticException: / by zero
	at com.toptop.scd.web.system.controller.module.xmga.XmgaController.time(XmgaController.java:50)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:123)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:367)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1639)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)

6.2.优化后

1、引入logstash-logback-encoder

<dependency>
    <groupId>net.logstash.logback</groupId>
    <artifactId>logstash-logback-encoder</artifactId>
    <version>7.1.1</version>
</dependency>

注意jdk版本依赖:

2、引入

<conversionRule conversionWord="stack" converterClass="net.logstash.logback.stacktrace.ShortenedThrowableConverter"/>

3、通过%stack{}进行配置

stack{100,16,2048,rootFirst,regex1,regex2,evaluatorName}

参数解释:

建议查看源码 net.logstash.logback.stacktrace.ShortenedThrowableConverter#parseOptions()

  •  示例:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <conversionRule conversionWord="stack"
                    converterClass="net.logstash.logback.stacktrace.ShortenedThrowableConverter"/>
    <property name="STE_EXCLUSIONS" value="\$\$FastClassByCGLIB\$\$,\$\$EnhancerBySpringCGLIB\$\$,^sun\.reflect\..*\.invoke,^com\.sun\.
    ,^sun\.net\.,^net\.sf\.cglib\.proxy\.MethodProxy\.invoke,^org\.springframework\.cglib\.,^org\.springframework\.transaction\.
    ,^org\.springframework\.validation\.,^org\.springframework\.app\.,^org\.springframework\.aop\.,^java\.lang\.reflect\.Method\.invoke
    ,^org\.springframework\.ws\..*\.invoke,^org\.springframework\.ws\.transport\.,^org\.springframework\.ws\.soap\.saaj\.SaajSoapMessage\.
    ,^org\.springframework\.ws\.client\.core\.WebServiceTemplate\.,^org\.springframework\.web\.filter\.,^org\.apache\.tomcat\.
    ,^org\.apache\.catalina\.,^org\.apache\.coyote\.,^java\.util\.concurrent\.ThreadPoolExecutor\.runWorker,^java\.lang\.Thread\.run$"/>
    <!--
        stack{100,16,2048,rootFirst,regex1,regex2,evaluatorName}
        参数解释: 建议查看源码 net.logstash.logback.stacktrace.ShortenedThrowableConverter#parseOptions() 方法
            第1参数: maxDepthPerThrowable:值可以是 full或者short或者int值,表示每个异常最多打印多少个 stackTraceElements 元素
            第2参数: shortenedClassNameLength:值可以是 full或者short或者int值,将尝试将类名长度缩短到小于此值
                     com.huan.springboot.service.ExceptionService 可能会变成 c.h.s.s.ExceptionService
            第3参数: maxLength:值可以是 full或者short或者int值,指的输出到日志中整个堆栈最大能存在多少个字符。
            后面这些参数没有固定顺序
            第4参数: rootFirst: 可选参数,如果使用该参数,值就是 rootFirst ,表示应首先打印堆栈的根本原因
            第5参数: inlineHash: 可选参数,如果使用该参数,值就是 inlineHash, 指示应该计算和内联十六进制错误哈希
            如果参数都不是上方的类型,那么可能是 evaluator 或者 exclude 类型,这2个都是判断这个 stackTraceElement 是否应该被打印,这2个参数没有顺序关系
                evaluator: 值的是需要实现 EventEvaluator<ILoggingEvent> 的类
                exclude: 指的是需要排除的正则表达式, 如果存在.需要转义成 \.
    -->
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %msg%n%stack{100,full,2048,rootFirst,inlineHash,${STE_EXCLUSIONS},}</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <root level="INFO">
        <appender-ref ref="stdout"/>
    </root>
</configuration>

优化后打印的日志,部分堆栈信息被隐藏:

<#6242a0ba> java.lang.ArithmeticException: / by zero
	at com.toptop.scd.web.system.controller.module.xmga.XmgaController.time(XmgaController.java:50)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java)
	... 3 frames excluded
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
	... 5 frames excluded
	at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:123)
	... 27 frames excluded
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	... 2 frames excluded

Logback的使用 logger.error("日志输出,ERROR日志---{}", output);logger.warn ("日志输出,WARN 日志---{}", output);logger.info ("日志输出,INFO 日志---{}", output);logger.debug("日志输出,DEBUG日志---{}", output);logger.trace("日志输出,TRACE日志---{}", output); 阅读详情

相关推荐

SpringBoot介绍

Spring是一个非常优秀的轻量级框架,以IOC(控制反转)和AOP(面向切面)为思想内核,极大简化了JAVA企业级项目的开发。虽然Spring的组件代码是轻量级的,但它的配置却是重量级的。使用Spring进行项目开发需要在配置文件中写很多代码,所有这些配置都代表了开发时的损耗。除此之外,Spring项目的依赖管理也是一件耗时耗力的事情。在环境搭建时,需要分析要导入哪些库的坐标,而且还需要分析导入与之有依赖关系的其他库的坐标,一旦选错了依赖的版本,随之而来的不兼容问题就会严重阻碍项目的开发进度。

1261

Springboot日志框架Logback的使用及配置

两种配置方式 application.properties或 application.yml (系统层面) logback-spring.xml(自定义文件方式) 第一种方式比较简单,可做的事情也比较简单,比如:只能配置日志文件的输出路径、日志文件的格式、日志的级别等 第二种方式比较复杂,对日志的处理比较好,生产上推荐这种,运行维护好。如有以下需求: 区分 debug、info、error 等类型的日志,并分别输出到不同的日志文件。 对日志文件进行维护,如每天产生一个日志文件,并设置日志文件的大小和保

weixin_41844824的博客 1242

互联网金融项目实战(大数据Hadoop hive)

什么是互联网金融? 互联网金融 --> 信贷(信用贷款) --> 支付宝率先搞了一个信用体系 互联网金融: 在线支付、P2P 银行: 只会锦上添画、不喜欢雪中送炭 银行害怕出现坏账 ( 储户存钱,银行放贷 赚个利息差 ) 银行是可以倒闭的 保险公司不允许倒闭 银行分为:商业银行(自生自灭的)和非商业银行(国家的) 中国工商银行 全球第一大行 招商银行(清朝的一个李鸿章) 中国银行(历史超过 100 年了) 国家政策:希望银行能够扶持中小型企业 p2p:网络借贷平台 民间吸纳贷款 -->

weixin_58276266的博客 1553

logback教程logback快速入门超实用详细教程收藏这一篇就够了(万字长文)

日志级别、参数化日志形式好处、日志级别的继承性、配置文件加载顺序、配置文件语法基本结构、标签大小写、日志颜色、变量定义、springProfile 多环境配置、SizeAndTimeBasedRollingPolicy、SiftingAppender、AsyncAppender......

weixin_72518095的博客 2万+

开源大模型“去审查化”技术解析:从LLaMA架构到本地部署与伦理边界

大型语言模型(LLM)基于Transformer架构,通过海量数据训练获得理解和生成自然语言的能力。其核心原理在于自注意力机制对上下文关系的建模。为了确保输出内容的安全与合规,主流模型普遍采用基于人类反馈的强化学习(RLHF)等技术进行安全对齐。这一过程旨在使模型行为符合人类价值观,是AI伦理工程实践的关键环节。然而,在特定研究场景下,如对抗性测试或内容安全算法研究,技术人员需要模拟极端对话以评估系统鲁棒性,这催生了针对“去对齐”或“移除护栏”的技术探索。此类技术通常通过对预训练模型进行反向微调或继续训练来

weixin_33743880的博客 589

使用KITTI数据集测试不同算法的性能

该文章将使用同一个kitti数据集来测试不同算法的性能,目前已经测试的算法包括:LIO-SAM,FAST-LIO2,Point-LIO,Faster-LIO。

wwtx的博客 2586

Logback日志详解

Logback是log4j的改良,更好更快更强大的性能 主要模块: logback-access:与servlet容器集成,提供通过Http访问日志的功能。 logback-classic:log4j的改良版本。 logback-core:为上两个提供基础的服务。 主要标签: logger:作为日志的记录器,主要用于存放日志对象,也可以定义日志的类型、级别等。 ...

仲夏宁叶香的博客 562

echarts的坐标轴处理算法

参考原文:https://www.cnblogs.com/vicky-li/p/11653415.html。2、可用于双轴的情况,指定splitNumber,保证左右两边的线没有交叉显示的情况。1、设置echarts显示的最大最小值,让数据显示比较有起伏。处理echarts的一些问题。

HYeeee的博客 801

logback 日志 介绍和配置详解

logback介绍和配置详解 logback是Java的开源框架,性能比log4j要好。是springboot自带的日志框架。该框架主要有3个模块: logback-core:核心代码块(不介绍) log back-classic:实现了slf4j的api,加入该依赖可以实现log4j的api。 log back-access:访问模块与servlet容器集成提供通过http来访问日志的功能(也就是说不需要访问服务器,直接在网页上就可以访问日志文件)。 一、logback的使用 引入maven依

qq_30436011的博客 9745

保研考研机试攻略(满分篇):第二章——满分之路上(1)

保研考研机试攻略(满分篇):第二章——满分之路上(1)2.1计算机和基础+2.2进阶背包问题+2.3毛毛虫算法

qq_63349644的博客 1195

Python爬虫模拟登录京东并抓取商品数据

京东是一个拥有海量商品数据的电子商务平台。作为爬虫开发者,能够抓取这些数据将为我们提供很多机会进行数据分析、价格预测、市场调研等工作。然而,京东的反爬虫机制非常强大,包括但不限于验证码、动态加载页面、IP封禁等。因此,想要通过Python爬虫抓取京东的数据并不容易。在本文中,我们将从分析京东的登录机制开始,逐步介绍如何使用Python中的各种工具,如。

2201_76125261的博客 1828

Logback 日志框架

Logback 作为 Spring Boot 的默认日志框架,提供了高性能、灵活的日志解决方案。(Log4j 作者)设计的高性能日志框架,专为 Java 应用提供高效、灵活的日志解决方案。Spring Boot 默认通过。结构化日志以 JSON 格式记录日志,便于后续分析。依赖集成 Logback,支持开箱即用的日志功能。

小李同学的博客 2683

152:vue+leaflet 判断一个点是否在一个电子围栏内

本文介绍了一个基于Vue+Leaflet的示例,演示如何判断点是否在电子围栏内。作者大剑师兰特(优快云知名博主)展示了使用polygon.getBounds().contains(latlng)方法检测点与多边形边界的关系。代码仅需80行,通过点击地图触发判断逻辑,结果显示提示信息。该技术可广泛应用于地理围栏、位置服务等场景,需要安装turf依赖。文章提供了完整源码和配置说明,适合GIS开发者学习参考。

大剑师兰特的GIS世界 756

Logback日志配置【详解】

1. logback主要模块 logback-access:与service容器集成,提供通过http来访问日志的功能。 logback-classic:是log4j的改良版,完整的实现了slf4j-api。 logback-core:为上述两个模块提供了基础的服务。 2. logback主要标签 logger: 作为日志的记录器主要用于存放日志对象,可以定义日志的类型及级别。 appender: 用于指定日志输入的目的地,也就是输出的媒介,可以是控制台,也可以是文件等。 layou

李忠祥个人博客 1386

基于特征模仿的YOLOv5中间层知识蒸馏:原理、实现与实验全解析

目标检测中的模型轻量化是一个关键挑战。本文提出一种基于特征模仿(Feature Imitation)的YOLOv5中间层知识蒸馏方法,通过让学生模型学习教师模型的中间层特征表示,显著提升轻量级检测器的性能。我们将详细阐述蒸馏损失函数的设计、特征对齐策略、训练流程,并提供完整可运行的代码实现。同时,推荐多个适合蒸馏训练的数据集,并通过实验验证方法的有效性。

YOLO 185

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Logback日志技术

这一步是固定的,想要记录日志,就需要一个日志记录对象。

2401_89221867的博客 1247

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Logback日志

Logback日志 1、配置logback日志2、创建 logback-spring.xml3、压缩日志 1、配置logback日志 删除application.properties中的日志配置(删除这两个) 2、创建 logback-spring.xml 安装idea彩色日志插件:grep-console resources 中创建 logback-spring.xml <?xml version="1.0" encoding="UTF-8"?> <!-- 日志配置 --> &l

一个孤独漫步者的遐想的博客 2879

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

LogBack日志

SpringBoot对所有内部日志使用通用日志记录,但保留底层日志实现。为Java Util Logging、Log4J2和Logback提供了默认配置。在不同的情况下,日志记录器都预先配置为使用控制台输出,同时还提供可选的文件输出。默认情况下,SpringBoot使用Logback进行日志记录。

mengyb个人文档记录 1188

SpringBoot如何使用日志Logback,及日志等级详解

Spring Boot默认已经集成了SLF4J(Simple Logging Facade for Java)作为日志的接口,以及Logback作为日志的实现。这意味着在大多数情况下,你无需做额外的配置即可开始记录日志。下面是一个简要的指南,包括如何在Spring Boot应用中使用SLF4J和Logback,以及一些实际的代码示例。

分享学习 2182

Logback 日志框架详解

环境隔离:严格区分开发/生产环境配置性能优先:必用异步日志+合理队列大小安全合规:敏感信息必须脱敏可观测性:集成TraceID便于排查智能运维:对接监控系统实现自动告警存储优化:采用压缩归档策略灵活调整:支持运行时动态调级性能提升50%+存储节省70%+问题定位效率提升3倍安全合规100%达标。

cv:小怪 1310

学习日志框架之——搞懂logback

Logback是由log4j创始人设计的又一个开源日志组件。Logback当前分成三个模块:logback-core,logback- classic和logback-access。logback-core是其它两个模块的基础模块。logback-classic是log4j的一个改良版本。此外logback-classic完整实现SLF4J API。使你可以很方便地更换成其它日志系统如log4j或JDK14 Logging。

秃了也弱了 3030

日志之logback

日志之logback 1.1 简介 师出同门,与log4j一样,logback也是由Ceki Gülcü开发的开源日志组件,可以说是log4j的改进版;在现如今的项目中,logback的出现次数越来越多,是目前主流首选的日志记录工具。 1.2 logback结构 logback分成三个模块:logback-core,logback- classic,logback-access。 logba...

木村的博客 300

logback日志配置详解

这里对 logback 的日志配置文件做了一下总结。logback 整体的运行机制是非常复杂而庞大的,这里只对 配置文件的一些节点,做简单的介绍,希望能对大家 ,有所帮助!

jcc4261的博客 3243
上一篇: 使用枚举Enum代替int常量
下一篇: idea修改pom.xml没有重新导入maven的按钮
why_su
博客等级 码龄10年 86粉丝 38原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值