2011-10-28 25 views
5

tôi muốn biết cách sử dụng api java.util.logging, để có thông báo tường trình được ghi trong tệp nhật ký khác nhau tùy thuộc vào mức sử dụng. Nếu mức độ là INFO thì tôi muốn có thông điệp được viết trong /log/info.log và cứ thế. Mức 3 được xác định là nghiêm trọng, cảnh báo và thông tin.Sử dụng API java.util.logging để đăng nhập các cấp khác nhau để phân tách các tệp

+0

bạn đang sử dụng api ghi nhật ký java nào? Đối với log4j, java util logging và slf4j bạn có thể thiết lập các appender làm những gì bạn muốn, nhưng cấu hình khác nhau cho mỗi người trong số họ. – sbridges

+0

Xin lỗi, tôi không sử dụng Log4j, nhưng tôi đang sử dụng api ghi nhật ký java được cung cấp bởi jdk. – xtrem06

Trả lời

3

Bạn sử dụng tùy chỉnh Handlers để ghi nhật ký ghi.

Đây là một ví dụ đơn giản nhưng đầy đủ mà bạn có thể xây dựng.

import java.io.IOException; 
import java.util.logging.FileHandler; 
import java.util.logging.Level; 
import java.util.logging.LogRecord; 

public class LevelBasedFileHandler extends FileHandler 
{ 
    public LevelBasedFileHandler(final Level level) throws IOException, SecurityException 
    { 
     super(); 
     super.setLevel(level); 
    } 

    public LevelBasedFileHandler(final String s, final Level level) throws IOException, SecurityException 
    { 
     super(s); 
     super.setLevel(level); 
    } 

    public LevelBasedFileHandler(final String s, final boolean b, final Level level) throws IOException, SecurityException 
    { 
     super(s, b); 
     super.setLevel(level); 
    } 

    public LevelBasedFileHandler(final String s, final int i, final int i1, final Level level) throws IOException, SecurityException 
    { 
     super(s, i, i1); 
     super.setLevel(level); 
    } 

    public LevelBasedFileHandler(final String s, final int i, final int i1, final boolean b, final Level level) throws IOException, SecurityException 
    { 
     super(s, i, i1, b); 
     super.setLevel(level); 
    } 

    @Override 
    public void setLevel() { throw new UnsupportedOperationException("Can't change after construction!"); } 

    // This is the important part that makes it work 
    // it also breaks the contract in the JavaDoc for FileHandler.setLevel() 
    @Override 
    public void publish(final LogRecord logRecord) 
    { 
     if (logRecord.getLevel().equals(super.getLevel()) 
     { 
      super.publish(logRecord); 
     } 
    } 
} 

và ở đây là làm thế nào để sử dụng nó

try 
{ 
    // I use the Anonymous logger here, but any named logger will work as well 
    final Logger l = Logger.getAnonymousLogger(); 
    l.addHandler(new LevelBasedFileHandler("/tmp/info.log", Level.INFO)); 
    l.addHandler(new LevelBasedFileHandler("/tmp/warn.log", Level.WARNING)); 
    l.addHandler(new LevelBasedFileHandler("/tmp/server.log", Level.SEVERE)); 

    l.info("This is an INFO message"); 
    l.warning("This is a WARNING message"); 
    l.severe("This is a SEVERE message"); 
} 
catch (final IOException e) 
{ 
    // ignore this for this example, you should never do this in real code 
} 

bạn sẽ nhận được ba tác phẩm trong /tmp mỗi chỉ với những thông điệp cho từng cấp đăng nhập đặc biệt trong đó.

Lưu ý, tôi thích cách tiếp cận kiểu Dependency Injection khi yêu cầu Level trong hàm tạo nên bạn không thể "quên" để gọi .setLevel() khi sử dụng lớp con này. Tôi cũng bị vô hiệu hóa vì .setLevel() gọi nó và thay đổi sẽ phá vỡ các ngữ nghĩa của lớp con"

Chỉ cần cho đầy đủ, bạn có thể sử dụng một java.util.logging.Filter để acomplish điều tương tự. Nó không phải là gói gọn nhưng nó là một sự thay thế. Đó là hơn mã và tiết hơn, do đó nhiều hơn để không có được quyền.

final FileHandler infoFileHandler = new FileHandler("/tmp/info.log"); 
infoFileHandler.setFilter(new Filter() 
{ 
    public boolean isLoggable(final LogRecord logRecord) 
    { 
     return logRecord.getLevel().equals(Level.INFO); 
    } 
}); 

Cá nhân tôi vẫn thích cách tiếp cận sub-class tốt hơn, nó ít dễ bị lỗi và nhiều hơn nữa tự chủ tài liệu như về mục đích và ý định của mình.

+0

Cảm ơn câu trả lời hay. – xtrem06

+0

Bạn không cần 'LevelBasedFileHandler' vì mỗi Handle có' setLevel'. Chỉ cần 'h = new FileHandler (...); h.setLevel (...) ' – bestsss

+0

@bestss setLevel() chỉ giới hạn ở ** tin nhắn cấp ** thấp hơn, nhưng chấp nhận tin nhắn mức cao hơn. Đọc javadoc trên đó. "Đặt mức nhật ký chỉ định mức độ tin nhắn nào sẽ được Trình xử lý này ghi lại. Các mức tin nhắn thấp hơn giá trị này sẽ bị hủy." Yêu cầu là ** chỉ ** các cấp được chỉ định. –

-1

Giả sử bạn sử dụng log4j để làm nhật ký của mình. Bạn sẽ cần phải viết một appender tùy chỉnh, và thêm nó vào mỗi logger.

  • hướng dẫn đơn giản

Trong appender tùy chỉnh, bạn chỉ cần có một câu lệnh if mà nhìn vào các loại nhật ký, và hiện các hành động cần thiết. Đặc biệt, có FileAppenders có thể được mở rộng đến rất tự nhiên theo nhu cầu này. http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/FileAppender.html

  • dụ More nhã

Thay vì mã hóa riêng của bạn, hãy cố gắng chỉ đơn giản là thiết lập một tập tin cấu hình!

http://www.vaannila.com/log4j/log4j-file-appender-example-1.html

này sẽ làm chính xác những gì bạn cần.

+0

Ok, có thể thực hiện tương tự với api ghi nhật ký do jdk cung cấp không? – xtrem06

+0

Trên thực tế, các giải pháp được cung cấp trong exemple, không phải là những gì tôi muốn đạt được, đặc biệt là một với các tập tin cấu hình. Trong giải pháp này, đăng nhập một tin nhắn trên một tập tin hoặc khác phụ thuộc vào gói bạn đang có. – xtrem06

0

Vì mọi người đều nói về log4j ... Đây là một câu trả lời hữu ích hơn:

Thêm các chốt khác nhau (các trình xử lý tệp cho các tệp) và đặt các cấp trên các trình xử lý. Mức cho logger phải cho phép tiết kiệm/thoải mái nhất để truyền cho các trình xử lý.

Tôi không sử dụng tệp thuộc tính để thiết lập jul.Logger nhưng chỉ là một số xml nhà ủ. Nếu bạn không thể làm điều đó thông qua các tập tin thuộc tính, chỉ cần sử dụng logger.getHandler() và thiết lập các mức thích hợp.

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