2010-02-19 34 views
54

Tôi đang sử dụng log4j với tomcat. Khi tôi ghi lại ngoại lệ trong các JSP của mình, các servlet:log4j không in stacktrace cho trường hợp ngoại lệ

private Logger _log = Logger.getLogger(this.getClass()); 
... 
try{...} catch (Exception e) { 
    _log.error("Error refreshing all prices", e); 
} 

Tôi chỉ nhận được dòng đầu tiên của trường hợp ngoại lệ, không có chồng xếp chồng.

17-Tháng Hai 17:37:45 LỖI AutoContrib: 175 - ngoại lệ khi xuất bản csv file: java.lang.ArrayIndexOutOfBoundsException

Không rất hữu ích ở tất cả!

log4j.properties My tập tin (/tomcat/common/classes/log4j.properties) trông như thế này:

log4j.appender.stdout=org.apache.log4j.ConsoleAppender 
log4j.appender.stdout.Target=System.out 
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 
log4j.appender.stdout.layout.ConversionPattern=%d{dd-MMM HH:mm:ss} %5p %c{1}:%L - %m%n 
log4j.appender.stdout.threshold=info 

log4j.appender.file=org.apache.log4j.RollingFileAppender 
log4j.appender.file.maxFileSize=5000KB 
log4j.appender.file.maxBackupIndex=10 
log4j.appender.file.File=${catalina.home}/logs/web.log 
log4j.appender.file.layout=org.apache.log4j.PatternLayout 
log4j.appender.file.layout.ConversionPattern=%d{dd-MMM HH:mm:ss} %5p %c{1}:%L - %m%n 
log4j.appender.file.threshold=info 

log4j.rootLogger=debug, stdout, file 
+0

Theo như tôi có thể thấy bạn đang làm tất cả vì nó nên được thực hiện ... bạn sẽ thấy tất cả các stacktrace trong nhật ký của bạn. Bạn đang sử dụng phiên bản nào của log4j, Java và Tomcat? –

+0

Chúng tôi đang sử dụng tomcat 5.5.17 và log4j-1.2.14 (Tôi nghĩ chúng tôi sẽ nâng cấp lên tc6 trong tương lai gần, nhưng tôi không chắc chắn sẽ tạo ra sự khác biệt nào?) – Ryan

Trả lời

58

Thực ra, có thể do tối ưu hóa điểm phát sóng: sau một số lượng nhất định của cùng một ngoại lệ được ném, nó dừng in ra dấu vết. Điều này có thể được tắt với một arg VM, xem:

Từ http://www.oracle.com/technetwork/java/javase/relnotes-139183.html:

Trình biên dịch trong máy chủ ảo hiện nay cung cấp đống vết lùi đúng cho tất cả "lạnh" built-in ngoại lệ. Đối với mục đích hiệu suất, khi ngoại lệ như vậy được ném một vài lần, phương pháp có thể được biên dịch lại. Sau khi biên dịch lại, trình biên dịch có thể chọn chiến thuật nhanh hơn bằng cách sử dụng ngoại lệ được phân phát không cung cấp dấu vết ngăn xếp. Để tắt hoàn toàn việc sử dụng ngoại lệ được phân phát, hãy sử dụng cờ mới này: -XX: -OmitStackTraceInFastThrow.

More đây:

http://jawspeak.com/2010/05/26/hotspot-caused-exceptions-to-lose-their-stack-traces-in-production-and-the-fix/

0

Sử dụng mẫu mã của bạn:

private static final Logger _log = Logger.getLogger(MyClass.class); 
... 
try{...} catch (Exception e) { 
    //Change 
    //_log.error("Error refreshing all prices", e); 

    //To 
    _log.error("Error refreshing all prices", e.fillInStackTrace()); 
} 

Bạn sẽ thấy tất cả các theo dõi ngăn xếp được hiển thị.

