2010-12-03 4 views
130

Dites que vous attrapez une exception et obtenir ce qui suit sur la sortie standard (comme, par exemple, la console) si vous faites un e.printStackTrace():Comment envoyer un stacktrace à log4j?

java.io.FileNotFoundException: so.txt 
     at java.io.FileInputStream.<init>(FileInputStream.java) 
     at ExTest.readMyFile(ExTest.java:19) 
     at ExTest.main(ExTest.java:7) 

Maintenant, je veux envoyer ce lieu à un enregistreur comme, par exemple, log4j pour obtenir ce qui suit:

31947 [AWT-EventQueue-0] ERROR Java.io.FileNotFoundException: so.txt 
32204 [AWT-EventQueue-0] ERROR at java.io.FileInputStream.<init>(FileInputStream.java) 
32235 [AWT-EventQueue-0] ERROR at ExTest.readMyFile(ExTest.java:19) 
32370 [AWT-EventQueue-0] ERROR at ExTest.main(ExTest.java:7) 

Comment est-ce que je peux faire ceci?

try { 
    ... 
} catch (Exception e) { 
    final String s; 
    ... // <-- What goes here? 
    log.error(s); 
} 

Répondre

218

Vous transmettez l'exception directement à l'enregistreur, par ex.

try { 
    ... 
} catch (Exception e) { 
    log.error("failed!", e); 
} 

C'est à log4j de rendre la trace de la pile.

+24

L'enregistreur prend un objet pour son premier argument et de la volonté toString() il. Cependant, le second argument doit être Throwable et affiche la trace de la pile. –

+1

Je ne sais jamais quoi mettre dans la première chaîne, d'habitude je finis par faire 'log.error (e.getLocalizedMessage(), e)' qui est totalement redondant. Est-ce qu'il gère un null pour le premier argument? –

+4

@Mark: Essayez de lui donner un message qui est plus pertinent au contexte que le message de l'exception, par ex. qu'essayait-il réellement de faire à ce moment-là? – skaffman

6

Vous pouvez également obtenir une trace de pile sous forme de chaîne via ExceptionUtils.getStackTrace.

Voir: ExceptionUtils.java

Je l'utilise seulement pour log.debug, de garder log.error simple.

+0

Vieux mais l'or. Merci – kosgeinsky

-2

Créer cette class:

public class StdOutErrLog { 

private static final Logger logger = Logger.getLogger(StdOutErrLog.class); 

public static void tieSystemOutAndErrToLog() { 
    System.setOut(createLoggingProxy(System.out)); 
    System.setErr(createLoggingProxy(System.err)); 
} 

public static PrintStream createLoggingProxy(final PrintStream realPrintStream) { 
    return new PrintStream(realPrintStream) { 
     public void print(final String string) { 
      logger.info(string); 
     } 
     public void println(final String string) { 
      logger.info(string); 
     } 
    }; 
} 
} 

Appelez ce dans votre code

StdOutErrLog.tieSystemOutAndErrToLog(); 
2

Cette réponse peut être pas liée à la question posée mais à titre de lié à la question.

public class ThrowableTest { 

    public static void main(String[] args) { 

     Throwable createdBy = new Throwable("Created at main()"); 
     ByteArrayOutputStream os = new ByteArrayOutputStream(); 
     PrintWriter pw = new PrintWriter(os); 
     createdBy.printStackTrace(pw); 
     try { 
      pw.close(); 
      os.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     logger.debug(os.toString()); 
    } 
} 

OU

public static String getStackTrace (Throwable t) 
{ 
    StringWriter stringWriter = new StringWriter(); 
    PrintWriter printWriter = new PrintWriter(stringWriter); 
    t.printStackTrace(printWriter); 
    printWriter.close(); //surprise no IO exception here 
    try { 
     stringWriter.close(); 
    } 
    catch (IOException e) { 
    } 
    return stringWriter.toString(); 
} 

OU

StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); 
for(StackTraceElement stackTrace: stackTraceElements){ 
    logger.debug(stackTrace.getClassName()+ " "+ stackTrace.getMethodName()+" "+stackTrace.getLineNumber()); 
} 
1

