Springboot logback 日志打印配置文件,每个日志文件100M,之后滚动到下一个日志文件,日志保留30天(包含traceid)
全部配置
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<property name="LOG_HOME" value="log"/>
<property name="LOG_NAME" value="admin"/>
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<property name="CONSOLE_LOG_PATTERN"
value="${CONSOLE_LOG_PATTERN:-%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) [%X{traceid}] %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<property name="FILE_LOG_PATTERN"
value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} [%X{traceid}] ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<logger name="org.apache.catalina.startup.DigesterFactory" level="ERROR"/>
<logger name="org.apache.catalina.util.LifecycleBase" level="ERROR"/>
<logger name="org.apache.coyote.http11.Http11NioProtocol" level="WARN"/>
<logger name="org.apache.sshd.common.util.SecurityUtils" level="WARN"/>
<logger name="org.apache.tomcat.util.net.NioSelectorPool" level="WARN"/>
<logger name="org.eclipse.jetty.util.component.AbstractLifeCycle" level="ERROR"/>
<logger name="org.hibernate.validator.internal.util.Version" level="WARN"/>
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<FileNamePattern>${LOG_HOME}/${LOG_NAME}-info.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
<MaxFileSize>100MB</MaxFileSize>
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<FileNamePattern>${LOG_HOME}/${LOG_NAME}-error.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
<MaxFileSize>100MB</MaxFileSize>
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- 日志输出级别 -->
<root level="INFO">
<appender-ref ref="FILE"/>
<appender-ref ref="FILE_ERROR"/>
<appender-ref ref="STDOUT"/>
</root>
</configuration>
2. 定义日志参数
<property name="LOG_HOME" value="log"/>
<property name="LOG_NAME" value="admin"/>
LOG_HOME
: 日志打印存放在服务器的位置LOG_NAME
: 日志文件名称(用于区分项目)- 如admin,文件名为admin-info.2024-12-17.0.log和admin-error.2024-12-17.0.log
3. 日志格式
<property name="CONSOLE_LOG_PATTERN"
value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) [%X{traceid}] %clr(%t){cyan} %clr(:){faint} %m%n"/>
<property name="FILE_LOG_PATTERN"
value="%d{yyyy-MM-dd HH:mm:ss.SSS} %5p [%X{traceid}] %t : %m%n"/>
控制台和文件的日志输出格式分别定义,确保输出内容既清晰又易读。格式化内容包括:
%d{}
- 格式:
%d{yyyy-MM-dd HH:mm:ss.SSS}
- 含义:记录日志的时间戳,格式化为
年-月-日 小时:分钟:秒.毫秒
。 - 动态属性:
${LOG_DATEFORMAT_PATTERN}
,支持配置化日期格式,默认为yyyy-MM-dd HH:mm:ss.SSS
。
- 格式:
%clr()
- 含义:为控制台输出添加颜色区分。
{faint}
,{magenta}
,{cyan}
等指定不同的颜色样式。 - 例如:
%clr(${PID:- }){magenta}
用洋红色显示进程 ID。
- 含义:为控制台输出添加颜色区分。
%5p
- 含义:显示日志级别(如 INFO、ERROR)。
%5p
表示固定宽度为 5 个字符,右对齐。
- 含义:显示日志级别(如 INFO、ERROR)。
[%X{traceid}]
- 含义:显示上下文变量
traceid
的值。 - 用法:通过
MDC.put("traceid", "value")
在日志记录中注入traceid
。
- 含义:显示上下文变量
%t
和%15.15t
- 含义:显示线程名称。
%15.15t
表示线程名称固定宽度为 15 个字符,超出部分会截断。
%-40.40logger{39}
- 含义:记录日志的类名,显示宽度范围为 40 个字符。
{39}
指定类名路径最大为 39 层。
%m
和%n
%m
:日志消息内容。%n
:换行符。
${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}
- 含义:异常栈信息的格式化输出,默认为 Logback 的
WhitespaceThrowableProxyConverter
。
- 含义:异常栈信息的格式化输出,默认为 Logback 的
3.1 生成traceid
import com.applets.manager.core.constant.Constants;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.UUID;
/**
* @author zr
*/
@Component
@Slf4j
@Order(1)
public class TraceFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
MDC.put(Constants.TRACE_ID, this.getTraceId(request));
filterChain.doFilter(request, response);
}
private String getTraceId(HttpServletRequest request) {
String traceId = request.getHeader(Constants.TRACE_ID);
if (StringUtils.isEmpty(traceId)) {
traceId = UUID.randomUUID().toString();
}
return traceId;
}
}
public class Constants {
public static final String TRACE_ID = "traceid";
/**
* 构造函数私有化,避免被实例化
*/
private Constants() {
}
}
4. 日志级别与输出
<root level="INFO">
<appender-ref ref="FILE"/>
<appender-ref ref="FILE_ERROR"/>
<appender-ref ref="STDOUT"/>
</root>
根日志记录器设置为 INFO
级别,并将日志分别输出到文件和控制台:
STDOUT
: 控制台输出,方便开发时实时查看。FILE
: 记录INFO
及以上级别的日志到文件。FILE_ERROR
: 专门记录ERROR
级别日志,便于快速定位严重问题。
5. 文件滚动策略
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<FileNamePattern>${LOG_HOME}/${LOG_NAME}-info.%d{yyyy-MM-dd}.%i.log</FileNamePattern>
<MaxFileSize>100MB</MaxFileSize>
<MaxHistory>30</MaxHistory>
</rollingPolicy>
- MaxFileSize:表示单个日志文件的最大大小。当日志文件达到 100MB 时,它将被滚动,生成一个新的文件。这个参数确保日志文件不会因为过大而占用过多的磁盘空间,避免出现性能问题。
- MaxHistory:表示保留的最大日志历史天数。这里设置为
30
,意味着系统会保留过去 30 天的日志文件。超过 30 天的日志文件将被自动删除,从而节省存储空间。这个设置防止了日志文件积累过多,确保只有最近的日志会被保存。
6. 实际日志实例
2024-12-19 16:31:44.222 INFO [39a89345-5f86-4ddd-9d68-96ae5cffd126] 15763 --- [http-nio-8081-exec-2] c.v.manager.api.filter.TraceFilter : 清除用户数据
- 时间戳:
2024-12-19 16:31:44.222
- 日志级别:
INFO
- traceid:
39a89345-5f86-4ddd-9d68-96ae5cffd126
- 进程 ID:
15763
- 线程名称:
http-nio-8081-exec-2
- 日志类路径:
c.v.manager.api.filter.TraceFilter
- 日志消息:
清除用户数据
- Springboot logback 日志打印配置文件,每个日志文件100M,之后滚动到下一个日志文件,日志保留30天(包含traceid)_%-40.40logger{39}-CSDN博客
-
Logback中文文档(三):配置
在第一部分,我们将介绍配置 logback 的各种方法,给出了很多配置脚本例子。在第二部分,我们将介绍 Joran,它是一个通用配置框架,你可以在自己的项目里使用 Joran。
Logback里的配置
把记录请求插入程序代码需要相当多的计划和努力。有观察显示大约 4%的代码是记录。
所以即使是一个中等规模的应用程序也会包含数以千计的记录语句。考虑到数量庞大,我们需要使用工具来管理记录语句。
Logback 可以通过编程式配置,或用 XML 格式的配置文件进行配置。
Logback 采取下面的步骤进行自我配置:- 尝试在 classpath 下查找文件 logback-test.xml;
- 如果文件不存在,则查找文件 logback.xml;
- 如果两个文件都不存在,logback 用 BasicConfigurator 自动对自己进行配置,这会导致记录输出到控制台。
第三步也是最后一步是为了在缺少配置文件时提供默认(但基本的)记录功能。
自动配置
最简单的配置方法就是使用默认配置。
BasicConfigurator 用法的简单例子:
((logback-examples/src/main/java/chapters/configuration/MyApp1.java))import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MyApp1 { final static Logger logger = LoggerFactory.getLogger(MyApp1.class); public static void main(String[] args) { logger.info("Entering application."); Foo foo = new Foo(); foo.doIt(); logger.info("Exiting application."); } } 该 类 定义 了一 个静 态变 量 logger ,然 后实 例 化一 个 Foo 对 象 。Foo 类 如 下
((logback-examples/src/main/java/chapters/configuration/Foo.java)):import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Foo { static final Logger logger = LoggerFactory.getLogger(Foo.class); public void doIt() { logger.debug("Did it again!"); } } 假设配置文件 logback-test.xml 和 logback.xml 都不存在,那么 logback 默认地会调用BasicConfigurator , 创 建一 个 最小 化配 置 。最 小化 配置 由 一个 关联 到 根 logger 的ConsoleAppender 组成。输出用模式为%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 的 PatternLayoutEncoder 进行格式化。还有,根 logger 默认级别是 DEBUG。
因此,chapters.configuration.MyApp1 运行后的输出应当类似于:16:06:09.031 [main] INFO chapters.configuration.MyApp1 - Entering application. 16:06:09.046 [main] DEBUG chapters.configuration.Foo - Did it again! 16:06:09.046 [main] INFO chapters.configuration.MyApp1 - Exiting application. MyApp1 程序通过调用 org.slf4j.LoggerFactory 类和 org.slf4j.Logger 类连接到 logback,取得想 要的 logger, 然后 继续 。注 意 Foo 类 对 logback 唯 一的 依赖 是通 过引入org.slf4j.LoggerFactory 和 org.slf4j.Logger。
用logback-test.xml 或 logback.xml自动配置
前面提到过,如果 classpath 里有 logback-test.xml 或 logback.xml,logback 会试图用它进行自我配置。下面的配置文件与刚才的 BasicConfigurator 等效。
示例:基本配置文件(logback-examples/src/main/java/chapters/configuration/sample0.xml)<configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder by default --> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n </pattern> </encoder> </appender> <root level="debug"> <appender-ref ref="STDOUT"/> </root> </configuration> 把 sample0.xml 重命名为 logback.xml 或 logback-test.xml,放到 classpath 里,运行后会和上例的输出几乎一样。
自动打印警告和错误消息
当解析配置文件有警告或出错时,logback 会在控制台上自动打印状态数据。如果没有警告或错误,你还是想检查 logback 的内部状态的话,可以调用 StatusPrinter 的 print()方法。
MyApp2 程序等价于 MyApp1,只是多了两行打印内部状态数据的代码。
示例:打印 logback 的内部状态信息(logback-examples/src/main/java/chapters/configuration/MyApp2.java)public static void main(String[] args) { // assume SLF4J is bound to logback in the current environment LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); // print logback's internal status StatusPrinter.print(lc); logger.info("Entering application."); Foo foo = new Foo(); foo.doIt(); logger.info("Exiting application."); } 如果一切顺利,控制台上会输出如下:
17:44:58,578 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback-test.xml] 17:44:58,671 |-INFO in ch.qos.logback.classic.joran.action.ConfigurationAction - debug attribute not set 17:44:58,671 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender] 17:44:58,687 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [STDOUT] 17:44:58,812 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Popping appender named [STDOUT] from the object stack 17:44:58,812 |-INFO in ch.qos.logback.classic.joran.action.LevelAction - root level set to DEBUG 17:44:58,812 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [STDOUT] to Logger[root] 17:44:58.828 [main] INFO chapters.configuration.MyApp2 - Entering application. 17:44:58.828 [main] DEBUG chapters.configuration.Foo - Did it again! 17:44:58.828 [main] INFO chapters.configuration.MyApp2 - Exiting application. 在输出的最后面,你可以看到上例输出的内容。你也应当注意到 logback 的内部消息,也就是 Status 对象,它可以方便地访问 logback 的内部状态。
可以不用从代码里调用 StatusPrinter,而是在配置文件里进行相关配置,即使没有出现错误。方法是,设置 configuration 元素的 debug 属性为 true。请注意 debug 属性只与状态数据有关,它不影响 logback 的配置,更不会影响记录级别。
示例:debug 模式的基本配置(logback-examples/src/main/java/chapters/configuration/sample1.xml)<configuration debug="true"> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <!-- encoders are assigned by default the type ch.qos.logback.classic.encoder.PatternLayoutEncoder --> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n </pattern> </encoder> </appender> <root level="debug"> <appender-ref ref="STDOUT" /> </root> </configuration> 把 configuration 元素的 debug 属性设为 true 后,会输出状态信息,但是前提是:
- 找到了配置文件;
- 配置文件是格式化良好的 XML。
如果其中任一条件未满足,Joran 就会因为配置文件不可读而无法读取 debug 属性。如果找到了配置文件,但却不是格式化良好的,那么 logback 会检测出错误并把内部状态打印到控制台。然而,如果找不到配置文件,由于这不是个严重的错误,logback 不会自动打印状态数据。使用编程式的主动调用 StatusPrinter.print()可以确保始终打印状态信息,如MyApp2。
把默认配置文件的位置作为系统属性进行指定
设置名为 logback.configurationFile 的系统属性,把默认配置文件的位置作为属性值,这种方法也可以。属性值即配置文件位置可以是个 URL、classpath 里的一个资源,或者是程序外部的文件路径。
java -Dlogback.configurationFile=/path/to/config.xml chapters.configuration.MyApp1 配置文件修改后自动重新加载
如果设置成自动重新加载,logback-classic 会扫描配置文件里的变化,并且当发生变化后进行重新配置。设置访方法是设 configuration 元素的 scan 属性为 true。
示例:扫描配置文件的变化并自动重新配置(logback-examples/src/main/java/chapters/configuration/scan1.xml)<configuration scan="true"> ... </configuration> 默认情况下,每隔一分钟扫描一次。configuration 元素的 scanPeriod 属性控制扫描周期,其值可以带时间单位,包括:milliseconds、seconds、minutes 和 hours。
示例:指定不同的扫描周期(logback-examples/src/main/java/chapters/configuration/scan2.xml)<configuration scan="true" scanPeriod="30 seconds"> ... </configuration> 如果没写明时间单位,则默认为毫秒。
内部实现是这样的,当设置扫描属性为 true 时,会安装一个叫 ReconfigureOnChangeFilter的 TurboFilter。每次调用 logger 的打印方法时,都会进行扫描。比如,当名为 myLogger 的logger执行“myLogger.debug("hello");”时,如果scan属性为true,则ReconfigureOnChangeFilter会被调用。而且,即使 myLogger 的 debug 级别被禁用了,仍然会调用上述过滤器。
考虑到在任何 logger 在每次被调用时都要调用 ReconfigureOnChangeFilter,这个过滤器的性能就变得十分关键了。为提高性能,不会在每个 logger 被调用时去检查是否需要扫描,而是每隔 16 次记录操作进行一次检查。简言之,当配置文件改变后,它会被延时重新加载,延时时间由扫描间隔时间和一些 logger 调用所决定。直接调用 JoranConfigurator
Logback 依赖 Joran,Joran 是 logback-core 的一部分,是个配置类库。Logback 的默认配置机制是调用JoranConfigurator对classpath上的默认配置文件进行处理。不管出于什么理由,如果你想重新实现 logback 的默认配置机制的话,你可以直接调用 JoranConfigurator。下面没的程序 MyApp3 就调用了 JoranConfigurator 对作为参数传入的配置文件进行处理。
示例:直接调用 JoranConfigurator(logback-examples/src/main/java/chapters/configuration/MyApp3.java)package chapters.configuration; /** * Demonstrates programmatic invocation of Joran. */ import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.joran.JoranConfigurator; import ch.qos.logback.core.joran.spi.JoranException; import ch.qos.logback.core.util.StatusPrinter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MyApp3 { final static Logger logger = LoggerFactory.getLogger(MyApp3.class); public static void main(String[] args) { // assume SLF4J is bound to logback in the current environment LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); try { JoranConfigurator configurator = new JoranConfigurator(); configurator.setContext(lc); // the context was probably already configured by default // configuration rules lc.reset(); configurator.doConfigure(args[0]); } catch (JoranException je) { // StatusPrinter will handle this } StatusPrinter.printInCaseOfErrorsOrWarnings(lc); logger.info("Entering application."); Foo foo = new Foo(); foo.doIt(); logger.info("Exiting application."); } } 本程序直接取得 LoggerContext,创建新 JoranConfigurator 并设置它要操作的上下文,重置 logger 上下文,最后要求配置器用参数中的配置文件对上下文进行配置。同时打印了内部状态数据。
查看状态消息
Logback 把内部数据放在一个 StatusManager 对象里,并通过 LoggerContext 访问。
StatusManager 通过 logback 上下文来访问所有数据对象。为把内存占用保持在合理的范围内,默认的 StatusManager 实现将状态消息按头和尾两部分存储。头部存储开始的 H 条状态消息,尾部存储后面的 T 条消息。现在的 H=T=150,将来或许会改变。
Logback-classic 带了一个叫 ViewStatusMessagesServlet 的 Servlet,它以 HTML 表格的格式打印与当前 LoggerContext 关联的 StatusManager 的内容。示例如下。要加到自己的 web 应用程序里,可以在 WEB-INF/web.xml 里添加如下内容:
<servlet> <servlet-name>ViewStatusMessages</servlet-name> <servlet-class>ch.qos.logback.classic.ViewStatusMessagesServlet </servlet-class> </servlet> <servlet-mapping> <servlet-name>ViewStatusMessages</servlet-name> <url-pattern>/lbClassicStatus</url-pattern> </servlet-mapping> 访问地址是 http://host/yourWebapp/lbClassicStatus。
监听状态消息
你也可以为 StatusManager 附加一个 StatusListener,这样就能立即对状态消息作出响应,尤其对那些 logback 配置完成之后的消息。注册一个状态监听器可以方便地实现对 logback
内部状态的无人监管。
Logback 带了一个叫 OnConsoleStatusListener 的 StatusListener 实现,可以把状态消息打印到控制台。
下例演示了如何为 StautsManager 注册一个 OnConsoleStatusListener 实例。LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); StatusManager statusManager = lc.getStatusManager(); OnConsoleStatusListener onConsoleListener = new OnConsoleStatusListener(); statusManager.add(onConsoleListener); 注意注册了的状态监听器只会接收被注册之后的状态消息,不会注册之前的消息。
也可以在配置文件里注册一个或多个状态监听器。如下面的例子。
示例:注册状态监听器(logback-examples/src/main/java/chapters/configuration/onConsoleStatusListener.xml)<configuration> <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" /> ... the rest of the configuration file </configuration> 还可以通过设置 Java 系统属性“logback.statusListenerClass”注册状态监听器,例如,
java -Dlogback.statusListenerClass=ch.qos.logback.core.status.OnConsoleStatusListener ... 配置文件语法
到目前为止,正如你已经在这份手册里看到的不少例子,logback 允许你重新定义记录行为而不必重新编译你的代码。实际上,你可以轻易地配置 logback,比如禁用程序里某些地方的记录功能,或者直接输出到一个 UNIX 系统守护进程、数据库、日志查看器,或把记录事件发送到远程 logback 服务器,远程 logback 服务器按照其本地策略进行记录,比如把记录时间发送到第二个 logback 服务器。
本节剩余部分介绍配置文件的语法。
Logback 配置文件的语法非常灵活。正因为灵活,所以无法用 DTD 或 XML schema 进行定义。尽管如此,可以这样描述配置文件的基本结构:以开头,后面有零个或多个元素,有零个或多个元素,有最多一个元素。如下图所示:标记名大小写敏感性
从 logback 0.9.17 版起,标记名不区分大小些。比如,
<logger>
、<Logger>
和<LOGGER>
都是合法元素且表示同一个意思。按照隐式规则,标记名除了首字母外要区分大小写。因此,<xyz>
与<Xyz>
等价,但不等价于<xYz>
。隐式规则一般遵循 Java 世界里常用的驼峰命名规则。因为很难确定一个标记什么时候与显式动作相关,什么时候又与隐式动作相关,所以很难说 XML 标记是否是大小写敏感。如果你不确定标记名的大小写,就用驼峰命名法,基本不会错。配置logger或
<logger>
元素Logger 是用
<logger>
元素配置的。<logger>
元素有且仅有一个 name 属性、一个可选的level 属性和一个可选的 additivity 属性。
Level 属性的值大小写无关,其值为下面其中一个字符串:TRACE、DEBUG、INFO、WARN、ERROR、ALL 和 OFF。还可以是一个特殊的字符串“INHERITED”或其同义词“NULL”,表示强制继承上级的级别。<logger>
元素可以包含零个或多个<appender-ref>
元素,表示这个 appender 会被添加到该 logger。强调一下,每个用元素声明的 logger,首先会移除所有 appender,然后才添加引用了的 appender,所以如果 logger 没有引用任何 appender,就会失去所有 appender。配置根logger,或
<root>
元素<root>
元素配置根 logger。该元素有一个 level 属性。没有 name 属性,因为已经被命名
为“ROOT”。
Level 属性的值大小写无关,其值为下面其中一个字符串:TRACE、DEBUG、INFO、WARN、ERROR、ALL 和 OFF。注意不能设置为“INHERITED” 或“NULL”。<logger>
元素可以包含零个或多个<appender-ref>
元素。与<logger>
元素类似,声明<root>
元素后,会先关闭然后移除全部当前 appender,只引用声明了的 appender。如果 root 元素没有引用任何 appender,就会失去所有 appender。示例
假设我们不想看到“chapters.configuration”包里的任何组件的任何 DEBUG 信息,可以设置如下:
示例:设置 logger 级别(logback-examples/src/main/java/chapters/configuration/sample2.xml)<configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <!-- encoders are assigned by default the type ch.qos.logback.classic.encoder.PatternLayoutEncoder --> <encoder> <pattern> %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n </pattern> </encoder> </appender> <logger name="chapters.configuration" level="INFO" /> <!-- Strictly speaking, the level attribute is not necessary since --> <!-- the level of the root level is set to DEBUG by default. --> <root level="DEBUG"> <appender-ref ref="STDOUT" /> </root> </configuration> 对于 MyApp3 应用上述配置文件后,输出如下:
17:34:07.578 [main] INFO chapters.configuration.MyApp3 - Entering application. 17:34:07.578 [main] INFO chapters.configuration.MyApp3 - Exiting application. 注意由名为“chapters.configuration.Foo”的 logger 生成的 DEBUG 级别的信息都被屏蔽了。
你 可 以为 任意 数 量的 logger 设 置级 别。 下面 的 配置 文件 里, 我 们为 logger“chapters.configuration”设置级别为 INFO,同时设置 logger“chapters.configuration.Foo”级别为 DEBUG。
示例:设置多个 logger 的级别<configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <!-- encoders are assigned by default the type ch.qos.logback.classic.encoder.PatternLayoutEncoder --> <encoder> <pattern> %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n </pattern> </encoder> </appender> <logger name="chapters.configuration" level="INFO"/> <logger name="chapters.configuration.Foo" level="DEBUG"/> <root level="DEBUG"> <appender-ref ref="STDOUT"/> </root> </configuration> 对于 MyApp3 应用上述配置文件后,输出如下:
17:39:27.593 [main] INFO chapters.configuration.MyApp3 - Entering application. 17:39:27.593 [main] DEBUG chapters.configuration.Foo - Did it again! 17:39:27.593 [main] INFO chapters.configuration.MyApp3 - Exiting application. 经 JoranConfigurator 用 sample3.xml 对 logback 进行配置后,各 logger 和各自级别如下表所示:
Logger 名 分配级别 有效级别 root DEBUG DEBUG chapters.configuration INFO INFO chapters.configuration.MyApp3 null INFO chapters.configuration.Foo DEBUG DEBUG MyApp3类的INFO级别的记录语句和Foo.doIt()的DEBUG消息都被启用。注意根 logger总是设为非 null 值,默认为 DEBUG。
注意,基本选择规则依赖于被调用的logger的有效级别,而不是 appender所关联的 logger的级别。Logback 首先判断记录语句是否被启用,如果启用,则调用logger 等级里的 appender,无视 logger 的级别。配置文件 sample4.xml 演示了这一点。
示例:logger 级别(logback-examples/src/main/java/chapters/configuration/sample4.xml)<configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <!-- encoders are assigned by default the type ch.qos.logback.classic.encoder.PatternLayoutEncoder --> <encoder> <pattern> %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n </pattern> </encoder> </appender> <logger name="chapters.configuration" level="INFO"/> <root level="OFF"> <appender-ref ref="STDOUT"/> </root> </configuration> 用 sample4.xml 对 logback 进行配置后,各 logger 和各自级别如下表所示:
Logger 名 分配级别 有效级别 root OFF OFF chapters.configuration INFO INFO chapters.configuration.MyApp3 null INFO chapters.configuration.Foo null INFO 配置里唯一的 appender “STDOUT”,被关联到级别为 OFF 的根 logger,但是运行 MyApp3后会输出:
17:52:23.609 [main] INFO chapters.configuration.MyApp3 - Entering application. 17:52:23.609 [main] INFO chapters.configuration.MyApp3 - Exiting application. 根 logger 的级别不起任何作用,是因为 chapters.configuration.MyApp3 里的 logger 和chapters.configuration.Foo 类的 INFO 级别都是启用的。附注:logger“chapters.configuration”即使没有任何 Java 代码直接引用它也会存在,全因为在配置文件里声明了它。
配置 Appender
Appender 用
<appender>
元素配置,该元素必要属性 name 和 class。
name 属性指定 appender 的名称,class 属性指定 appender 类的全限定名。<appender>
元素可以包含零个或多个<layout>
元素、零个或多个<encoder>
元素和零个或多个<filter>
元素。除了这三个常用元素之外,还可以包含 appender 类的任意数量的 javabean属性。下图演示了常用结构,注意对 javabean 属性的支持在图中不可见。<layout>
元素的 class 属性是必要的,表示将被实例化的 layout 类的全限定名。和<appender>
元素一样,<layout>
元素可以包含 layout 的javabean 属性。因为太常用了,所以当layout 是 PatternLayout 时,可以省略 class 属性。<encoder>
元素 class 属性是必要的,表示将被实例化的 encoder 类的全限定名。因为太常用了,所以当当 encoder 是 PatternLayoutEncoder 时,可以省略 class 属性。
记录输出到多个 appender 很简单,先定义各种 appender,然后在 logger 里进行引用,就行了。如下面的配置文件所示:
示例:多个 logger (logback-examples/src/main/java/chapters/configuration/multiple.xml)<configuration> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>myApp.log</file> <!-- encoders are assigned by default the type ch.qos.logback.classic.encoder.PatternLayoutEncoder --> <encoder> <pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n </pattern> </encoder> </appender> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%msg%n</pattern> </encoder> </appender> <root level="debug"> <appender-ref ref="FILE" /> <appender-ref ref="STDOUT" /> </root> </configuration> 该配置文件定义了两个 appender,分别是“FILE”和“STDOUT”。
“ FILE” 这 个 appender 把 记 录 输 出 到 文 件 “ myapp.log ”, 它 的 encoder 是PatternLayoutEncoder,输出了日期、级别、线程名、logger 名、文件名及记录请求的行号、消息和行分隔符。
“STDOUT”这个 appender 把记录输出到控制台,它的 encoder 只是输出消息和行分隔符。
注意每个 appender 都有自己的 encoder。Encoder 通常不能被多个 appender 共享,layout也是。所以,logback 的配置文件里没有共享 encoder 或 layout 的语法。Appender累积
默认情况下,appender 是可累积的:logger 会把记录输出到它自身的 appender 和它所有祖先的 appender。因此,把同一 appender 关联到多个 logger 会导致重复输出。
示例:重复的 appender
(logback-examples/src/main/java/chapters/configuration/duplicate.xml)<configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern> %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n </pattern> </encoder> </appender> <logger name="chapters.configuration"> <appender-ref ref="STDOUT"/> </logger> <root level="debug"> <appender-ref ref="STDOUT"/> </root> </configuration> 用 duplicate.xml 配置 MyApp3 后输出如下:
14:25:36.343 [main] INFO chapters.configuration.MyApp3 - Entering application. 14:25:36.343 [main] INFO chapters.configuration.MyApp3 - Entering application. 14:25:36.359 [main] DEBUG chapters.configuration.Foo - Did it again! 14:25:36.359 [main] DEBUG chapters.configuration.Foo - Did it again! 14:25:36.359 [main] INFO chapters.configuration.MyApp3 - Exiting application. 14:25:36.359 [main] INFO chapters.configuration.MyApp3 - Exiting application. 看到重复输出了吧?名为 STDOUT 的 appender 被关联给两个 logger,分别是根和chapters.configuration。由于根 logger 是所有 logger 的祖先,hapters.configuration 是chapters.configuration.MyApp3 和 chapters.configuration.Foo 之父,所以这两个 logger 的记录请求会被输出两次。一次是因为 STDOUT 被关联到 chapters.configuration,一次是因为被关联到根 logger。
Appender 的叠加性对新手来说并不是陷阱,反而是非常方便的。举例来说,你可以让某些系统里所有 logger 的记录信息出现在控制台,却让某些特定 logger 的记录信息发到一个特定的 appender。
示例:多个 appender(logback-examples/src/main/java/chapters/configuration/restricted.xml)<configuration> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>myApp.log</file> <!-- encoders are assigned by default the type ch.qos.logback.classic.encoder.PatternLayoutEncoder --> <encoder> <pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n </pattern> </encoder> </appender> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%msg%n</pattern> </encoder> </appender> <logger name="chapters.configuration"> <appender-ref ref="FILE"/> </logger> <root level="debug"> <appender-ref ref="STDOUT"/> </root> </configuration> 本例中,控制台 appender 会输出所有消息(出自系统里的所有 logger),但是只有来自chapters.configuration 这个 logger 的消息会输出到文件 myApp.log。
覆盖默认的累积行为
如果你觉得默认的累积行为不合适,可以设置叠加性标识为 false 以关闭它。这样的话,logger 树里的某个分支可以输出到与其他 logger 不同的 appender。
示例:叠加性标识(logback-examples/src/main/java/chapters/configuration/additivityFlag.xml)<configuration> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>foo.log</file> <encoder> <Pattern> %date %level [%thread] %logger{10} [%file : %line] %msg%n </Pattern> </encoder> </appender> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <Pattern>%msg%n</Pattern> </encoder> </appender> <logger name="chapters.configuration.Foo" additivity="false"> <appender-ref ref="FILE"/> </logger> <root level="debug"> <appender-ref ref="STDOUT"/> </root> </configuration> 本例中,logger“chapters.configuration.Foo”关联 appender“FILE”,它的叠加性标记为false,这样它的记录输出仅会被发送到 appender“FILE”,不会被发送到更高 logger 等级关联的 appender。其他 logger 不受此影响。
用 additivityFlag.xml 配 置 MyApp3 , 运 行 后 , 控 制 台 上 由 输 出 由“chapters.configuration.MyApp3”产生的记录。而 logger“ chapters.configuration.Foo”将且仅仅将输出到文件 foo.log。设置上下文名称
每个 logger 都关联到 logger 上下文。默认情况下,logger 上下文名为“default”。但是你可以借助配置指令设置成其他名字。注意一旦设置 logger 上下文名称后,
不能再改。设置上下文名称后,可以方便地区分来自不同应用程序的记录。
示例:设置上下文名称并显示它(logback-examples/src/main/java/chapters/configuration/contextName.xml)<configuration> <contextName>myAppName</contextName> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <Pattern>%d %contextName [%t] %level %logger{36} - %msg%n</Pattern> </encoder> </appender> <root level="debug"> <appender-ref ref="STDOUT"/> </root> </configuration> 本例演示了 logger 上下文的命名方法:在 layout 模式里添加“%contextName”就会输
出上下文的名称。变量替换
原则上,指定变量的地方就能够发生变量替换。变量替换的语法与 Unix shell 中的变量替换相似。位于“”与“”之间的字符串是键(key),取代键的值可以在同一配置文件里指定,也可以在外部文件或通过系统属性进行指定。例如,如果设系统属性“java.home.dir”为“/home/xyz”,那么每次当{java.home.dir}出现时都会被解释为“/home/xyz”。Logback自动定义了一个常用变量“${HOSTNAME}”。
属性被插入 logger 上下文
注意通过
<property>
元素定义的值实际上会被插入 logger 上下文。换句话说,这些值变成了 logger 上下文的属性。所以,它们对所有记录事件都可用,包括通过序列化方式被发送到远程主机的记录事件。
下面的例子在配置文件的开头声明了一个变量又名替换属性,它代表输出文件的位置,然后在后面的配置文件里使用它。
示例:简单变量替换(logback-examples/src/main/java/chapters/configuration/variableSubstitution1.xml)<configuration> <property name="USER_HOME" value="/home/sebastien"/> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>${USER_HOME}/myApp.log</file> <encoder> <pattern>%msg%n</pattern> </encoder> </appender> <root level="debug"> <appender-ref ref="FILE"/> </root> </configuration> 下一个例子用系统属性实现了同样的功能。属性没有在配置文件里声明,因此 logback会从系统属性里找。Java 系统属性用下面的命令行进行设置:
java -DUSER_HOME="/home/sebastien" MyApp2 示例:系统变量替换
(logback-examples/src/main/java/chapters/configuration/variableSubstitution2.xml)<configuration> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>${USER_HOME}/myApp.log</file> <encoder> <pattern>%msg%n</pattern> </encoder> </appender> <root level="debug"> <appender-ref ref="FILE" /> </root> </configuration> 当需要很多变量时,更方便的做法是在一个单独的文件里声明所有变量,如下例所示。
示例:文件变量替换(logback-examples/src/main/java/chapters/configuration/variableSubstitution3.xml)<configuration> <property file="src/main/java/chapters/configuration/variables1.properties"/> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>${USER_HOME}/myApp.log</file> <encoder> <pattern>%msg%n</pattern> </encoder> </appender> <root level="debug"> <appender-ref ref="FILE"/> </root> </configuration> 这个配置文件包含对文件“variables1.properties”的引用,该文件里的变量会被读入
logback 配置文件的上下文里。
文件“variables1.properties”内容类似于:
示例:变量文件
(logback-examples/src/main/java/chapters/configuration/variables1.properties)USER_HOME=/home/sebastien 还可以不引用文件,而是引用 class path 上的资源。
<configuration> <property resource="resource1.properties"/> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>${USER_HOME}/myApp.log</file> <encoder> <pattern>%msg%n</pattern> </encoder> </appender> <root level="debug"> <appender-ref ref="FILE"/> </root> </configuration> 嵌套变量替换
Logback 支持嵌套变量替换。这里的嵌套是指变量的值里包含对其他变量的引用。假设你希望用变量指定目的地目录和文件名,然后用一个变量“destination”组合这两个变量,如下面所示。
示例:嵌套变量替换(logback-examples/src/main/java/chapters/configuration/variables2.properties)USER_HOME=/home/sebastien fileName=myApp.log destination=${USER_HOME}/${fileName} 注意在上面的属性文件里, “destination”由另外两个变量“USER_HOME”和“fileName”组合而成。
示例:文件变量替换(logback-examples/src/main/java/chapters/configuration/variableSubstitution4.xml)<configuration> <property file="src/main/java/chapters/configuration/variables2.properties"/> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>${destination}</file> <encoder> <pattern>%msg%n</pattern> </encoder> </appender> <root level="debug"> <appender-ref ref="FILE"/> </root> </configuration> 变量的默认替换值
在某些特定情况下,最好给变量一个默认值,以免变量未被声明或值为 null。Bash shell用“:-”指定默认值。例如,假设“aKey”未被声明,那么“${aKey:-golden}”将被解释为“golden”。
HOSTNAME 属性
HOSTNNAME 属性因为很常用,所以在配置过程中被自动定义。
设置时间戳
元素 timestamp 可以定义表示一个当前日期和时间的属性。
在运行中定义属性
可以配置文件里用
<define>
元素定义属性。<define>
元素有两个必要属性:name 和 class。
name 属性代表属性的名称,class 属性代表 PropertyDefiner 接口的任意实现。PropertyDefiner接口的 getPropertyValue()方法返回的值就是属性值。
如下例。<configuration> <define name="rootLevel" class="a.class.implementing.PropertyDefiner"> <aProperty>of a.class.implementing.PropertyDefiner</aProperty> </define> <root level="${rootLevel}"/> </configuration> Logback 目前还没有提供 PropertyDefiner 接口的具体实现,只是为动态定义属性提供了一种方法。
配置文件里的条件 化处理
开发者经常需要针对不同的环境在不同的配置文件里换来换去,比如开发、测试和生产环境。这些配置文件大同小异。为避免重复劳动,logback 支持在配置文件里进行条件化处理,用、和这些元素可以让一个配置文件适用于多个环境。
条件语句一般格式如下。<configuration> <!-- if-then form --> <if condition="some conditional expression"> <then> ... </then> </if> <!-- if-then-else form --> <if condition="some conditional expression"> <then> ... </then> <else> ... </else> </if> </configuration> 其中“condition”是 java 表达式,只允许访问上下文属性和系统属性。对于作为参数传入的键,property()方法或其等价的 p()方法将返回属性的字符串值。例如,想访问属性键为“k”的值,你可以用 property("k")或等价的 p("k")。如果键为“k”的属性未被定义,property方法将返回空字符串而不是 null,这样避免了检查 null 值。
下一个例子里,ConsoleAppender 被关联到根 logger,但是前提条件是 HOSTNAME 属性的值是“torino”。注意名为“FILE”的 FileAppender 在任何情况下都被关联到根 logger。<configuration> <if condition='property("HOSTNAME").contains("torino")'> <then> <appender name="CON" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d %-5level %logger{35} - %msg %n</pattern> </encoder> </appender> <root> <appender-ref ref="CON"/> </root> </then> </if> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>${randomOutputDir}/conditional.log</file> <encoder> <pattern>%d %-5level %logger{35} - %msg %n</pattern> </encoder> </appender> <root level="ERROR"> <appender-ref ref="FILE"/> </root> </configuration> <configuration>
元素之内的任何地方都支持条件化处理。也支持嵌套的 if-then-else 语句。
然而,加入过多的条件语句会导致 XML 文件非常难读。从JNDI获取变量
在某些特定情况下,你也许利用 JNDI 里存储的 env 项,指令会从JNDI里取得 env 项,然后用 as 属性把它们作为变量。
示例:通过 JNDI 取得 env 项并作为属性插入(logback-examples/src/main/java/chapters/configuration/insertFromJNDI.xml)<configuration> <insertFromJNDI env-entry-name="java:comp/env/appName" as="appName"/> <contextName>${appName}</contextName> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d %contextName %level %msg %logger{50}%n</pattern> </encoder> </appender> <root level="DEBUG"> <appender-ref ref="CONSOLE"/> </root> </configuration> 本例中,env 项“java:comp/env/appName”被作为“appName”属性插入到配置文件。
注意先是<insertFromJNDI>
指令插入的“appName”属性,然后<contextName>
指令把“appName”的值设成“contextName”。文件包含
Joran 支持在配置文件里包含其他文件。方法是声明元素,如下所示:
示例:文件包含
(logback-examples/src/main/java/chapters/configuration/containingConfig.xml)<configuration> <include file="src/main/java/chapters/configuration/includedConfig.xml"/> <root level="DEBUG"> <appender-ref ref="includedConsole"/> </root> </configuration> 被包含的文件必须把它的元素嵌套在元素里。例如,可以这样声明ConsoleAppender:
示例:文件包含(logback-examples/src/main/java/chapters/configuration/includedConfig.xml)<included> <appender name="includedConsole" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>"%d - %m%n"</pattern> </encoder> </appender> </included> 请再次注意元素是必需的。
被包含的内容可以是文件、资源或 URL。- 作为文件
用“file”属性包含一个文件。可以用相对路径,但是需要注意,当前目录是由应用程序决定的,与配置文件的路径必要的联系。 - 作为资源
用“resource”属性包含一个资源,也就是在 class path 上的文件。<include resource="includedConfig.xml" />
- 作为 URL
用“url”属性包括一个 URL。<include url="http://some.host.com/includedConfig.xml" />
【SpringBoot】【log】 自定义logback日志配置_springboot指定logback配置文件-CSDN博客
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="false" scanPeriod="30 seconds">
<property name="logDeletePath" value="${log.dir:-./logs}"/>
<property name="applicationName" value="eapi-worker"/>
<property name="logKeepCounts" value="90"/>
<property name="totalSizeCap" value="10GB"/>
<property name="maxFileSize" value="1KB"/>
<property name="cleanHistoryOnStart" value="false"/>
<property name="logDeleteGlob" value="*.log*"/>
<property name="projectPackage" value="com.zt"/>
<property name="projectLevel" value="INFO"/>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<!-- <include resource="org/springframework/boot/logging/logback/defaults.xml" /> -->
<!-- <include resource="org/springframework/boot/logging/logback/console-appender.xml" /> -->
<appender name="CONSOLE2" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>${CONSOLE_LOG_THRESHOLD}</level>
</filter>
<encoder>
<!-- <pattern>"%d{yyyy-MM-dd HH:mm:ss.SSS} %5p ${PID:-} --- %esb(){APPLICATION_NAME}%esb{APPLICATION_GROUP}[%t] ${LOG_CORRELATION_PATTERN:-}%-40.40logger{39}: %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"</pattern> -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %5p ${PID:-} --- %esb(){APPLICATION_NAME}%esb{APPLICATION_GROUP}[%15.15t] ${LOG_CORRELATION_PATTERN:-} %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}</pattern>
<charset>${CONSOLE_LOG_CHARSET}</charset>
</encoder>
</appender>
<appender name="LogFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>${FILE_LOG_THRESHOLD}</level>
</filter>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %5p ${LOG_CORRELATION_PATTERN:-} %-40.40logger{39} -》 %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}</pattern>
<charset>${FILE_LOG_CHARSET}</charset>
</encoder>
<file>${sys:LOG_PATH:-./logs}/${applicationName:-app}.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${sys:LOG_PATH:-./logs}/achive/${applicationName:-app}.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<cleanHistoryOnStart>${cleanHistoryOnStart:-true}</cleanHistoryOnStart>
<maxFileSize>${maxFileSize:-10MB}</maxFileSize>
<totalSizeCap>${totalSizeCap:-100MB}</totalSizeCap>
<maxHistory>${logKeepCounts:-30}</maxHistory>
</rollingPolicy>
</appender>
<appender name="WarnLogFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>WARN</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %5p ${PID:-} --- %esb(){APPLICATION_NAME}%esb{APPLICATION_GROUP}[%15.15t] ${LOG_CORRELATION_PATTERN:-} %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}</pattern>
<charset>${FILE_LOG_CHARSET}</charset>
</encoder>
<file>${sys:LOG_PATH:-./logs}/${applicationName:-app}.warn.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${sys:LOG_PATH:-./logs}/achive/${applicationName:-app}.warn.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<cleanHistoryOnStart>${cleanHistoryOnStart:-true}</cleanHistoryOnStart>
<maxFileSize>${maxFileSize:-10MB}</maxFileSize>
<totalSizeCap>${totalSizeCap:-100MB}</totalSizeCap>
<maxHistory>${logKeepCounts:-30}</maxHistory>
</rollingPolicy>
</appender>
<appender name="ERROR_LOG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %5p ${PID:-} --- %esb(){APPLICATION_NAME}%esb{APPLICATION_GROUP}[%15.15t] ${LOG_CORRELATION_PATTERN:-} %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}</pattern>
<charset>${FILE_LOG_CHARSET}</charset>
</encoder>
<file>${sys:LOG_PATH:-./logs}/${applicationName:-app}.err.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${sys:LOG_PATH:-./logs}/achive/${applicationName:-app}.err.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<cleanHistoryOnStart>${cleanHistoryOnStart:-true}</cleanHistoryOnStart>
<maxFileSize>${maxFileSize:-10MB}</maxFileSize>
<totalSizeCap>${totalSizeCap:-100MB}</totalSizeCap>
<maxHistory>${logKeepCounts:-30}</maxHistory>
</rollingPolicy>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<!-- <appender-ref ref="CONSOLE2"/> -->
<!-- <appender-ref ref="FILE" /> -->
</root>
<logger name="org.springframework" level="WARN"/>
<logger level="ERROR" name="org.apache.catalina.startup.DigesterFactory"/>
<logger level="ERROR" name="org.apache.catalina.util.LifecycleBase"/>
<logger level="WARN" name="org.apache.coyote.http11.Http11NioProtocol"/>
<logger level="WARN" name="org.apache.sshd.common.util.SecurityUtils"/>
<logger level="WARN" name="org.apache.tomcat.util.net.NioSelectorPool"/>
<logger level="ERROR" name="org.eclipse.jetty.util.component.AbstractLifeCycle"/>
<logger level="WARN" name="org.hibernate.validator.internal.util.Version"/>
<logger level="WARN" name="org.springframework.boot.actuate.endpoint.jmx"/>
<logger level="${logLevel}" name="com.zt" additivity="true">
<!-- <appender-ref ref="CONSOLE2"/> -->
<appender-ref ref="LogFile"/>
<appender-ref level="WARN" ref="WarnLogFile"/>
<appender-ref level="ERROR" ref="ERROR_LOG_FILE"/>
</logger>
</configuration>
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
2017-02-07 [No0000B9]C# 类型基础 值类型和引用类型 及其 对象复制 浅度复制vs深度复制 深入研究2
2017-02-07 [No0000B8]WPF或Winform调用系统Console控制台显示信息