javascript
Spring Boot 应用系列 5 -- Spring Boot 2 整合logback
上一篇我們梳理了Spring Boot 2 整合log4j2的配置過程,其中講到了Spring Boot 2原裝適配logback,并且在非異步環境下logback和log4j2的性能差別不大,所以對于那些日志量不算太高的項目來說,選擇logback更簡單方便。
1. pom.xml
pom.xml不需要添加任何依賴。
2. logback的配置文件
系統啟動時,logback按照下列順序加載第一個找到的配置文件:
(1) classpath:?logback-test.xml
(2) classpath:?logback.groovy
(3) classpath:?logback.xml
(4) 查詢com.qos.logback.classic.spi.Configurator接口的實現
(5)?如果以上均未找到,則加載默認配置。
但是與Spring Boot集成時,上面的配置文件加載較早,Spring Boot為logback提供了很多擴展(比如<springProfile>節點),這些擴展的加載要晚于上面的配置文件,所以Spring Boot建議使用logback-spring.xml作為配置文件。
3. 配置目標
類似上一篇整合log4j2時的情況,我們希望達成以下目標:
(1) 所有級別的日志均可以通過控制臺打印;
(2) 日志的存儲目錄格式為“/yyyy-MM/dd/”(“年-月/日/”),日志文件名稱包含小時;
(3) error級別的日志存儲在“/yyyy-MM/dd/app-error-{HH}.log”中,其中HH是日志發生的小時;
(4) 其他級別的日志存儲在“/yyyy-MM/dd/app-other-{HH}.log”中;
(5) 所有級別的日志同時以html格式存儲備份;
(6) 所有日志文件按照小時歸檔,一個小時一套文件(三個具體文件error,other);
(7) 設置日志文件的size上限,如果某一小時出現的日志特別多,超過size limit之后自動生成帶數字后綴的文件。
4.?logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?> <configuration debug="true"><property name="Log_Home" value="logs" /><property name="Log_Pattern" value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%thread] %-5level %logger - %msg%n" /><appender name="Console" class="ch.qos.logback.core.ConsoleAppender"><encoder><Pattern>${Log_Pattern}</Pattern><charset>UTF-8</charset></encoder></appender><appender name="RollingFile_Error" class="ch.qos.logback.core.rolling.RollingFileAppender"><prudent>true</prudent><encoder><pattern>${Log_Pattern}</pattern><charset>UTF-8</charset></encoder><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}/%d{yyyy-MM}/%d{dd}/app-error-%d{HH-mm}.%i.log</FileNamePattern><maxFileSize>10MB</maxFileSize><maxHistory>10080</maxHistory></rollingPolicy></appender><appender name="RollingFile_Other" class="ch.qos.logback.core.rolling.RollingFileAppender"><prudent>true</prudent><encoder><pattern>${Log_Pattern}</pattern><charset>UTF-8</charset></encoder><filter class="ch.qos.logback.classic.filter.LevelFilter"><level>ERROR</level><onMatch>DENY</onMatch><onMismatch>NEUTRAL</onMismatch></filter><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><FileNamePattern>${Log_Home}/%d{yyyy-MM}/%d{dd}/app-other-%d{HH-mm}.%i.log</FileNamePattern><maxFileSize>10MB</maxFileSize><maxHistory>10080</maxHistory></rollingPolicy></appender><appender name="RollingFile_HTML" class="ch.qos.logback.core.rolling.RollingFileAppender"><prudent>true</prudent><encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"><layout class="ch.qos.logback.classic.html.HTMLLayout"><pattern>%relative%thread%mdc%level%logger%msg</pattern></layout></encoder><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><FileNamePattern>${Log_Home}/%d{yyyy-MM}/%d{dd}/app-%d{HH-mm}.%i.html</FileNamePattern><maxFileSize>10MB</maxFileSize><maxHistory>10080</maxHistory></rollingPolicy></appender><root level="info"><appender-ref ref="Console" /><appender-ref ref="RollingFile_Error" /><appender-ref ref="RollingFile_Other" /><appender-ref ref="RollingFile_HTML" /></root> </configuration>(1)?logback的日志等級跟slf4j保持一致包括TRACE, DEBUG, INFO, WARN 和 ERROR;
(2)?<configuration>節點設置debug="true"屬性會在系統啟動時打印logback加載的狀態信息,如果logback加載過程中出現錯誤也會被打印出來,另外一種起同樣作用的配置為在<configuration>節點中配置:
<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />(3)?<property>節點屬于xml級別的全局配置變量;
(4)?<appender>節點中的<encoder>節點是日志事件的輸出格式化配置,其中<Pattern>屬性存儲格式化規則,其中的符號含義分別為:
[%d{yyyy-MM-dd HH:mm:ss.SSS}]: 時間格式;
[%thread]: 輸出日志的線程;
%-5level: 日志級別;
%logger: 日志調用者;
%msg: 日志內容;
%n: 換行符。
(5)?<prudent>節點默認值為false,如果設置為true可確保在多線程下對同一日志文件的操作的線程安全性,但是打開之后寫日志的性能會下降大約三倍。參考官網描述:
In prudent mode, FileAppender will safely write to the specified file, even in the presence of other FileAppender instances running in different JVMs, potentially running on different hosts. The default value for prudent mode is false. Prudent mode can be used in conjunction with RollingFileAppender although some restrictions apply.Prudent mode implies that append property is automatically set to true.Prudent more relies on exclusive file locks. Experiments show that file locks approximately triple (x3) the cost of writing a logging event. On an "average" PC writing to a file located on a local hard disk, when prudent mode is off, it takes about 10 microseconds to write a single logging event. When prudent mode is on, it takes approximately 30 microseconds to output a single logging event. This translates to logging throughput of 100'000 events per second when prudent mode is off and approximately 33'000 events per second in prudent mode.此外,prudent功能還有兩個限制:
a. 日志文件不能被壓縮;
b. 不能在<FileAppender>節點上設置file屬性。
(6)?<filter>節點用來配置過濾器,本例針對兩個appender分別配置了兩個<filter>,第一個filter只打印ERROR級別的日志,第二個filter只打印非ERROR級別的日志。此外logback還提供多種過濾器詳見logback官網。
關于onMatch和onMismatch,請看logback源碼:
1 /** 2 * Logback: the reliable, generic, fast and flexible logging framework. 3 * Copyright (C) 1999-2015, QOS.ch. All rights reserved. 4 * 5 * This program and the accompanying materials are dual-licensed under 6 * either the terms of the Eclipse Public License v1.0 as published by 7 * the Eclipse Foundation 8 * 9 * or (per the licensee's choosing) 10 * 11 * under the terms of the GNU Lesser General Public License version 2.1 12 * as published by the Free Software Foundation. 13 */ 14 package ch.qos.logback.core.filter; 15 16 import ch.qos.logback.core.spi.FilterReply; 17 18 public abstract class AbstractMatcherFilter<E> extends Filter<E> { 19 20 protected FilterReply onMatch = FilterReply.NEUTRAL; 21 protected FilterReply onMismatch = FilterReply.NEUTRAL; 22 23 final public void setOnMatch(FilterReply reply) { 24 this.onMatch = reply; 25 } 26 27 final public void setOnMismatch(FilterReply reply) { 28 this.onMismatch = reply; 29 } 30 31 final public FilterReply getOnMatch() { 32 return onMatch; 33 } 34 35 final public FilterReply getOnMismatch() { 36 return onMismatch; 37 } 38 } 1 /** 2 * Logback: the reliable, generic, fast and flexible logging framework. 3 * Copyright (C) 1999-2015, QOS.ch. All rights reserved. 4 * 5 * This program and the accompanying materials are dual-licensed under 6 * either the terms of the Eclipse Public License v1.0 as published by 7 * the Eclipse Foundation 8 * 9 * or (per the licensee's choosing) 10 * 11 * under the terms of the GNU Lesser General Public License version 2.1 12 * as published by the Free Software Foundation. 13 */ 14 package ch.qos.logback.core.spi; 15 16 /** 17 * 18 * This enum represents the possible replies that a filtering component 19 * in logback can return. It is used by implementations of both 20 * {@link ch.qos.logback.core.filter.Filter Filter} and 21 * ch.qos.logback.classic.turbo.TurboFilter abstract classes. 22 * 23 * Based on the order that the FilterReply values are declared, 24 * FilterReply.ACCEPT.compareTo(FilterReply.DENY) will return 25 * a positive value. 26 * 27 * @author Sébastien Pennec 28 */ 29 public enum FilterReply { 30 DENY, NEUTRAL, ACCEPT; 31 }簡單來講onMatch和onMismatch的取值都有三個分別是DENY(拒絕),NEUTRAL(進入下一個filter),ACCEPT(接受,跳過所有剩下的filter)。
(7)?rollingPolicy節點配置日志文件的存檔策略,本例后三個appender都是每分鐘(不超過10MB)存儲一個文件;
注意如果存檔日志文件數量超過maxHistory值,最老的日子文件會被刪除。
(8) 最后說一下<encoder>里面的<layout>,它是logback中的一個組件負責將日志事件轉成字符串,先看一下它的接口定義:
public interface Layout<E> extends ContextAware, LifeCycle {String doLayout(E event);String getFileHeader();String getPresentationHeader();String getFileFooter();String getPresentationFooter();String getContentType(); }繼承該接口你就可以自定義自己的layout:
package chapters.layouts;import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.LayoutBase; public class MySampleLayout extends LayoutBase<ILoggingEvent> {public String doLayout(ILoggingEvent event) {StringBuffer sbuf = new StringBuffer(128);sbuf.append(event.getTimeStamp() - event.getLoggingContextVO.getBirthTime());sbuf.append(" ");sbuf.append(event.getLevel());sbuf.append(" [");sbuf.append(event.getThreadName());sbuf.append("] ");sbuf.append(event.getLoggerName();sbuf.append(" - ");sbuf.append(event.getFormattedMessage());sbuf.append(CoreConstants.LINE_SEP);return sbuf.toString();} }然后使用你自定義的layout:
<configuration><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder"><layout class="chapters.layouts.MySampleLayout" /></encoder></appender><root level="DEBUG"><appender-ref ref="STDOUT" /></root> </configuration>本例使用了logback自帶的HTMLLayout。
5. logback不同環境不同配置
有兩種實現方式:
(1) 按環境將配置文件拆分為logback-production.xml和logback-dev.xml等,然后在application.properties里面配置:
logging.config: classpath:logback-dev.xml(2) 第二種是使用<springProfile>標簽,在logback-spring.xml中配置:
<!-- develop --> <springProfile name="dev"><root level="DEBUG"><appender-ref ref="CONSOLE" /></root> </springProfile><!-- production --> <springProfile name="prod"><root level="INFO"><appender-ref ref="STDOUT" /></root> </springProfile>同時也有兩種方式指定使用的環境:
a. 在application.properties里配置:
spring.profiles.active: dev spring.profiles.active: prodb.?啟動時指定:
java -jar xxx.jar --spring.profiles.active=dev6. 應用
import org.slf4j.Logger; import org.slf4j.LoggerFactory;public abstract class BaseController {protected static Logger logger = LoggerFactory.getLogger(BaseController.class); } import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;@RestController @RequestMapping("/log") public class LogController extends BaseController {@RequestMapping("/all")public String all(String message) {logger.trace(message);logger.debug(message);logger.info(message);logger.warn(message);logger.error(message);System.out.println(message);try {System.out.println(3 / 0);} catch (Exception e) {logger.error(null, e);}return message;} }轉載于:https://www.cnblogs.com/eagle6688/p/9635175.html
總結
以上是生活随笔為你收集整理的Spring Boot 应用系列 5 -- Spring Boot 2 整合logback的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 搭建好看的静态博客(使用Hexo进行搭建
- 下一篇: 即使会溢出,也能得到正确的结果