探索java世界中的日志奧秘

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? java日志簡單介紹

?

?

?

對于一個應用程序來說日志記錄是必不可少的一部分。線上問題追蹤,基于日志的業務邏輯統計分析等都離不日志。JAVA領域存在多種日志框架,目前常用的日志框架包括Log4jLog4j 2Commons LoggingSlf4jLogbackJul

?

?

一、java日志發展史

?

二、java?常用日志框架類別介紹

?

三、門面、實現、橋接

?

四、commons logging vs Slf4j

?

五、 log4j vs logback

六、 slf4j?源碼解讀

?

七、logback

?

八、MDC

?

?

?

?

?

?

?

?

?

?

?

?

?

一、java日志發展史

?

? 1996年早期,歐洲安全電子市場項目組決定編寫它自己的程序跟蹤API(Tracing API)。經過不斷的完善,這個API終于成為一個十分受歡迎的Java日志軟件包,即Log4j。后來Log4j成為Apache基金會項目中的一員。

?

? 期間Log4j近乎成了Java社區的日志標準。據說Apache基金會還曾經建議sun引入Log4jjava的標準庫中,但Sun拒絕了。

? 2002Java1.4發布,Sun推出了自己的日志庫JUL(Java Util Logging),其實現基本模仿了Log4j的實現。在JUL出來以前,log4j就已經成為一項成熟的技術,使得log4j在選擇上占據了一定的優勢。

? 接著,Apache推出了Jakarta Commons LoggingJCL只是定義了一套日志接口(其內部也提供一個Simple Log的簡單實現),支持運行時動態加載日志組件的實現,也就是說,在你應用代碼里,只需調用Commons Logging的接口,底層實現可以是log4j,也可以是Java Util Logging

? 后來(2006)Ceki Gülcü不適應Apache的工作方式,離開了Apache。然后先后創建了slf4j(日志門面接口,類似于Commons Logging)Logback(Slf4j的實現)兩個項目,并回瑞典創建了QOS公司,QOS官網上是這樣描述Logback的:The GenericReliable Fast&Flexible Logging Framework(一個通用,可靠,快速且靈活的日志框架)

? 現今,Java日志領域被劃分為兩大陣營:Commons Logging陣營和SLF4J陣營。
Commons LoggingApache大樹的籠罩下,有很大的用戶基數。但有證據表明,形式正在發生變化。2013年底有人分析了GitHub30000個項目,統計出了最流行的100Libraries,可以看出slf4j的發展趨勢更好:

?

?

? Apache眼看有被Logback反超的勢頭,于2012-07重寫了log4j 1.x,成立了新的項目Log4j 2Log4j 2具有logback的所有特性。

?

?

二、java常用日志框架類別介紹

?

? ? ? ? ?? Log4j?Apache Log4j是一個基于Java的日志記錄工具。現在則是Apache軟件基金會的一個項目。 Log4j是幾種Java日志框架之一。 Log4j應該說是Java領域資格最老,應用最廣的日志工具。從誕生之日到現在一直廣受業界歡迎。Log4j是高度可配置的,并可通過在運行時的外部文件配置。它根據記錄的優先級別,并提供機制,以指示記錄信息到許多的目的地,諸如:數據庫,文件,控制臺,UNIX系統日志等。

? Log4j 2?Apache Log4j 2apache開發的一款Log4j的升級產品。

?

? Logback?一套日志組件的實現(slf4j陣營)

? ? ? ?? Jul?(Java Util Logging),Java1.4以來的官方日志實現。JDK1.4開始,通過java.util.logging提供日志功能。它能滿足基本的日志需要,但是功能沒有Log4j強大,而且使用范圍也沒有Log4j廣泛。

?

? Commons Logging?Apache基金會所屬的項目,是一套Java日志接口,之前叫Jakarta Commons Logging,后更名為Commons Logging

? Slf4j?類似于Commons Logging,是一套簡易Java日志門面,本身并無日志的實現。(Simple Logging Facade for Java,縮寫Slf4j)。

?

? ? ? ? ? ? ? ? ? ?這個些所有的日志們都要歸功于一個人? ? ? ?Ceki Gülcü !!!

