2013-12-13 71 views
2

在我一直在努力的每個項目中,總會有日誌文件變得太大的問題。 現成的解決方案是使用Log4j RollingFileAppender並設置允許的最大尺寸。 但是有些情況下,在有人手動干預之前,相同的異常會非常快速地重複達到最大值。在這種情況下,由於滾動策略,最終會丟失在發生異常之前發生的重要事件的信息。 有人可以提出解決這個問題?如何減小日誌大小

P.S.我能想到的事情是保存目前發生的Exceptions的緩存,這樣當再次發生同樣的異常時,我不會記錄大量的堆棧跟蹤行。不過,我認爲這一定是一個衆所周知的問題,我不想重新發明輪子。

+0

什麼樣的例外?如果這是你可以修復或改進的東西,那麼考慮你可能試圖治療症狀而不是問題。您也可以考慮使用[FileHandler](http://docs.oracle.com/javase/7/docs/api/java/util/logging/FileHandler.html)來使用循環日誌。您可以指定日誌文件的數量及其最大大小,並通過它們進行旋轉。另外,考慮讓你的代碼像@TimB所建議的那樣按常規壓縮日誌。 – turbo

回答

1

購買更大的硬盤驅動器並設置批處理以定期自動壓縮舊日誌。

(Zip將檢測重複的異常模式並非常有效地對其進行壓縮)。

+0

感謝Tim B.然而,硬盤已經很龐大:但是它被許多服務共享,每個服務都生成它自己的日誌。我正在尋找解決該問題的軟件解決方案。 – Gep

+0

它實際上可以用Java來完成,我有一個我在一個android項目中使用的類,它可以將日誌壓縮,甚至可以將新的日誌文件添加到zip文件中。不要不同意你的答案,只是提供一種不同的方法。 – turbo

3

使用Log4J功能在使用「滾動文件附加程序」達到指定大小後壓縮日誌文件。對於1MB文件,Zip大約爲85KB。 爲此,指定觸發器策略根據大小進行壓縮並在滾動策略中指定zip文件。
讓我知道你是否需要信息。

+0

不存在任何鏈接? – shareef

+0

這只是一個解決方案,而不是具體的答案。但你可以通過谷歌搜索或[這裏](http:// stackoverflow。)找到壓縮日誌文件[這裏](http://2min2code.com/articles/log4j_intro/rolling_archiving_file_on_size_prop)的例子。com/questions/3329385/compress-log4j-files),但使用SizeBasedRollingPolicy。 – dARKpRINCE

0

如果達到最大大小,則使用策略,追加到新的日誌文件中。並像日常一樣運行調度程序以擦除舊的日誌文件

3

有兩個方向來解決這個問題:系統端和開發端。在系統方面(即應用程序部署和運行之後)處理這個問題已經有了幾個答案。不過,我想解決發展問題。

我看到的一個很常見的模式是在每個級別處記錄例外。我看到UI組件,EJB的,連接器,線程,助手類,pojos等等,記錄發生的所有異常。在很多情況下,無需檢查日誌級別。這具有您遇到的確切結果,以及調試和故障排除所花費的時間超過必要的時間,因爲人們必須篩查所有重複的錯誤。

我的建議是不要在下列代碼:

  • 認爲。並不是每一個例外都是致命的,而且在很多情況下實際上並不相關(例如,在流上操作close()IOException)。我不想說「不要記錄異常」,因爲你肯定不想不放過任何一個問題,那麼在最壞的情況,把日誌語句條件檢查中的調試級別

    if(logger.isDebugEnabled()){
      // log exception
    }

  • 日誌只在頂層。我確信這會遇到一些負面影響,但我的感覺是,除非班級是應用程序或組件的頂級界面,否則例外不再被傳遞,那麼應該記錄例外而不是 。換句話說,如果重新拋出異常,包裝,拋出或聲明爲從方法拋出異常,則不要在該級別上記錄它。

例如,第一種情況是造成太多的日誌報表的問題,因爲它很可能調用者和任何被稱爲還將記錄有關錯誤的異常或一些聲明。

public void something() throws IllegalStateException{ 
     try{ 
     // stuff that throws some exception 
     }catch(SomeException e){ 
     logger.error(e); // <- NO because we're throwing one 
     throw new IllegalStateException("Can't do stuff.",e); 
     } 
} 

由於我們在扔它,不要記錄它。

public void something() throws IllegalStateException{ 
     try{ 
     // stuff that throws some exception 
     }catch(SomeException e){ 
     // Whoever called Something should make the decision to log 
     throw new IllegalStateException("Can't do stuff.",e); 
     } 
} 

但是,如果something停止傳播異常,則應記錄它。

public void something(){ 
     try{ 
     // stuff that throws some exception 
     }catch(SomeException e){ 
     if(logger.isLogLevelEnabled(Log.INFO)){ 
      logger.error(e);      // DEFINITELY LOG! 
     } 
     } 
} 
+2

非常有用的文章,但它忽略瞭如何處理更常見的情況:應用程序堆棧中使用的大量庫之一實際上不會拋出異常;例如,當您使用JEE容器時,這是一個挑戰。除了最小化日誌時刻之外,它還有助於微調特定程序包/類庫的日誌過濾器,從而過濾掉所有無用的垃圾。 – Gimby

+0

@Gimby同意。偉大的一點。 – MadConan

+0

謝謝MadConan和Gimby。迄今爲止我的最佳答案。 – Gep

1

根據我的經驗,日誌被用作正確測試和調試代碼的替代品。程序員自言自語道:「我不能確定這段代碼是否正常工作,所以我會在其中添加日誌消息,所以當它失敗時,我可以使用日誌消息來找出錯誤。」

不要只是在沒有想到的情況下噴灑日誌消息,而應將每條日誌消息視爲軟件用戶界面的一部分。 DBA,網站管理員或系統管理員的用戶界面,但仍是用戶界面的一部分。每條消息都應該做一些有用的事該信息應該是行動的動力,或者提供他們可以使用的信息。如果消息無法使用,請不要記錄。

爲每條消息提供適當的日誌記錄級別。如果消息沒有描述實際問題,也沒有提供通常有用的狀態信息,則該消息可能僅用於調試,因此將其標記爲DEBUG或TRACING消息。你平常的Log4J配置根本不應該寫這些消息。只有在調試問題時,才能更改配置以寫入它們。

您提到這些消息是由於經常發生的異常。並非所有的例外都表明程序中存在錯誤,甚至是程序運行中的問題。您應該記錄全部異常,指出程序中存在錯誤,並記錄堆棧跟蹤。在很多情況下,你幾乎需要找出錯誤的原因。如果您擔心的異常是由於錯誤引起的,那麼您將重點放在錯誤的問題上:您應該修復錯誤。如果一個異常沒有在你的程序中指出一個錯誤,你不應該爲它記錄一個堆棧跟蹤。堆棧跟蹤僅適用於試圖調試問題的程序員。如果該例外根本沒有指出問題,則根本不需要登錄。