web-dev-qa-db-fra.com

Comment envoyer un stacktrace à log4j?

Supposons que vous attrapiez une exception et que vous obteniez ce qui suit sur la sortie standard (par exemple, la console) si vous faites un e.printStackTrace () :

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 plutôt envoyer ceci à 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 puis-je faire ceci?

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

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

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

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

239
skaffman

Si vous souhaitez consigner un stacktrace sans impliquer une exception, procédez comme suit: 

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);
7
borjab

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

Voir: ExceptionUtils.Java

Je ne l'utilise que pour log.debug, pour garder log.error simple.

7
ktsujister

Cette réponse peut ne pas être liée à la question posée mais au titre de 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());
    }
}

OR

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

OR

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

Juste parce que cela m'est arrivé et que cela 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 de la pile. Parce que l'enregistreur pensera que vous passez une chaîne . Faites-le sans {} comme l'a dit skaffman

2
iberbeu

La réponse de skaffman est certainement la bonne réponse. Toutes les méthodes de journalisation telles que error(), warn(), info(), debug() prennent Throwable en tant que deuxième paramètre:

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

Cependant, vous pouvez également extraire stacktrace sous forme de chaîne. Parfois, il peut être utile de tirer parti de la fonctionnalité de formatage en utilisant un espace réservé "{}" - voir la méthode void info(String var1, Object... var2);. Dans ce cas, spécifiez que vous avez un stacktrace sous forme de chaîne.

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

Ceci imprimera le message paramétré et le stacktrace à la fin de la même manière que pour la méthode: logger.error("error: ", e);

En fait, j'ai écrit une bibliothèque open source dotée d'un utilitaire permettant d'extraire un stacktrace sous forme de chaîne avec une option permettant de filtrer intelligemment du bruit hors de stacktrace. C'est à dire. si vous spécifiez le préfixe de paquet qui vous intéresse dans votre pile extraite, il serait filtré de certaines parties non pertinentes et vous laisserait des informations très sérieuses. Voici le lien vers l'article qui explique quels utilitaires ont la bibliothèque et où l'obtenir (à la fois sous forme d'artefacts maven et de sources git) et comment l'utiliser également. Bibliothèque Java Open Source avec filtrage de trace de pile, conversion silencieuse de chaînes de caractères Unicode et comparaison de versions Voir le paragraphe "Filtre de bruit de pile"

2
Michael Gantman
Try this:

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

Vous pouvez utiliser le code ci-dessous:

import org.Apache.logging.log4j.Logger;
import org.Apache.logging.log4j.LogManager;

public class LogWriterUtility {
    Logger log;

    public LogWriterUtility(Class<?> clazz) {
        log = LogManager.getLogger(clazz);
    }

public void errorWithAnalysis( Exception exception) {

        String message="No Message on error";
        StackTraceElement[] stackTrace = exception.getStackTrace();
        if(stackTrace!=null && stackTrace.length>0) {
            message="";
            for (StackTraceElement e : stackTrace) {
                message += "\n" + e.toString();
            }
        }
        log.error(message);


    }

}

Ici, vous pouvez simplement appeler: LogWriterUtility.errorWithAnalysis( YOUR_EXCEPTION_INSTANCE);

Il imprimera stackTrace dans votre journal.

0
Md. Sajedul Karim

log4j journalisation des erreurs/exceptions - lisible par splunk/autre journalisation/surveillance s/w. tout est la forme d'une 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
src3369