一.日志系統介紹
slf4j,即簡單日志門面(Simple Logging Facade for Java),不是具體的日志解決方案,它只服務於各種各樣的日志系統。簡答的講就是slf4j是一系列的日志接口,而log4j是具體實現了的日志框架。
slf4j與常用日志框架綁定關系

二.導入jar包
Maven導入slf4j和log4j,編輯pom.xml
<!-- 導入slf4j-log4j12,依賴slf4j-api和log4j,自動導入 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.25</version> </dependency>
三.配置log4j
log4j日志框架配置,編輯resources/log4j.xml
log4j的xml配置方式基本步驟有3個,第一步:配置appender;第二步:配置logger;第三步:配置root。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <!-- 輸出信息到控制台,用於開發調試 --> <appender name="myConsole" class="org.apache.log4j.ConsoleAppender"> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="[%d{dd HH:mm:ss,SSS\} %-5p] [%t] (%F:%L) - %m%n"/> </layout> <!-- 日志過濾條件,輸出哪些日志 --> <filter class="org.apache.log4j.varia.LevelRangeFilter"> <!-- OFF FATAL ERROR WARN INFO DEBUG TRACE ALL --> <param name="levelMin" value="debug"/> <param name="levelMax" value="error"/> <param name="AcceptOnMatch" value="true"/> </filter> </appender> <!-- 輸出信息到文件,每天產生一個日志文件 --> <appender name="myFile" class="org.apache.log4j.DailyRollingFileAppender"> <param name="File" value="${catalina.base}/logs/log4j.log"/> <param name="Append" value="true"/> <!-- 日志輸出的最低等級 --> <param name="Threshold" value="info"/> <param name="DatePattern" value="'.'yyyy-MM-dd"/> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="[%d{dd HH:mm:ss,SSS\} %-5p] [%t] (%F:%L) - %m%n"/> </layout> </appender> <!-- 日志記錄器,子logger會默認繼承父logger的appender;子logger只在自己未定義輸出級別的情況下,才會繼承父logger的輸出級別 --> <logger name="com.learn.spring.server" additivity="false"> <!-- Logger中定義的level和appender中的filter定義的level的區間取交集 --> <level value="debug"/> <!-- 默認作用於所有的appender --> <appender-ref ref="myConsole"/> <appender-ref ref="myFile"/> </logger> <root> <level value="ALL"/> <appender-ref ref="myConsole"/> </root> </log4j:configuration>
四.日志調用示例
Slf4j初始化時自動查找CLASSPATH路徑下的log4j.xml配置文件
@Controller
@RequestMapping("/server")
public class IndexController {
private static final Logger LOGGER = LoggerFactory.getLogger(IndexController.class);
@ResponseBody
@RequestMapping("/hello")
public Object hello(String username) {
LOGGER.debug("Debug level log: username = " + username);
LOGGER.info("Info level log: username = " + username);
try {
throw new Exception("Error level log");
} catch (Exception e) {
LOGGER.error("Error level log: username = " + username, e);
}
return "hello " + username;
}
}
控制台日志,輸出debug、info、error級別日志

日志文件log4j.log,輸出info和error級別日志,未輸出debug級別日志

五.日志輸出格式符號含義
%p:輸出日志信息優先級,即TRACE,DEBUG,INFO,WARN,ERROR,FATAL
%d:輸出日志時間點的日期或時間,默認格式為ISO8601,也可以在其后指定格式
%r:輸出自應用啟動到輸出該log信息耗費的毫秒數
%c:輸出日志信息所屬的類目,通常就是所在類的全名
%t:輸出產生該日志事件的線程名
%l:輸出日志事件的發生位置,相當於%C.%M(%F:%L)的組合,包括類目名、發生的線程,以及在代碼中的行數
%x:輸出和當前線程相關聯的NDC(嵌套診斷環境),尤其用到像java servlets這樣的多客戶多線程的應用中
%%:輸出一個"%"字符
%F:輸出日志消息產生時所在的文件名稱
%L:輸出代碼中的行號
%m:輸出代碼中指定的消息,產生的日志具體信息
%n:輸出一個回車換行符,Windows平台為"/r/n",Unix平台為"/n"輸出日志信息換行
六.阿里巴巴日志規約
1.【強制】應用中不可直接使用日志系統 (Log 4 j 、Logback) 中的 API ,而應依賴使用日志框架SLF4J中的 API ,使用門面模式的日志框架,有利於維護和各個類的日志處理方式統一。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(Abc.class);
2.【強制】日志文件推薦至少保存 15 天,因為有些異常具備以“周”為頻次發生的特點。
3.【強制】應用中的擴展日志 ( 如打點、臨時監控、訪問日志等 ) 命名方式:appName _ logType _ logName . log 。 logType :日志類型,推薦分類有stats / desc / monitor / visit 等 ;logName :日志描述。這種命名的好處:通過文件名就可知道日志文件屬於什么應用,什么類型,什么目的,也有利於歸類查找。
正例: mppserver 應用中單獨監控時區轉換異常,如:
mppserver _ monitor _ timeZoneConvert . log
說明:推薦對日志進行分類,如將錯誤日志和業務日志分開存放,便於開發人員查看,也便於通過日志對系統進行及時監控。
4.【強制】對 trace / debug / info 級別的日志輸出,必須使用條件輸出形式或者使用占位符的方式。
說明: logger . debug( " Processing trade with id : " + id + " and symbol : " + symbol);如果日志級別是 warn ,上述日志不會打印,但是會執行字符串拼接操作,如果 symbol 是對象,會執行 toString() 方法,浪費了系統資源,執行了上述操作,最終日志卻沒有打印。
正例: ( 條件 )
if (logger.isDebugEnabled()) {
logger.debug("Processing trade with id: " + id + " and symbol: " + symbol);
}
正例: ( 占位符 )
logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol);
5.【強制】避免重復打印日志,浪費磁盤空間,務必在 log 4 j . xml 中設置 additivity = false 。
正例: <logger name="com.taobao.dubbo.config" additivity="false">
6.【強制】異常信息應該包括兩類信息:案發現場信息和異常堆棧信息。如果不處理,那么通過關鍵字 throws 往上拋出。
正例: logger.error(各類參數或者對象 toString+ "_" + e.getMessage(), e);
7.【推薦】謹慎地記錄日志。生產環境禁止輸出 debug 日志 ; 有選擇地輸出 info 日志 ; 如果使用 warn 來記錄剛上線時的業務行為信息,一定要注意日志輸出量的問題,避免把服務器磁盤撐爆,並記得及時刪除這些觀察日志。
說明:大量地輸出無效日志,不利於系統性能提升,也不利於快速定位錯誤點。記錄日志時請思考:這些日志真的有人看嗎?看到這條日志你能做什么?能不能給問題排查帶來好處?
8.【參考】可以使用 warn 日志級別來記錄用戶輸入參數錯誤的情況,避免用戶投訴時,無所適從。注意日志輸出的級別, error 級別只記錄系統邏輯出錯、異常等重要的錯誤信息。如非必要,請不要在此場景打出 error 級別。
