web-dev-qa-db-fra.com

log4j n'imprime pas la trace de pile pour les exceptions

J'utilise log4j avec Tomcat. Lorsque je consigne 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 reçois uniquement la première ligne de l'exception, sans trace de pile.

17-fév 17:37:45 ERREUR AutoContrib: 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
66
Ryan

En fait, c'est probablement dû à une optimisation de hotspot: après qu'un certain nombre de la même exception soit levée, il cesse 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 du serveur VM fournit désormais des traces de pile correctes pour toutes les exceptions intégrées "à froid". À des fins de performances, lorsqu'une telle exception est levée plusieurs fois, 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 pile. 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/

76
minimo

Ce que vous avez publié doit afficher la trace de la pile comme indiqué dans javadoc .

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

21
objects

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

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

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

15
Venkatesh Boya

Comme répondu par @Luhar ci-dessus, j'ai eu du mal avec la même chose et finalement cela a fonctionné pour moi; Une bonne chose à propos de cette approche est que nous n'avons pas à bricoler avec des paramètres de niveau système comme JVM, Log4J car nous ne savons 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 String(os.toByteArray()));
        //LOGGER.error(er);
}
6
Rockoder

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 faire vos enregistreurs private static final

1
Bozho

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 formaté à partir d'une exception.

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

Dans votre code de journalisation, vous pouvez écrire:

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

Vous pouvez ajouter 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();
            String trace = cw.toString();

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