¿Cómo enviar un stacktrace a log4j?


152

Supongamos que detecta una excepción y obtiene lo siguiente en la salida estándar (como, por ejemplo, la consola) si realiza 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)

Ahora quiero enviar esto a un registrador como, por ejemplo, log4j para obtener lo siguiente:

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)

¿Cómo puedo hacer esto?

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

Respuestas:


262

Pasa la excepción directamente al registrador, p. Ej.

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

Depende de log4j renderizar el seguimiento de la pila.


32
El registrador toma un objeto para su primer argumento y lo toString (). Sin embargo, el segundo argumento tiene que ser Throwable y muestra el seguimiento de la pila.
Peter Lawrey,

1
Nunca sé qué meter en la primera Cadena, generalmente termino haciendo lo log.error(e.getLocalizedMessage(), e)que es totalmente redundante. ¿Maneja un nulo para el primer argumento?
Mark Peters el

55
@Mark: Intenta darle un mensaje que sea más pertinente al contexto que el mensaje de la excepción, por ejemplo, ¿qué estaba tratando de hacer en ese momento?
skaffman

2
@ Mark Peters, un buen ejemplo podría ser registrar los argumentos en el método actual como mensaje o, para una excepción FileNotFound, el nombre completo de la ruta que se intentó abrir. Cualquier cosa que pueda ayudarlo a descubrir qué está mal, simplemente piense que no puede depurar la situación.
Thorbjørn Ravn Andersen

1
@skaffman: En realidad estoy usando log4j-1.2.8.jary quería imprimir todo stackTraceen mi archivo de registro, así que intenté como mencioné anteriormente, pero solo imprimo en mi archivo de registro nullPointerException. Fui utilizado en mi código e.printStackTrace(), imprime todo rastro. ¿Por qué este Kolavery?
Yubaraj

9

Si desea registrar un seguimiento de pila sin involucrar una excepción, simplemente haga esto:

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

3
+1 para System.lineSeparator (), esto me ayudó a imprimir un stacktrace que obtuve como respuesta de un servicio remoto
Stephanie

1
lo que he buscado, pero deberías usar StringBuilder aquí
Xerus

9

También puede obtener el seguimiento de la pila como una cadena a través de ExceptionUtils.getStackTrace.

Ver: ExceptionUtils.java

Lo uso solo para log.debug, para ser log.errorsimple.


4

Solo porque me pasó y puede ser útil. Si haces esto

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

obtendrá el encabezado de la excepción y no todo el seguimiento de la pila. Porque el registrador pensará que estás pasando una cadena. Hazlo sin {}como dijo skaffman


1
Seguramente obtendrá un seguimiento completo de la pila aquí, sin embargo, el {} también se imprimirá textualmente (sin ninguna sustitución).
k1eran

1
no estés tan seguro mi amigo! No me funcionó, solo obtuve el encabezado. Sin embargo, podría depender de la versión de log4j
iberbeu

@iberbeu tiene razón porque Throwable.toString()no devuelve un seguimiento de pila. (Suponiendo que está usando un registrador que sabe qué hacer para con '{}'.)

4

La respuesta de skaffman es definitivamente la respuesta correcta. Todos los métodos logger tales como error(), warn(), info(), debug()toman Throwable como un segundo parámetro:

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

Sin embargo, también puede extraer stacktrace como String. A veces puede ser útil si usted desea tomar ventaja de función usando el formato "{}" marcador de posición - ver método void info(String var1, Object... var2);En este caso, supongamos que tiene un StackTrace como secuencia, a continuación, en realidad se puede hacer algo como esto:

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

Esto imprimirá el mensaje parametrizado y el stacktrace al final de la misma manera que lo hace para el método: logger.error("error: ", e);

De hecho, escribí una biblioteca de código abierto que tiene una Utilidad para la extracción de un stacktrace como String con una opción para filtrar de forma inteligente algo de ruido fuera del stacktrace. Es decir, si especifica el prefijo del paquete que le interesa, su seguimiento de pila extraído se filtraría de algunas partes irrelevantes y le dejaría información muy detallada. Aquí está el enlace al artículo que explica qué utilidades tiene la biblioteca y dónde obtenerla (tanto como artefactos expertos y fuentes git) y cómo usarla también. Biblioteca Java de código abierto con filtrado de seguimiento de pila, análisis de cadena silenciosa, convertidor Unicode y comparación de versiones Consulte el párrafo " Filtro de ruido de seguimiento de pila "


1
Una respuesta enterrada pero agradable.
Payne

Gracias, @payne. Agradezco una buena respuesta
Michael Gantman el

2

Es posible que esta respuesta no esté relacionada con la pregunta formulada, sino con el título de la pregunta.

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

O

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

O

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

1

En Log4j 2, puede usar Logger.catching () para registrar un seguimiento de pila de una excepción que se detectó.

    try {
        String msg = messages[messages.length];
        logger.error("An exception should have been thrown");
    } catch (Exception ex) {
        logger.catching(ex);
    }

0

esto sería bueno log4j error / registro de excepciones - legible por splunk / otro registro / monitoreo s / w. todo es forma de par clave-valor. log4j obtendría el seguimiento de la pila de Exception obje

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

-1

Puede usar el siguiente código:

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


    }

}

Aquí puedes llamar: LogWriterUtility.errorWithAnalysis( YOUR_EXCEPTION_INSTANCE);

Imprimirá stackTrace en su registro.


-2

Crea esto 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);
        }
    };
}
}

Llama a esto en tu código

StdOutErrLog.tieSystemOutAndErrToLog();
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.