JavaRush /Java Blog /Random-TW /Java 日誌記錄:什麼、如何、在哪裡、使用什麼?
Roman Beekeeper
等級 35

Java 日誌記錄:什麼、如何、在哪裡、使用什麼?

在 Random-TW 群組發布
大家好,JavaRush 社群!今天我們來談談Java日誌記錄:
  1. 這是什麼,這是為什麼。什麼情況下最好用,什麼情況下不宜用?
  2. Java 中的日誌記錄有哪些不同的實作?我們該如何利用這種多樣性?
  3. 記錄級別。讓我們討論一下什麼是appender以及如何正確配置它。
  4. 記錄節點以及如何正確配置它們,以便一切都按照我們想要的方式運作。
本資料面向廣大受眾。對於那些剛剛熟悉 Java 的人以及那些已經在工作但只是透過logger.info(“log something”); Let's Go!才弄清楚的人來說,這一點都會很清楚。

為什麼需要日誌記錄?

讓我們來看看日誌記錄可以解決問題的真實案例。這是我工作中的一個例子。有一些與其他服務整合的應用程式點。我使用記錄這些點作為「不在場證據」:如果整合不起作用,很容易找出問題源自哪一方。也建議記錄保存到資料庫的重要資訊。例如,建立管理員使用者。這正是記錄的好地方。

Java 日誌工具

日誌記錄:什麼、如何、在哪裡、用什麼? - 2眾所周知的 Java 日誌記錄解決方案包括:
  • 日誌4j
  • 七月 - java.util.logging
  • JCL - 雅加達公共日誌記錄
  • 回溯
  • SLF4J - java 的簡單日誌記錄門面
讓我們快速瀏覽一下它們中的每一個,在材料的實際部分中,我們將以Slf4j - log4j 的連接作為基礎。現在這可能看起來很奇怪,但別擔心:在文章結​​束時一切都會清楚。

系統錯誤.println

當然,最初有System.err.println(將輸出記錄到控制台)。仍然是在調試時用來快速取得日誌。當然,這裡不需要談論任何設置,所以我們記住它並繼續。

Log4j

這已經是一個成熟的解決方案,是根據開發人員的需求創建的。事實證明這是一個非常有趣的工具。由於各種情況,這個解決方案從未進入 JDK,這讓整個社區感到非常沮喪。log4j 具有配置選項,以便可以在套件中開啟日誌記錄com.example.type並在子包中關閉日誌記錄com.example.type.generic。這使得快速區分需要記錄的內容和不需要的內容成為可能。這裡要注意的是,log4j有兩個版本:1.2.x和2.x.x,它們彼此不相容log4j增加了appender這樣一個概念,即記錄日誌和佈局日誌格式化的工具。這使您可以僅記錄您需要的內容以及您需要的方式。稍後我們將詳細討論appender。

七月 - java.util.logging

主要優點之一是解決方案 - JUL 包含在 JDK(Java 開發工具包)中。不幸的是,在它的開發過程中,並不是以流行的log4j為基礎,而是IBM的解決方案,影響了它的發展。事實上,目前有JUL,但沒有人使用它。從「馬馬虎虎」來看:JUL 中的日誌記錄等級與 Logback、Log4j、Slf4j 中的日誌等級不同,這使得它們之間的理解變得更加糟糕。創建記錄器或多或少相似。為此,您需要導入:
java.util.logging.Logger log = java.util.logging.Logger.getLogger(LoggingJul.class.getName());
專門傳遞類別名稱是為了了解日誌記錄來自哪裡。從 Java 8 開始,可以透過Supplier<String>. 這有助於僅在真正需要時才計算和創建字串,而不是像以前那樣每次都進行計數和創建。直到Java 8的發布,開發人員才解決了重要問題,JUL才真正可用。即帶有參數的方法Supplier<String> msgSupplier如下所示:
public void info(Supplier<String> msgSupplier) {
   log(Level.INFO, msgSupplier);
}

JCL - 雅加達公共日誌記錄

