log4j n’imprime pas la trace de la stack pour les exceptions

J’utilise log4j avec tomcat. Lorsque je journalise des exceptions dans mes JSP, les servlets:

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

Je n’obtiens que la première ligne de l’exception, sans stacktrace.

17-Feb 17:37:45 ERREUR AutoConsortingb: 175 – Exception lors de la publication du fichier csv: java.lang.ArrayIndexOutOfBoundsException

Pas très utile du tout!

Mon fichier log4j.properties (/tomcat/common/classes/log4j.properties) ressemble à ceci:

 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 

En fait, cela est probablement dû à une optimisation du point chaud: après un certain nombre d’exceptions identiques, il arrête d’imprimer la trace. Cela peut être désactivé avec un argument VM, voir:

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

Le compilateur de la machine virtuelle du serveur fournit désormais des traces de stack correctes pour toutes les exceptions intégrées «à froid». Pour des raisons de performances, lorsqu’une telle exception est émise à plusieurs resockets, la méthode peut être recompilée. Après la recompilation, le compilateur peut choisir une tactique plus rapide en utilisant des exceptions préallouées qui ne fournissent pas de trace de stack. Pour désactiver complètement l’utilisation des exceptions préallouées, utilisez ce nouvel indicateur: -XX: -OmitStackTraceInFastThrow.

Plus ici:

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

Ce que vous avez posté doit afficher la trace de la stack comme indiqué dans le javadoc .

Notez que si vous n’incluez pas de message (et que vous appelez simplement logger.error(ex) ), la trace de la stack n’est pas consignée.

Il existe deux méthodes surchargées pour la méthode d’erreur.

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

si vous utilisez la 1ère méthode, qui imprimera uniquement le nom de l’exception. Si vous utilisez la 2ème méthode, un message avec une exception qui affichera une trace de stack complète similaire à la méthode e.printStackTrace() .

Comme répondu par @Luhar ci-dessus, j’ai lutté avec la même chose et finalement cela a fonctionné pour moi; La bonne chose à propos de cette approche est que nous n’avons pas à bricoler avec les parameters de niveau système tels que JVM, Log4J, car nous ne soaps jamais que cela peut conduire à une nouvelle surprise inattendue!

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

Je n’ai pas utilisé l’appel fillStackTrace, donc je ne peux pas commenter si cela fonctionnera. Une autre approche consiste à utiliser une petite méthode qui renvoie le texte mis en forme à partir d’une exception.

 public static Ssortingng getStackTrace(Exception e) { SsortingngWriter sWriter = new SsortingngWriter(); PrintWriter pWriter = new PrintWriter(sWriter); e.printStackTrace(pWriter); return sWriter.toSsortingng(); } 

Dans votre code de journalisation, vous pouvez écrire:

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

Je ne vois rien de mal avec votre configuration, alors essayez de mettre à jour log4j vers une version plus récente (pas nécessairement la plus récente).

Bien que ce ne soit pas le problème dans ce cas, vous feriez mieux de rendre vos enregistreurs private static final

En utilisant votre exemple de code:

 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()); } 

Vous verrez toute la trace de la stack affichée.

PS Faites de Logger un singleton … (vérifiez ma déclaration) juste après avoir déclaré public class MyClass {

Vous pouvez append ces lignes de code dans votre bloc catch.

 catch (SQLException e) { CharArrayWriter cw = new CharArrayWriter(); PrintWriter w = new PrintWriter(cw); e.printStackTrace(w); w.close(); Ssortingng trace = cw.toSsortingng(); log.error("This is complete stacktrace", trace); }