2011-07-31 22 views
7

Có thể in tên luồng trong các câu lệnh tường trình được tạo bởi java.util.logging.Logger không? Một cách khác là thực hiện một số việc như sau:in tên chủ đề bằng cách sử dụng java.util.logging

logger.info(thread.getName() +" some useful info"); 

nhưng lặp lại và khung ghi nhật ký phải xử lý nó.

+0

Tôi tin rằng, việc sử dụng log4j hoặc slf4j sẽ sạch hơn các giải pháp được đề xuất trong câu trả lời. :) – Diablo

Trả lời

7

xấu hổ, nhưng trông giống như java.util.logging không thể làm điều này ...

Giá trị mặc định java.util.logging.SimpleFormatter không có khả năng đăng nhập tên chủ đề ở tất cả. java.util.logging.FileHandler hỗ trợ một vài trình giữ chỗ mẫu, không có trình giữ chỗ mẫu nào là tên chủ đề.

java.util.logging.XMLFormatter là gần nhất một, nhưng chỉ ghi thread id:

<record> 
    <date>2011-07-31T13:15:32</date> 
    <millis>1312110932680</millis> 
    <sequence>0</sequence> 
    <logger></logger> 
    <level>INFO</level> 
    <class>java.util.logging.LogManager$RootLogger</class> 
    <method>log</method> 
    <thread>10</thread> 
    <message>Test</message> 
</record> 

Nếu bạn nghĩ rằng chúng tôi đang nhận được gần - chúng tôi không. LogRecord lớp chỉ giữ ID luồng chứ không phải tên của nó - không phải là rất hữu ích.

1

Một số máy chủ ứng dụng ngầm đăng nhập ID luồng (tôi biết về WebSphere). Bạn có thể tạo riêng của mình LogFormatter. Các bản ghi được chuyển đến trình định dạng chứa ID chủ đề, xem here. Tôi đã thực hiện phương pháp đó cho Tomcat nhiều lần, nhưng nó cũng sẽ hoạt động trong môi trường Java SE.

BTW: Tên chủ đề không khả dụng cho LogRecord.

1

java.util.logging có nhiều đặc điểm kỳ lạ. bạn có thể thêm API mặt tiền để tinh chỉnh hành vi của mình

public class Log 

    Logger logger; 

    static public Log of(Class clazz) 
     return new Log(Logger.getLogger(clazz.getName())); 

    public void error(Throwable thrown, String msg, Object... params) 
    { 
     log(ERROR, thrown, msg, params); 
    } 

    void log(Level level, Throwable thrown, String msg, Object... params) 
    { 
     if(!logger.isLoggable(level)) return; 

     // bolt on thread name somewhere 
     LogRecord record = new LogRecord(...); 
     record.setXxx(...); 
     ... 
     logger.log(record); 
    } 

---- 

static final Log log = Log.of(Foo.class); 
.... 
log.error(...); 

Mọi người sử dụng nhật ký của java chủ yếu là vì họ không muốn có phụ thuộc bên thứ 3. Đó cũng là lý do tại sao họ không thể phụ thuộc vào mặt tiền khai thác hiện có như apache hoặc slf4j.

2

Tôi gặp sự cố tương tự. Như đã trả lời ở đây How to align log messages using java.util.logging bạn có thể mở rộng java.util.logging.Formatter nhưng thay vì nhận được LogRecord#getThreadID() bạn có thể nhận tên chủ đề bằng cách gọi Thread.currentThread().getName() như thế này:

public class MyLogFormatter extends Formatter 
{ 

    private static final MessageFormat messageFormat = new MessageFormat("[{3,date,hh:mm:ss} {2} {0} {5}]{4} \n"); 

    public MyLogFormatter() 
    { 
     super(); 
    } 

    @Override 
    public String format(LogRecord record) 
    { 
     Object[] arguments = new Object[6]; 
     arguments[0] = record.getLoggerName(); 
     arguments[1] = record.getLevel(); 
     arguments[2] = Thread.currentThread().getName(); 
     arguments[3] = new Date(record.getMillis()); 
     arguments[4] = record.getMessage(); 
     arguments[5] = record.getSourceMethodName(); 
     return messageFormat.format(arguments); 
    } 

} 
+7

Điều này sẽ không đặt vào tên luồng của chuỗi gọi trình định dạng chứ không phải tên luồng của chuỗi đã tạo mục nhật ký? Tôi đoán chúng có thể giống nhau trong một số tình huống nhưng không có sự bảo đảm. – pauli

1

Một vài câu trả lời ở trên gợi ý rằng LogRecord.getThreadId() trả về một thread ID có ý nghĩa, và tất cả chúng ta đang thiếu là một cách để tương quan với tên của chủ đề.

Thật không may LogRecord.getThreadId() trả về giá trị int không tương ứng với id dài của chuỗi tạo ra thông điệp tường trình.

Vì vậy, chúng tôi không thể chỉ sử dụng ManagementFactory.getThreadMXBean() để giải quyết tên chuỗi. Nó dẫn đến các tên luồng ngẫu nhiên.

Nếu bạn chắc chắn rằng thiết bị Ghi nhật ký của bạn luôn định dạng trong cùng một chuỗi với người gọi, thì bạn có thể tạo Trình định dạng tùy chỉnh như được đề xuất ở trên và gọi Thread.currentThread(). GetName().

Dường như mặt tiền Ghi nhật ký hoặc thư viện của bên thứ ba là các tùy chọn hoàn toàn an toàn.

-1

Để bổ sung cho câu trả lời @ l245c4l: Thay vì sử dụng SimpleFormatter() sử dụng:

//fileHandler.setFormatter(new SimpleFormatter()); 

class MyFormatter extends Formatter { 
    private final MessageFormat messageFormat = new MessageFormat("{0,date}, {0,time} {1} {2}: {3} [T:{4}] {5}\n"); 

    public String format(LogRecord record) 
    { 
     Object[] arguments = new Object[6]; 
     arguments[0] = new Date(record.getMillis()); 
     arguments[1] = record.getSourceClassName(); 
     arguments[2] = record.getSourceMethodName(); 
     arguments[3] = record.getLevel(); 
     arguments[4] = Long.toString(Thread.currentThread().getId()); 
     arguments[5] = record.getMessage(); 

     return messageFormat.format(arguments); 
    } 
} 

fileHandler.setFormatter(new MyFormatter()); 

Logger myLogger = Logger.getLogger("<LOGGER_NAME>"); 
myLogger.addHandler(fileHandler); 

nơi T:{4} là thread id (argument 4).

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