log4j不打印堆栈跟踪的例外
我正在使用tomcat的log4j。 当我在JSP中loggingexception时,servlets:
private Logger _log = Logger.getLogger(this.getClass()); ... try{...} catch (Exception e) { _log.error("Error refreshing all prices", e); }
我只得到exception的第一行,没有堆栈跟踪。
17-Feb 17:37:45 ERROR AutoContrib:175 – 发布csv文件时发生exception:java.lang.ArrayIndexOutOfBoundsException
不是很有帮助!
我的log4j.properties文件(/tomcat/common/classes/log4j.properties)看起来像这样:
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
实际上,这可能是由于热点优化:在抛出一定数量的exception之后,停止打印跟踪。 这可以通过虚拟机argclosures,请参阅:
从http://www.oracle.com/technetwork/java/javase/relnotes-139183.html :
服务器VM中的编译器现在为所有“冷”内置exception提供正确的堆栈回溯。 出于性能考虑,当这样的exception被抛出几次时,该方法可能被重新编译。 重新编译之后,编译器可以使用不提供堆栈跟踪的预先分配的exception来select更快的策略。 要完全禁用预分配的exception,请使用以下新标志:-XX:-OmitStackTraceInFastThrow。
更多在这里:
你已经发布的应该显示在javadoc中所述的堆栈跟踪。
请注意,如果您不包含消息(并且只是调用logger.error(ex)
),那么不会logging堆栈跟踪。
有两种重载的错误方法。
-
logger.error(ex);
-
logger.error("some oops string ", ex);
如果您使用第一种方法,这将只打印例外的名称。 如果使用第二种方法,则会出现一些消息,同时会打印类似于e.printStackTrace()
方法的完整堆栈跟踪。
就像上面的@卢哈回答的那样,我也是一样挣扎着,终于为我工作了。 这种方法的好处是我们不必修改像JVM,Log4J这样的系统级设置,因为我们不知道它可能会导致新的意外惊喜!
try { ... .. } catch (Exception er) { ByteArrayOutputStream os = new ByteArrayOutputStream(); er.printStackTrace(new PrintStream(os)); LOGGER.error(new String(os.toByteArray())); //LOGGER.error(er); }
我没有使用fillStackTrace调用,所以我不能评论,如果这将工作。 另一种方法是使用一个从Exception中返回格式化文本的小方法。
public static String getStackTrace(Exception e) { StringWriter sWriter = new StringWriter(); PrintWriter pWriter = new PrintWriter(sWriter); e.printStackTrace(pWriter); return sWriter.toString(); }
在你的日志代码中,你可以写:
logger.error("An exception occurred: " + Utils.getStackTrace(e));
我没有看到你的configuration有什么问题,所以尝试升级log4j
到一个更新的(不一定是最新的)版本。
虽然在这种情况下不是问题,但是最好让你的logging器保持private static final
使用你的代码示例:
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()); }
你会看到所有的堆栈跟踪显示。
PS。 使logging器单身…(检查我的声明)刚刚声明public class MyClass {
你可以在你的catch块中添加这些代码行。
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); }
- 日志logging,面向方面的编程和dependency injection – 试图理解这一切
- Log4j2configuration – 找不到log4j2configuration文件
- 来自subprocess命令的实时输出
- 单个Logger的每个appender的日志级别
- Apache Commons Logging的运行时发现algorithm有什么问题
- Docker守护进程日志在哪里?
- Chrome / Firefox console.log总是附加一行说明未定义的行
- Google analytics 3.08 IOS idfa class missing,不会收集idfa
- closureshibernate日志logging控制台输出