Juste parce qu'il est arrivé à moi et peut être utile. Si vous faites cela

try { 
    ... 
} catch (Exception e) { 
    log.error("failed! {}", e); 
} 

vous obtiendrez l'en-tête de l'exception et non l'ensemble stacktrace. Parce que l'enregistreur pensera que vous passez une chaîne. faire sans {} comme skaffman dit

+1

Sûrement vous obtiendrez toute la trace de la pile ici, mais le {} sera imprimé verbatim aussi (sans aucune substitution)? – k1eran

+0

ne soyez pas si sûr mon ami! Cela n'a pas fonctionné pour moi, j'ai seulement l'en-tête. Cela pourrait dépendre de la version de log4j bien que – iberbeu

7

Si vous voulez connecter un stacktrace sans faire intervenir une exception faire juste ceci:

String message = ""; 

for(StackTraceElement stackTraceElement : Thread.currentThread().getStackTrace()) {       
    message = message + System.lineSeparator() + stackTraceElement.toString(); 
} 
log.warn("Something weird happened. I will print the the complete stacktrace even if we have no exception just to help you find the cause" + message); 
+2

+1 pour System.lineSeparator(), cela m'a aidé à imprimer une pile de paquets que j'ai reçu en réponse d'un service distant – Stephanie

+0

ce que j'ai cherché, mais vous devriez utiliser StringBuilder ici – Xerus

+0

Exactement ce que je cherchais – tcardoso

0

La réponse de skaffman est certainement la bonne réponse. Toutes les méthodes de l'enregistreur tels que error(), warn(), info(), debug() prennent Throwable comme second paramètre:

try { 
... 
} catch (Exception e) { 
logger.error("error: ", e); 
} 

Cependant, vous pouvez extraire stacktrace en tant que chaîne aussi bien.Parfois, il pourrait être utile si vous souhaitez profiter de mise en forme caractéristique « {} » espace réservé - voir la méthode void info(String var1, Object... var2); Dans ce cas, que vous avez un stacktrace comme String, alors vous pouvez réellement faire quelque chose comme ceci:

try { 
... 
} catch (Exception e) { 
String stacktrace = TextUtils.getStacktrace(e); 
logger.error("error occurred for usename {} and group {}, details: {}",username, group, stacktrace); 
} 

Cela affichera un message paramétrisé et le stacktrace à la fin de la même façon il le fait pour la méthode: logger.error("error: ", e);

j'ai écrit une bibliothèque open source qui a une utilité pour l'extraction d'un stacktrace comme une chaîne avec une option pour filtrer intelligemment sortir un peu de bruit hors de la pile. C'est à dire. Si vous spécifiez le préfixe du paquet qui vous intéresse, votre piletrace extraite sera filtrée hors de certaines parties non pertinentes et vous laissera des informations très détaillées. Voici le lien vers l'article qui explique quels utilitaires la bibliothèque a et où l'obtenir (à la fois comme artefacts maven et sources git) et comment l'utiliser aussi bien. Open Source Java library with stack trace filtering, Silent String parsing Unicode converter and Version comparison Voir le paragraphe "Stacktrace filtre de bruit"

0

ce serait bon de journalisation des erreurs log4j/exception - lisibles par splunk/autre enregistrement/surveillance s/p. tout est forme de paire clé-valeur. log4j obtiendrait la trace de pile de Exception obj e

try { 
      --- 
      --- 
    } catch (Exception e) { 
     log.error("api_name={} method={} _message=\"error description.\" msg={}", 
        new Object[]{"api_name", "method_name", e.getMessage(), e}); 
    } 
0
Try this: 

catch (Throwable t) { 
    logger.error("any message" + t); 
    StackTraceElement[] s = t.getStackTrace(); 
    for(StackTraceElement e : s){ 
     logger.error("\tat " + e); 
    } 
}