PS. Tạo Logger một singleton ... (kiểm tra khai báo của tôi) ngay sau khi khai báo public class MyClass {

+0

Cảm ơn lời khuyên! Tôi sẽ cố gắng này ngay bây giờ. BTW, cho cách tiếp cận singleton bạn không thể sử dụng 'this' với getLoggger tĩnh(). Tôi đoán tôi có thể sử dụng getLogger (MyClass.class) – Ryan

+0

True Ryan !. Nó làm cho instantiation nhanh hơn thấy rằng singleton đã tồn tại sau khi sáng tạo. –

+0

lý tưởng, anh ta không cần điều này – Bozho

0

Tôi không thấy điều gì sai với cấu hình của bạn, vì vậy hãy thử nâng cấp log4j lên phiên bản mới hơn (không nhất thiết phải là mới nhất).

Mặc dù không phải là vấn đề trong trường hợp này, bạn nên thực hiện logger của bạn private static final

1

Tôi đã không được sử dụng các cuộc gọi fillStackTrace, vì vậy tôi không thể bình luận nếu điều đó sẽ làm việc. Một cách tiếp cận khác là sử dụng một phương thức nhỏ trả về văn bản đã định dạng từ một Ngoại lệ.

public static String getStackTrace(Exception e) 
{ 
    StringWriter sWriter = new StringWriter(); 
    PrintWriter pWriter = new PrintWriter(sWriter); 
    e.printStackTrace(pWriter); 
    return sWriter.toString(); 
} 

Trong mã đăng nhập của bạn, bạn có thể viết:

logger.error("An exception occurred: " + Utils.getStackTrace(e)); 
+0

lý tưởng, anh ta không cần điều này – Bozho

15

Những gì bạn đã gửi sẽ hiển thị stack trace như đã nêu trong javadoc.

Lưu ý rằng nếu bạn không bao gồm một tin nhắn (và chỉ cần gọi logger.error(ex)) thì dấu vết ngăn xếp sẽ không được ghi lại.

+3

Ah. Nó đây rồi. Đây là những gì đã cắn tôi. Việc ghi nhật ký lỗi sẽ không in dấu vết ngăn xếp. Bạn cần phải đăng nhập một tin nhắn với lỗi để có được điều đó. – rbwhitaker

+0

Điều này hữu ích. Cảm ơn bạn. Chúng ta có thể cấu hình log4j để nó hiển thị một dấu vết đầy đủ ngay cả khi chúng ta chỉ cung cấp đối tượng ngoại lệ? –

3

Giống như trả lời bằng cách @Luhar trên, tôi phải vật lộn với điều tương tự và cuối cùng này làm việc cho tôi; Điều tốt về cách tiếp cận này là chúng ta không phải lo lắng với các thiết lập mức hệ thống như JVM, Log4J vì chúng ta không bao giờ biết nó có thể dẫn đến bất ngờ mới bất ngờ!

try { 

... 
.. 

} catch (Exception er) { 
     ByteArrayOutputStream os = new ByteArrayOutputStream(); 
     er.printStackTrace(new PrintStream(os)); 
     LOGGER.error(new String(os.toByteArray())); 
     //LOGGER.error(er); 
} 
0

Bạn có thể thêm các dòng mã này vào khối catch của mình.

catch (SQLException e) { 
      CharArrayWriter cw = new CharArrayWriter(); 
      PrintWriter w = new PrintWriter(cw); 
      e.printStackTrace(w); 
      w.close(); 
      String trace = cw.toString(); 

    log.error("This is complete stacktrace", trace); 
} 
6

Có hai phương pháp quá tải cho phương pháp lỗi.

  1. logger.error(ex);
  2. logger.error("some oops string ", ex);

nếu bạn sử dụng phương pháp 1, mà sẽ chỉ in tên của các ngoại lệ. nếu bạn sử dụng phương pháp thứ 2, một số thư cùng với ngoại lệ sẽ in dấu vết ngăn xếp hoàn chỉnh tương tự như phương thức e.printStackTrace().

+0

Cảm ơn. Tôi nghĩ đây là câu trả lời đúng. –

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