由於很長一段時間以來日誌記錄都沒有行業標準,並且有一段時間許多人創建了自己的自訂記錄器,因此他們決定發布 JCL - 一種可以在其他日誌記錄器上使用的通用包裝器。為什麼?當某些依賴項新增至專案時,它們可以使用與專案上的記錄器不同的記錄器。因此,它們被傳遞到專案中,這在嘗試將它們放在一起時產生了真正的問題。不幸的是,該包裝器的功能非常差,並且沒有引入任何附加功能。如果每個人都使用 JCL 來完成他們的工作,那可能會很方便。但實際上情況並非如此,因此目前使用 JCL 並不是一個好主意。

回溯

開源之路是多麼的荊棘啊……Logback 是由與 log4j 相同的開發者編寫的,旨在創建它的後繼者。這個想法與 log4j 相同。差異在於 logback:
  • 提高性能;
  • 新增了對 slf4j 的原生支援;
  • 過濾選項已擴展。
預設情況下,logback不需要任何設置,記錄DEBUG及以上級別的所有日誌。如果需要配置,可以透過xml配置來完成:
<configuration>
    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>app.log</file>
        <encoder>
            <pattern>%d{HH:mm:ss,SSS} %-5p [%c] - %m%n</pattern>
        </encoder>
    </appender>
    <logger name="org.hibernate.SQL" level="DEBUG" />
    <logger name="org.hibernate.type.descriptor.sql" level="TRACE" />
    <root level="info">
        <appender-ref ref="FILE" />
    </root>
</configuration>

SLF4J - java 的簡單日誌記錄門面

2006 年左右,log4j 的創始人之一離開了該專案並創建了 slf4j - Simple Logging Facade for Java - log4j、JUL、common-loggins 和 logback 的包裝器。正如你所看到的,進展已經達到了他們在包裝器之上創建了一個包裝器的地步......而且,它分為兩部分:API(在應用程序中使用)和實現(添加為)每種類型的日誌記錄都有單獨的依賴關係。例如,slf4j-log4j12.jarslf4j-jdk14.jar。連接正確的實作就足夠了:整個專案都將與它一起工作。Slf4j 支援所有新功能,例如記錄的字串格式。之前也有這樣的問題。假設有一個日誌條目:
log.debug("User " + user + " connected from " + request.getRemoteAddr());
由於字串連接, 物件中user存在隱式轉換,這需要時間,從而減慢系統速度。user.toString()如果我們調試應用程序,一切都會正常。如果此類的日誌記錄等級為 INFO 或更高,就會出現問題。即這條日誌不應該被寫下來,也不應該進行字串拼接。理論上,這應該是由日誌庫本身決定的。而且,這竟然是log4j第一個版本的最大問題。他們沒有提供正常的解決方案,但建議這樣做:
if (log.isDebugEnabled()) {
    log.debug("User " + user + " connected from " + request.getRemoteAddr());
}
也就是說,他們建議寫 3(!),而不是一行日誌。日誌記錄應該最大限度地減少對程式碼的更改,三行顯然與一般方法相矛盾。slf4j 與 JDK 和 API 沒有相容性問題,因此一個漂亮的解決方案立即出現:
log.debug("User {} connected from {}", user, request.getRemoteAddr());
其中{}表示插入在方法中傳遞的參數。也就是說,第一個{}對應於user,第二個對應於{}- request.getRemoteAddr()。因此,只有當日誌記錄等級允許記錄時,該訊息才能串聯成一條訊息。此後,SJF4J迅速流行起來,是目前最好的解決方案。因此,我們將考慮使用bundle 的範例進行日誌記錄slf4j-log4j12

需要記錄什麼

當然,您不應該記錄所有內容。有時這是不必要的,甚至是危險的。例如,如果你承諾某人的個人數據,但不知何故被曝光,就會出現真正的問題,特別是在面向西方的專案上。但還有一些事情是必須記錄的
  1. 應用程式的開始/結束。我們需要知道應用程式實際上按我們的預期啟動並按預期結束。
  2. 安全問題。在這裡最好記錄密碼猜測嘗試、記錄重要使用者的登入等。
  3. 一些應用程式聲明。例如,業務流程中從一種狀態轉換到另一種狀態。
  4. 一些用於調試的信息,以及適當級別的日誌記錄。
  5. 一些 SQL 腳本。確實有需要這樣做的案例。再次,透過巧妙地調整級別,可以取得優異的效果。
  6. 在檢查正確操作的情況下,可以記錄執行的執行緒(Thread) 。