?

?

?

?

?

?

?

三、門面、實現、橋接

?

經歷了上述的發展,現在使用日志框架時往往會涉及三個層面的東西。?

? ? ? ? ? ? ? ??

?

· 門面

· Slf4j: The simple logging facade for java.

·? ? JCL: Jakarta Commons Logging.

· 實現類

· log4j-1.2

· log4j-2.x

· logback

· jul: java.util.logging

·

· 橋接包

· SLF4J LOG4J 12 Binding

· JUL To SLF4J Bridge

· JCL 1.1.1 Implemented Over SLF4J ??

· SLF4J JDK14 Binding

· Apache Log4j Commons Logging Bridge

·

?

門面主要只負責定義接口,實現類才負責具體的編碼工作。

?

為什么要定義門面呢? 依賴接口而不依賴實現

?

橋接包顧名思義就是橋接門面和實現類。比如SLF4J LOG4J 12 Binding這個橋接包可以使Slf4j和log4j1.2結合起來正常工作。一個已經成型的系統如果使用了這個模式,底層又想將log4j1.2換成log4j2.0實現,則只需要替換實現包為log4j2.x以及橋接包為 Log4j 2 SLF4J Binding。

?

?

? ? ? ? ? ? ? ? ? ??

?

?

?

?

?

?

?

?

?

?

?

四、commons logging vs Slf4j

?

我們先看一下java日志框架之間的關系

?

? Commons LoggingSlf4j是日志門面(門面模式是軟件工程中常用的一種軟件設計模式,也被稱為正面模式、外觀模式。它為子系統中的一組接口提供一個統一的高層接口,使得子系統更容易使用)log4jLogback則是具體的日志實現方案。可以簡單的理解為接口與接口的實現,調用這只需要關注接口而無需關注具體的實現,做到解耦。

? 比較常用的組合使用方式是Slf4jLogback組合使用,Commons LoggingLog4j組合使用。

