1. 市面是最通用的是 log4j2+slf4j。理由是用slf4j實現藉口便於往後可能的日誌框架遷移,用log4j2實現日誌核型。畢竟是2.0版本,取長補短過。須要注意的是, log4j2 和 log4j的版本groupId、artifactId都是同樣的,區別是version不同-- 1.X / 2.X。讓我疑惑了好久。官網也找不到1.X的介紹了,看來是再也不維護了。spring
用log4j2+slf4j配置的寫法是 sql
import org.slf4j.Logger; import org.slf4j.LoggerFactory;
private Logger logger = LoggerFactory.getLogger(getClass());
若是隻用log4j2,不用slf4j,寫法是apache
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager;
private static Logger logger = LogManager.getLogger(getClass());
2.須要用到的最低配置jar包下。 須要注意的事,大機率會出現jar包衝突,如slf4j-simple、slf4j-log4j-imp等,會顯示Class path contains multiple SLF4J bindings。找到衝突的jar包排除便可。設計模式
<!--日誌 slf4j 核心包 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.12</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>1.7.1</version> </dependency> <!--日誌 log4j2 核心包 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.5</version> </dependency> <!--日誌 log4j-slf4j 集合包 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>2.5</version> </dependency>
若是想用異步記錄日誌,還須要api
<dependency> <groupId>com.lmax</groupId> <artifactId>disruptor</artifactId> <version>3.3.2</version> </dependency>
3. 官網的文檔很坑,找了半天沒有找到log4j2.xml的默認路徑。對於maven、gradle項目,百度找到了默認路徑是src-main-resources下。服務器
4. log4j2配置項的意義中 <Appenders> <Loggers>mybatis
Appenders是定義一個日誌輸出格式,須要在loggers裏使用ref進行引號纔是一個日誌系統的完整閉環。這麼作的好處是appender能夠重複使用了,能夠應付複雜的日誌配置。app
Loggers裏面有個頗有用的配置項Logger,能夠對不一樣包路徑的下的logger差別化配置。好比我引用了spring的包,只想看到spring的info級別的,就用下面這樣配置。框架
<Loggers> <Logger name="org.springframework" level="info"> <AppenderRef ref="Console"/> </Logger> <Root level="debug"> <AppenderRef ref="console"/> <AppenderRef ref="log"/> </Root> </Loggers>
5. 異步配置dom
使用異步配置代替同步,提升服務器性能
用<asyncRoot>代替<Root> ,用<asyncLogger>代替<Logger>
6. slf4j的設計模式--門面模式
private static String STATIC_LOGGER_BINDER_PATH = "org/slf4j/impl/StaticLoggerBinder.class"; static Set<URL> findPossibleStaticLoggerBinderPathSet() { // use Set instead of list in order to deal with bug #138 // LinkedHashSet appropriate here because it preserves insertion order // during iteration Set<URL> staticLoggerBinderPathSet = new LinkedHashSet<URL>(); try { ClassLoader loggerFactoryClassLoader = LoggerFactory.class.getClassLoader(); Enumeration<URL> paths; if (loggerFactoryClassLoader == null) { paths = ClassLoader.getSystemResources(STATIC_LOGGER_BINDER_PATH); } else { paths = loggerFactoryClassLoader.getResources(STATIC_LOGGER_BINDER_PATH); } while (paths.hasMoreElements()) { URL path = paths.nextElement(); staticLoggerBinderPathSet.add(path); } } catch (IOException ioe) { Util.report("Error getting resources from path", ioe); } return staticLoggerBinderPathSet; }
約定各個日誌系統的開發者須要實現org/slf4j/impl/StaticLoggerBinder.class,即在各自的jar包實現這個類,對LoggerFactory類進行綁定。
約定各個日誌系統的使用者只使用LoggerFactory。門面模式帶來的好處就是對使用者來講,系統至關簡單,容易上手。
7.最後,附上2個log4j.xml的配置文件,最簡單的和項目實用的。
最簡單的
<?xml version="1.0" encoding="UTF-8"?> <!-- 日誌級別 OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL --> <!-- status屬性配置log4j2自身的日誌信息打印級別 --> <!-- packages插件類搜索目錄 --> <!-- monitorInterval配置文件從新加載間隔,單位爲秒,最小間隔5秒 --> <Configuration status="warn"> <Appenders> <!-- 輸出到控制檯 --> <Console name="console" target="SYSTEM_OUT"> <PatternLayout pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n"/> </Console> </Appenders> <Loggers> <Root level="debug"> <AppenderRef ref="console"/> </Root> </Loggers> </Configuration>
項目實用的:
<?xml version="1.0" encoding="UTF-8"?> <!-- 日誌級別 OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL --> <!-- status屬性配置log4j2自身的日誌信息打印級別 --> <!-- monitorInterval配置文件從新加載間隔,單位爲秒,最小間隔5秒 --> <Configuration status="info" packages="utry.core.log.appender" monitorInterval="5"> <!-- 自定義屬性 --> <Properties> <!-- 日誌文件統一存放路徑 --> <Property name="LOG_HOME">D://</Property> <!-- 模塊名,使用子站名稱 --> <Property name="SERVER_NAME">moduleName</Property> </Properties> <Appenders> <!-- 輸出到控制檯 --> <Console name="console" target="SYSTEM_OUT"> <PatternLayout pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n"/> </Console> <!-- 錯誤日誌,輸出到滾動保存的文件,按天切分 --> <RollingRandomAccessFile name="errorLog" immediateFlush="true" fileName="${LOG_HOME}/${SERVER_NAME}.log" filePattern="${LOG_HOME}/${SERVER_NAME}.%d{yyyy-MM-dd}.log.gz"> <PatternLayout pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n" /> <Policies> <TimeBasedTriggeringPolicy interval="1" modulate="true" /> </Policies> </RollingRandomAccessFile> <!-- 調試日誌,輸出到滾動保存的文件,按大小切分 --> <RollingRandomAccessFile name="debugLog" immediateFlush="true" fileName="${LOG_HOME}/${SERVER_NAME}-debug.log" filePattern="${LOG_HOME}/${SERVER_NAME}-debug.%i.log.gz"> <PatternLayout pattern="[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n" /> <Policies> <SizeBasedTriggeringPolicy size="50 MB"/> </Policies> <DefaultRolloverStrategy max="10"/> </RollingRandomAccessFile> </Appenders> <Loggers> <!-- spring日誌 --> <AsyncLogger name="org.springframework" level="info"></AsyncLogger> <!-- mybaits日誌,debug級別能夠看到執行的sql及參數 --> <AsyncLogger name="org.mybatis" level="error"></AsyncLogger> <AsyncRoot level="all"> <!-- 控制檯 --> <AppenderRef ref="console" level="off"/> <!-- 錯誤日誌 --> <AppenderRef ref="errorLog" level="info"/> <!-- 調試日誌,生產環境請註釋 --> <!--<AppenderRef ref="debugLog" level="debug"/>--> </AsyncRoot> </Loggers> </Configuration>