常見的日誌記錄錯誤

有很多細微差別,但以下是一些常見錯誤:
  1. 過多的日誌記錄。您不應該記錄理論上可能重要的每一個步驟。有一個規則:日誌對效能的負載不能超過10%。否則會出現效能問題。
  2. 將所有數據記錄到一個文件中。這將使讀取/寫入在某個時刻變得非常困難,更不用說某些系統上有檔案大小限制。
  3. 使用不正確的日誌記錄等級。每個日誌記錄等級都有明確的界限,應該受到尊重。如果邊界模糊,您可以商定使用哪個層級。

記錄層級

x:可見
致命的 錯誤 警告 資訊 偵錯 痕跡 全部
離開
致命的 X
錯誤 X X
警告 X X X
資訊 X X X X
偵錯 X X X X X
痕跡 X X X X X X
全部 X X X X X X X
什麼是日誌記錄等級?為了以某種方式對日誌進行排名,有必要給出某些名稱和差異。為此,引入了日誌記錄等級。級別在應用程式中設定。如果條目屬於指定級別以下的級別,則不會將其輸入日誌中。例如,我們有用於調試應用程式的日誌。在正常的生產工作中(當應用程式用於其預期目的時),不需要此類日誌。因此,日誌記錄的等級將高於調試等級。讓我們以 log4j 為例來看看層級。除 JUL 之外的其他解決方案都使用相同的等級。這裡它們按降序排列:
  • OFF:不寫入日誌,全部會被忽略;
  • FATAL:應用程式將無法再工作並停止的錯誤,例如 JVM 記憶體不足錯誤;
  • ERROR:出現需要解決的問題時的錯誤率。該錯誤不會使整個應用程式停止。其他查詢可能會正常運作;
  • WARN:表示包含警告的日誌。儘管系統拒絕並完成了請求,但發生了意外的操作;
  • INFO:記錄應用程式中重要操作的日誌。這些不是錯誤,這些不是警告,這些是系統的預期操作;
  • DEBUG:調試應用程式所需的日誌。確保系統完全按照預期執行,或描述系統的操作:「method1開始工作」;
  • TRACE:用於偵錯的較低優先權日誌,具有最低的日誌記錄等級;
  • ALL:記錄系統所有日誌的等級。
事實證明,如果在應用程式中的某個位置啟用了 INFO 日誌記錄級別,則所有級別都會被記錄,從 INFO 開始一直到 FATAL。如果日誌等級為FATAL,則僅記錄該等級的日誌。

記錄與傳送日誌:Appender

我們將使用 log4j 作為範例來考慮此過程:它提供了充足的記錄/發送日誌的機會:
  • 用於寫入檔案 - 解決方案DailyRollingFileAppender
  • 將資料接收到應用程式控制台 - ConsoleAppender
  • 將日誌寫入資料庫 - JDBCAppender
  • 透過 TCP/IP 控制傳輸 - TelnetAppender
  • 確保日誌記錄不會影響效能 - AsyncAppender
還有其他幾種實現:可以在此處找到完整列表。順便說一句,如果所需的附加程式不可用,這不是問題。您可以透過實作Appender介面來編寫自己的appender ,該介面僅接受log4j。

記錄節點

為了進行演示,我們將使用 slf4j 介面和 log4j 的實作。建立記錄器非常簡單:您需要在名為 的類別中編寫以下內容MainDemo,在其中完成日誌記錄:
org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(MainDemo.class);
這將為我們建立一個記錄器。若要建立日誌條目,您可以使用多種方法來指示將在哪個層級建立條目。例如:
logger.trace("Method 1 started with argument={}", argument);
logger.debug("Database updated with script = {}", script);
logger.info("Application has started on port = {}", port);
logger.warn("Log4j didn't find log4j.properties. Please, provide them");
logger.error("Connection refused to host = {}", host);
儘管我們傳遞的是類,但最終寫下的是類別和包的全名。這樣做是為了讓您可以將日誌記錄劃分為節點,並為每個節點配置日誌記錄等級和附加程式。例如,類別的名稱:com.github.romankh3.logginglecture.MainDemo- 在其中建立了一個記錄器。這就是它可以被劃分為日誌節點的方式。主節點是 null RootLogger。這是接收整個應用程式所有日誌的節點。其餘部分可以如下所示: 日誌記錄:什麼、如何、在哪裡、用什麼? - 4Appender 專門在日誌節點上配置其工作。現在,以 log4j.properties為例,我們將了解如何配置它們。