? Logback必須配合Slf4j使用。由于LogbackSlf4j是同一個作者,其兼容性不言而喻。(https://stackoverflow.com/questions/10117788/how-to-setup-commons-logging-to-use-logback)

?

Commons logging實現機制

Commons logging是通過動態查找機制,在程序運行時,使用自己的ClassLoader尋找和載入本地具體的實現。詳細策略可以查看commons-logging-*.jar包中的org.apache.commons.logging.impl.LogFactoryImpl.java文件。

?

Slf4j實現機制

Slf4j在編譯期間,靜態綁定本地的LOG庫。它是通過查找類路徑下org.slf4j.impl.StaticLoggerBinder,然后綁定工作都在這類里面進行。

?

?

靜態綁定 & 動態綁定

靜態綁定又稱編譯時綁定,動態綁定又稱運行時綁定。

JCL作為第一個log接口框架,使用了基于反射的動態綁定的方法,原理很簡單,預先定義好支持的log實現的工廠類的全路徑到一個數組中,遍歷這個數組,調用Class.forName依次嘗試尋找各個log實現,如果當前class loader沒找到,就去父class loader去找,直到找到任意一個實現為止。

這種方法有致命的缺陷,這也正是SLF4J誕生的原因。Java EE的web容器,為了實現servlet規范中同一個容器中不同web app之間、web app和web容器之間的隔離,都使用的自己實現的class loader,邏輯和標準的class loader不同,導致一系列的無法正常發現log實現庫的問題。

Taxonomy of class loader problems encountered when using Jakarta Commons Logging

這篇文章做了非常詳盡的分析解釋,文章的作者正是log4j和SLF4J的作者Ceki Gülcü,有興趣的同學可以閱讀。

?

另外一個小改進:

JCL 輸出一個 debug 級別的 log:

logger.debug("start process request, url:" + url);

這個有什么問題呢?一般生產環境 log 級別都會設到 info 或者以上,那這條 log 是不會被輸出的。然而不管會不會輸出,這其中都會做一個字符串連接操作,然后生產一個新的字符串。如果這條語句在循環或者被調用很多次的函數中,就會多做很多無用的字符串連接,影響性能。

所以 JCL 的最佳實踐推薦這么寫:

if (logger.isDebugEnabled()) {

? ? logger.debug("start process request, url:" + url);

}

然而開發者常常忽略這個問題或是覺得麻煩而不愿意這么寫。

?

?

所以SLF4J提供了新的API,方便開發者使用:

logger.debug("start process request, url:{}", url);

這樣的話,在不輸出 log 的時候避免了字符串拼接的開銷;在輸出的時候需要做一個字符串format,代價比手工拼接字符串大一些,但是可以接受。

?

?

五、 log4j vs logback

logback算是log4j的升級版本 ,基本實現了所有log4j的功能。

logback比log4j有更多的優點

更快的實現?

Logback的內核重寫了,在一些關鍵執行路徑上性能提升10倍以上。而且logback不僅性能提升了,初始化內存加載也更小了。?

?

非常充分的測試?

Logback經過了幾年,數不清小時的測試。Logback的測試完全不同級別的。在作者的觀點,這是簡單重要的原因選擇logback而不是log4j。?

?

Logback-classic非常自然實現了SLF4j?

Logback-classic實現了SLF4j。在使用SLF4j中,你都感覺不到logback-classic。而且因為logback-classic非常自然地實現了SLF4J,所以切換到log4j或者其他,非常容易,只需要提供成另一個jar包就OK,根本不需要去動那些通過SLF4JAPI實現的代碼。?

?

非常充分的文檔?

Logback文檔免費。Logback的所有文檔是全面免費提供的,不象Log4J那樣只提供部分免費文檔而需要用戶去購買付費文檔?

?

?

?

Filters(過濾器)?

有些時候,需要診斷一個問題,需要打出日志。在log4j,只有降低日志級別,不過這樣會打出大量的日志,會影響應用性能。在Logback,你可以繼續保持那個日志級別而除掉某種特殊情況,如alice這個用戶登錄,她的日志將打在DEBUG級別而其他用戶可以繼續打在WARN級別。要實現這個功能只需加4行XML配置。

?

SiftingAppender(一個非常多功能的Appender)?

它可以用來分割日志文件根據任何一個給定的運行參數。如,SiftingAppender能夠區別日志事件跟進用戶的Session,然后每個用戶會有一個日志文件。?

?

自動壓縮已經打出來的log?

RollingFileAppender在產生新文件的時候,會自動壓縮已經打出來的日志文件。壓縮是個異步過程,所以甚至對于大的日志文件,在壓縮過程中應用不會受任何影響。?

?

堆棧樹帶有包版本?

Logback在打出堆棧樹日志時,會帶上包的數據。?

?

自動去除舊的日志文件?

通過設置TimeBasedRollingPolicy或者SizeAndTimeBasedFNATP的maxHistory屬性,你可以控制已經產生日志文件的最大數量。如果設置maxHistory為12,那那些log文件超過12個月的都會被自動移除。?

?

?

六、 slf4j源碼解讀

?

我們寫代碼的時候是怎么打日志的呢?

?

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

?

LoggerFactory.getLogger(getClass());

?

這里看不到任何跟實現類有關聯的代碼,然而我們已經可以使用get到的logger打日志了。那么slf4j到底是怎么找到實現類的了?

?

根據Path = “org/slf4j/impl/StaticLoggerBinder.class”去加載相應的實現類

?

?

為什么要獲取類的名字,而根據名字來獲取對象呢?

因為每個類使用的日志處理實現可能不同,iLoggerFactory中也是根據名字來判斷一個類的實現方式的。

?

?

?

?

?

?

那么這里會有一個問題,如果找到多個實現類,最終會綁定哪一個呢?

?

The warning emitted by SLF4J is just that, a warning. Even when multiple bindings are present, SLF4J will pick one logging framework/implementation and bind with it. The way SLF4J picks a binding is determined by the JVM and for all practical purposes should be considered random. As of version 1.6.6, SLF4J will name the framework/implementation class it is actually bound to.

Embedded components such as libraries or frameworks should not declare a dependency on any SLF4J binding but only depend on slf4j-api. When a library declares a compile-time dependency on a SLF4J binding, it imposes that binding on the end-user, thus negating SLF4J’s purpose. When you come across an embedded component declaring a compile-time dependency on any SLF4J binding, please take the time to contact the authors of said component/library and kindly ask them to mend their ways.

如果發現有多個實現類,那么slf4j會打印出warning信息。但是僅僅是warning而已。即使有多個實現類,slf4j也只會挑選其中一個,這個選擇取決于JVM和所有其他實際因素,基本算是隨機性的。同時,slf4j建議刪除多余的實現類,僅僅保留一個。

?

?

?

?

?

七、logback

?

?

1StaticLoggerBinder 初始化并創建logFactory ()

?

?

?

StaticLoggerBinder.init();

?

初始化 new ContextInitializer(defaultLoggerContext).autoConfig();

?

getLoggerFactory()

?

?

總結一下這個過程:?

1StaticLoggerBinder在加載的時候,會去讀取配置文件,并根據配置文件對LoggerContext進行初始化?

2、然后初始化ContextSelectorStaticBinder,在這個類內部new一個DefaultContextSelector,并把第一步中配置完畢的LoggerContext傳給DefaultContextSelector?

3、調用getLoggerFactory()方法,直接返回第一步中配置的LoggerContext,或者委托DefaultContextSelector類返回LoggerContext

?

?

2loggerContext工廠類產出logger對象?

?

?

?

Logger getLogger(final String name);

?

com.darcytech.controller.LoginController

?

Logger[com]、Logger[com.darcytec]、Logger[com.darcytech.controller]、Logger[com.darcytech.controller.LoginController]?

?

?

總結一下創建Logger的完整流程:?

1、如果請求ROOT logger,則直接返回root?

2、如果請求的Logger已經存在,則直接返回?

3、如果請求的Logger尚未創建,則從ROOT開始,級聯創建所有Logger?

4、每創建一個Logger,都要設置父子關系,繼承生效級別?

5、每創建一個Logger,都將其放入loggerCache,并將size++?

?

?

3、Logger

?

transient private AppenderAttachableImpl<ILoggingEvent> aai;

Logger是委托這個類實現AppenderAttachable接口,也是委托這個類來調用Appender組件來實際記錄日志,所以這個字段是最關鍵的。

?

主要方法

getChildByName

setLevel

createChildByName每創建一個Logger,都要設置父子關系,繼承生效級別

info

?

?

?

?

callAppenders

如果子Logger和父Logger都關聯了同樣的Appender,則日志信息會重復記錄

?

?

?

總結一下Logger類中定義的字段和方法,是出于以下目的:?

?

1、定義parentchildList,用于實現父子Logger的樹形結構?

2、定義createChildByName()getChildByName()方法,是供LoggerContext創建Logger?

3、定義leveleffectiveLevelInt,是為了判定日志級別是否足夠?

4、最后,filterAndLog()buildLoggingEventAndAppend()callAppenders()appendLoopOnAppenders()方法,是Logger類的核心方法,一步步地委托AppenderAttachableImpl類來實際記錄日志?

?

?

?

4Appender

?

?

實現類就是最常見的ConsoleAppender和FileAppender

?

doAppend()

?

最終writeOut()方法委托配置給它的Encoder組件來記錄

?

?

?

5、簡單了解一下RollingFileAppender,rollingPolicy

常用的RollingFileAppender, TimeBasedRollingPolicy

?

?

?

?

?

?

?

?

八、什么是MDC

?

?

?

MDC(Mapped Diagnostic Context,映射調試上下文)是 log4j 和 logback 提供的一種方便在多線程條件下記錄日志的功能。MDC 可以看成是一個與當前線程綁定的哈希表,可以往其中添加鍵值對,當需要記錄日志時,只需要從 MDC 中獲取所需的信息即可。

?

?

?

此外,對于一些線程池使用的應用場景,可能我們在最后使用結束時,需要調用clear方法來清洗將要丟棄的數據。

?

LogbackMDCAdapter

?

?

?

?

?

?

?

?

?

轉載于:https://www.cnblogs.com/wazqy/p/8315757.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/284421.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/284421.shtml
英文地址,請注明出處:http://en.pswp.cn/news/284421.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

nginx的負載均衡集群

針對域名:vim /usr/local/nginx/conf/vhosts/lb.conf //自定義名稱upstream xrc { //別名server 192.168.0.1:80 weight2; //包含的主機server,負載均衡里面的機器server 192.168.0.2:80 weight1; //權重weight}server {li…

英語名言警句100句

1、寧為百夫長&#xff0c;勝作一書生。——楊炯 Better be a centurion than a scholar. 2、我是閑暇為所有中最的。——蘇格拉底 I am the most leisure of all. 3、立志不堅&#xff0c;終不濟事。——朱熹 If you are not determined, you will not help. 4、人學始知道&am…

RabbitMQ細說之開篇

前言關于消息中間件的應用場景&#xff0c;小伙伴們應該都耳熟能詳了吧&#xff0c;比如經常提到的削峰填谷、分布式事務、異步業務處理、大數據分析等等&#xff0c;分布式消息隊列成為其中比較關鍵的橋梁&#xff0c;也就意味著小伙伴們得掌握相關技能&#xff1b;當下相對比…

【Java】五種常見排序之-----------冒泡排序

冒泡排序&#xff1a; 原理: 將關鍵字較小的值不斷地上浮&#xff0c;將關鍵字值較大的不斷下沉&#xff1b;時間復雜度&#xff1a;O(n^2)空間復雜度&#xff1a;最優&#xff08;即已經排好序&#xff09;為0&#xff0c;平均空間復雜度為O(1);核心代碼&#xff1a;for(int i…

混戰的低代碼江湖,如何區分「李逵」和「李鬼」?

作者&#xff1a;APICloud 創始人劉鑫 這兩年&#xff0c;無論是資本層面&#xff0c;還是企業IT部門的關注&#xff0c;“低代碼”都是絕對的熱點。互聯網圈也似在一夜之間冒出了各種各樣的低代碼公司。 到底什么是低代碼&#xff1f;低代碼是新技術么&#xff1f;低代碼開發能…

關于捕獲鍵盤信息的processDialogkey方法2--具體應用

自定義控件里的keydown方法無法捕獲所有的按鍵消息的處理方法1&#xff08;自定義控件里的keydown方法無法獲取的鍵值如上下左右鍵等&#xff09; 處理辦法具體如下&#xff1a; 1、首先在自定義控件UserControl1中重寫ProcessDialogKey方法 自定義控件UserControl1中重寫Proce…

指針

指針 題目一&#xff1a; 計算兩數的和與差 本題要求實現一個計算輸入的兩數的和與差的簡單函數。 函數接口定義&#xff1a; void sum_diff( float op1, float op2, float psum, float pdiff ); 其中op1和op2是輸入的兩個實數&#xff0c;psum和pdiff是計算得出的和與差。 裁判…

【MapGIS精品教程】006:MapGIS根據經緯度計算各比例尺圖幅編號

己知某點的經緯度或圖幅西南圖廓點的經緯度,計算該點所在圖幅號。 例題一:某點的經度為11433′45″,緯度為3922′30″,計算所在1:250000圖幅的編號。 文章目錄 1. 公式計算編號的方法2. 軟件計算編號的方法1. 公式計算編號的方法 求解過程: 第一步,利用下列公式計算其所…

寫出一個緩存系統的偽代碼001

/*** 寫出一個緩存系統的偽代碼*/ public class CacheDemo {private Map<String, Object> map new HashMap<String, Object>();public static void main(String[] args) {// TODO Auto-generated method stub} public synchronized Object getData(String key)…

分析完百年飛機空難數據,我發現了這幾條“保命”小秘訣

來 源&#xff5c;Giao數據 數 據 | YaJie 文 章 | 張子豪,YaJie 本文爬取了飛機失事網1908-2020年空難相關數據&#xff0c;包括空難發生次數、機組和乘客的死亡人數與死亡率、不同季節的空難發生次數、空難相關文本的關鍵詞、空難高發地、空難高發航空公司、空難高發機型以…

用 QuestPDF操作生成PDF更快更高效!

QuestPDFQuestPDF是一個開源的工具庫&#xff0c;可以在.NET或者.Net Core中生成pdf文檔它提供了一個布局引擎&#xff0c;設計時考慮到了完整的分頁支持以及靈活性要求&#xff01;比市面上常見的Aspose和iTextSharp好用太多了&#xff01;GitHub地址安裝Install-Package Ques…

ASP.NET vs MVC vs WebForms

許多ASP.NET開發人員開始接觸MVC認為MVC與ASP.NET完全沒有關系&#xff0c;是一個全新的Web開發&#xff0c;事實上ASP.NET是創建WEB應用的框架而MVC是能夠用更好的方法來組織并管理代碼的一種更高級架構體系&#xff0c;所以可以稱之為ASP.NET MVC。 我們可將原來的ASP.NET稱為…

產品經理有哪些類型?

不知道大家是如何給產品經理這個職業進行分類&#xff0c; 按負責的產品&#xff1f;按等級&#xff1f;按工作年限&#xff1f;按工作方向等&#xff1f; 一、按工作內容分 1. 功能設計產品經理 最常見的了&#xff0c;負責的工作就是設計出功能來。從 APP 的界面&#xff0…

在Blazor 中自定義權限驗證

Blazor是什么Blazor 是微軟在 .NET 里推出的一個 WEB 客戶端 UI 交互的框架&#xff0c;使用 Blazor 你可以代替 JavaScript 來實現自己的頁面交互邏輯&#xff0c;可以很大程度上進行 C# 代碼的復用&#xff0c;Blazor 對于 .NET 開發人員來說是一個不錯的選擇。需求背景其實我…

看出每個應用程序最高可用內存是多少

int maxMemory (int) (Runtime.getRuntime().maxMemory() / 1024); Log.d("TAG", "Max memory is " maxMemory "KB"); 轉載于:https://www.cnblogs.com/coderwjq/p/6501639.html

中文分詞之HMM模型詳解

文章轉載自: http://yanyiwu.com/work/2014/04/07/hmm-segment-xiangjie.html HMM(Hidden Markov Model): 隱式馬爾科夫模型。 HMM模型可以應用在很多領域&#xff0c;所以它的模型參數描述一般都比較抽象&#xff0c;以下篇幅針對HMM的模型參數介紹直接使用它在中文分詞中的實…

【ArcGIS微課1000例】0035:地圖面狀符號設計教程

地圖符號是表示地圖內容的基本手段,它由形狀不同、大小不一、色彩有別的圖形和文字組成。 地圖符號是地圖的語言,是一種圖形語言。它與文字語言相比較,最大的特點是形象直觀,一目了然。 本文講解ArcGIS中面狀符號設計方法。 文章目錄 一、新建符號樣式二、面狀符號設計1. 斜…

MySQL奪命15問,你能堅持到第幾問?

前言 MySQL在面試中經常被問到&#xff0c;本文總結了面試中的經典問題。 1. 數據庫三大范式是什么&#xff1f; 第一范式&#xff1a;每個列都不可以再拆分。 第二范式&#xff1a;在第一范式的基礎上&#xff0c;非主鍵列完全依賴于主鍵&#xff0c;而不能是依賴于主鍵的一部…

ios元素定位

原文地址http://www.cnblogs.com/meitian/p/7373460.html 第一種&#xff1a;通過Appium1.6的Inspector來查看 具體安裝方式前面的隨筆已經介紹了&#xff1a;http://www.cnblogs.com/meitian/p/7360017.html可以通過定位找到元素xpath或name個人不推薦用這個方法&#xff0c;實…

分治法——循環賽日程表

1、問題描述&#xff1a;有n2^k個遠動員選手&#xff0c;設計比賽日程表實現&#xff1a;&#xff08;1&#xff09;每個選手必須與n-1個選手比賽&#xff08;2&#xff09;每個選手一天只比賽一場&#xff08;3&#xff09;比賽共進行n-1天輸入&#xff1a;n人輸出&#xff1a…