2011-04-18 33 views
54

Tôi đang sử dụng log4j để đăng nhập lỗi và thông tin hệ thống khác. nhưng đến thông tin được ghi hai lần ở cấp độ INFO.log4j logging hai lần

public static void main(final String... args) throws Exception { 

    LOGGER.info("program started"); 
    try { 
     // try body codes 
    } catch (Exception ex) { 
     LOGGER.info("program start-up failed.",ex); 
    } 
} 

tuy nhiên khi chương trình bắt đầu hoặc thất bại thông tin đăng nhập hai lần, bất kỳ ai có thể giúp tôi tìm ra nguyên nhân.

+0

Có thể sự cố cấu hình hoặc sự cố khởi tạo. Bạn khởi tạo trình ghi nhật ký ở đâu? Đừng gọi bạn là Logger.getLogger (SomeClass.class) hai lần? Một số mã bổ sung có thể cung cấp cho chúng tôi thêm thông tin để giúp bạn. – MaSEL

Trả lời

75

Có vẻ như thư của bạn đang được ghi nhật ký một lần bởi trình ghi nhật ký cụ thể vì bạn có thể có cả hai trình cấu hình ứng dụng (có thể ở các vị trí khác nhau trong tệp thuộc tính và sau đó trong mã).

Điều này có thể được giải quyết bằng cách đặt độ nhạy thành sai trên trình ghi nhật ký của bạn. Log4j manual đề cập đến độ nhạy trong phần Trình bày và Bố cục.Kiểm tra rằng hãy ra

+2

Đây có phải là cách bạn * nên giải quyết vấn đề này hay một băng trợ giúp che giấu vấn đề cấu hình lớn hơn không? –

+1

Nếu không có logger, không có gì được ghi lại. Khi tôi thêm logger trở lại, nó đăng nhập hai lần. Khi tôi đặt độ nhạy thành false, nó được ghi lại một lần. Những gì đang xảy ra ở đây? –

+0

@DanielKaplan Nếu logger của bạn có một số cấu trúc phân cấp, vâng. Diễn giải từ liên kết thủ công, giả sử bạn chỉ muốn thư ERROR cho tất cả các lớp ngoại trừ Foo, mà bạn muốn xem tất cả thư từ đó. Bạn sẽ đặt độ nhạy của trình đăng nhập Foo thành sai, vì vậy mọi thông báo L ERI không tiếp tục đến gốc và được in lại. Nếu không có sự bổ sung, cấu hình sẽ phức tạp hơn và ít bảo trì hơn, vì vậy tôi muốn nói điều này là chính xác. – whrrgarbl

29

Đồng ý với atlantis.

log4j.rootCategory=INFO, console 
log4j.logger.org.hibernate=INFO 

Cài đặt thuộc tính ở trên sẽ làm đăng nhập kép.

Tuy nhiên thêm

log4j.additivity.org.hibernate=false 

cố định vấn đề này.

Kiểm tra trang 62 của cuốn sách này. http://books.google.com/books?id=hZBimlxiyAcC&printsec=frontcover#v=onepage&q&f=false

+6

không nên là 'sai', không phải 'đúng'? –

+0

Sách của Google dường như ẩn một cách ngẫu nhiên các trang nhất định. [Đây] (http://veerasundar.com/blog/2009/08/log4j-tutorial-additivity-what-and-why/) một bài đăng trên blog mà tôi thấy hữu ích. Nó bao gồm một ví dụ rộng hơn bao gồm một số mục nhập ** log4j.category ... ** –

28

Đối với những định dạng sử dụng XML:

<logger name="package.class" additivity="false"> 
    <level value="info" /> 
    <appender-ref ref="file" /> 
    <appender-ref ref="console" /> 
</logger> 

Lưu ý: Theo mặc định, Loggers có cờ additivity họ thiết lập là true.

2

Nếu bạn có thể chạy chương trình bằng trình gỡ lỗi Java, hãy đặt điểm ngắt trong chương trình nơi xảy ra một trong các cuộc gọi ghi nhật ký kép này.

Kiểm tra đối tượng nhật ký trong trình gỡ lỗi. Nếu nó là một org.apache.log4j.Logger (v 1.2.x) thì nó có thể có một AppenderAttachableImpl. Bạn có thể truy vấn AppenderAttachableImpl cho danh sách appender.

Nếu bạn tìm thấy nhiều hơn 1 appender, điều này có thể là vấn đề - và một đầu mối để sửa chữa nó.

2

Chỉ cần chỉ cần thêm

logger.setadditivity(false); 

mã của bạn (Reference).

Chúng tôi đang có kết quả gấp đôi trong bảng điều khiển, đó là vì người phụ trách không phải là người độc thân, họ là phụ gia. Có nghĩa là, một thể loại kế thừa tất cả các appenders từ tổ tiên của nó (theo mặc định). Nếu chúng ta thêm một appender vào một category và nó ghi vào cùng một luồng cơ bản (console, cùng một file, vv) như một appender khác, cùng một thông điệp tường trình sẽ xuất hiện hai lần (hoặc nhiều hơn) trong log. Ngoài ra, nếu hai danh mục trong một cấu trúc phân cấp được cấu hình để sử dụng cùng một tên của appender, Log4j sẽ ghi hai lần vào appender đó. Được định cấu hình cho danh mục đó

0

Một giải pháp thay thế tiềm năng để điều chỉnh thuộc tính additivity là kiểm tra logger của bạn từ cụ thể nhất cho đến chung nhất. Trong ví dụ sau, chúng tôi hy vọng sẽ thấy việc ghi nhật ký kép trong Bảng điều khiển cho bất kỳ sự kiện nhật ký nào xảy ra trong foo.bar.LoggingExampleClass. Nó sẽ an toàn để loại bỏ thêm appender Console từ foo.bar.LoggingExampleClass Logger vì nó đã được Root logger bao trả.

<Logger name="foo.bar.LoggingExampleClass" level="DEBUG"> 
    <AppenderRef ref="Console" /> <!-- THIS APPENDER COULD BE REMOVED --> 
    <AppenderRef ref="FooBarPackageLogging" /> 
</Logger> 

<Root level="WARN"> 
    <AppenderRef ref="Console" /> 
    <AppenderRef ref="MainLogFile" /> 
</Root> 

Có sự cân bằng với cả phương pháp điều chỉnh độ nhạy và cách tiếp cận điều chỉnh trình điều chỉnh. Tắt tính năng bổ sung có thể vô tình dừng trình phụ của trình ghi nhật ký mức mong muốn từ việc sử dụng. Trong ví dụ trên, đặt thuộc tính additivity="false" trên foo.bar.LoggingExampleClass Logger có nghĩa là sự kiện ghi nhật ký sẽ không được thêm vào MainLogFile được tham chiếu trong trình ghi nhật ký Gốc.

Mặt khác, dựa vào phụ huynh có thể có vấn đề nếu các phụ huynh thay đổi mà không kiểm tra các hiệu ứng trên logger chi tiết hơn. Ví dụ, giả sử có một yêu cầu rằng foo.bar.LoggingExampleClass sự kiện ghi nhật ký nên được ghi vào Console. Họ hiện đang ở trong cấu hình ví dụ ở trên do sự bổ sung, ngay cả khi trình bổ sung Bảng điều khiển của foo.bar.LoggingExampleClass Logger bị xóa. Tuy nhiên, nếu ứng dụng Console cũng bị xóa khỏi trình ghi nhật ký gốc mà không có bất kỳ điều chỉnh bổ sung nào, yêu cầu sẽ không còn được đáp ứng nữa.

Các vấn đề liên quan