逐步配置Log4j.properties

現在我們將逐步設定一切,看看可以做什麼:
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
這一行表示我們正在註冊一個使用 org.apache.log4j.ConsoleAppender 實作的 CONSOLE 附加程式。該附加程式將資料寫入控制台。接下來,讓我們註冊另一個將寫入檔案的附加程式:
log4j.appender.FILE=org.apache.log4j.RollingFileAppender
值得注意的是,附加程式仍然需要配置。一旦我們已經註冊了附加程序,我們就可以確定節點中的日誌記錄等級以及將使用哪些附加程序。

log4j.rootLogger=偵錯、控制台、文件

  • log4j.rootLogger 表示我們將配置主節點,其中包含所有日誌;
  • 等號後面的第一個單字表示日誌將記錄在哪個等級及更高等級(在我們的例子中,這是 DEBUG);
  • 然後在逗號之後指示將使用的所有附加程式。
若要設定特定的日誌記錄節點,您需要使用下列條目:
log4j.logger.com.github.romankh3.logginglecture=TRACE, OWN, CONSOLE
它用於log4j.logger.配置特定節點,在我們的例子中它是com.github.romankh3.logginglecture. 現在讓我們討論設定 CONSOLE 附加程式:
# CONSOLE appender customisation
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.threshold=DEBUG
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=[%-5p] : %c:%L : %m%n
在這裡我們看到我們可以設定附加程式處理的層級。真實情況:日誌節點收到 info 等級的訊息,並將其傳遞給指派給它的appender,但是 warn 等級及更高等級的appender 接受了該日誌,但沒有對其執行任何操作。接下來,您需要決定在訊息中使用什麼模板。我在範例中使用 PatternLayout,但有很多解決方案。它們不會在本文中披露。設定 FILE 附加程式的範例:
# File appender customisation
log4j.appender.FILE=org.apache.log4j.RollingFileAppender
log4j.appender.FILE.File=./target/logging/logging.log
log4j.appender.FILE.MaxFileSize=1MB
log4j.appender.FILE.threshold=DEBUG
log4j.appender.FILE.MaxBackupIndex=2
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=[ %-5p] - %c:%L - %m%n
在這裡您可以設定日誌將寫入哪個文件,如下所示
log4j.appender.FILE.File=./target/logging/logging.log
錄音進入檔案logging.log。為了避免檔案大小出現問題,您可以設定最大值:在本例中為 1MB。MaxBackupIndex - 告訴有多少個這樣的檔案。如果建立的檔案數量超過此數量,則第一個檔案將被刪除。若要查看配置日誌記錄的真實範例,您可以存取GitHub 上的 開放儲存庫。

我們來合併一下結果

試著做你自己描述的一切:
  • 建立您自己的項目,類似於上例中的項目。
  • 如果您了解使用 Maven,我們將使用它;如果沒有,那麼這裡有一篇描述如何連接該庫的文章的連結。

讓我們總結一下

  1. 我們討論了Java有哪些解決方案。
  2. 幾乎所有已知的日誌庫都是在一個人的控制下編寫的:D
  3. 我們了解了哪些內容需要記錄,哪些內容不需要記錄。
  4. 我們計算出了日誌記錄等級。
  5. 我們熟悉了日誌節點。
  6. 我們了解了附加程式是什麼以及它的用途。
  7. 我們一步步配置了log4j.proterties檔。

附加材料

  1. JavaRush:日誌記錄。展開 strace 球
  2. JavaRush:記錄器講座
  3. Habr:Java 日誌記錄。你好世界
  4. Habr:Java 日誌記錄:惡夢的故事
  5. Youtube:戈洛瓦赫課程。記錄。第 1 部分第 2 部分第 3 部分第 4 部分
  6. Log4j:附加程序
  7. Log4j:佈局
另請參閱我的其他文章:
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION