2010-02-19 23 views
54

Estoy usando log4j con tomcat. Cuando registro excepciones en mis JSP, servlets:log4j no imprime el stacktrace para las excepciones

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

solo me dan la primera línea de la excepción, sin StackTrace.

17-Feb 17:37:45 ERROR AutoContrib: 175 - Excepción al publicar el archivo csv: java.lang.ArrayIndexOutOfBoundsException

No

muy útil en absoluto!

Mi archivo log4j.properties (/tomcat/common/classes/log4j.properties) tiene el siguiente aspecto:

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 
+0

Por lo que puedo ver, lo está haciendo todo como debería ser ... debería ver toda la stacktrace en su registro. ¿Qué versión de log4j, Java y Tomcat estás usando? –

+0

Estamos usando tomcat 5.5.17 y log4j-1.2.14 (creo que actualizaremos a tc6 en el futuro cercano, pero no estoy seguro de que eso haga la diferencia) – Ryan

Respuesta

58

En realidad, es probable que se deba a una optimización de punto de acceso: después de arrojar un cierto número de la misma excepción, se detiene la impresión de la traza. Esto se puede desactivar con una arg VM, consulte:

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

El compilador en el servidor de VM proporciona ahora trazas de pila correctos para todos "en frío" excepciones incorporadas. Por motivos de rendimiento, cuando se lanza una excepción de este tipo al , el método puede volver a compilarse. Después de la recompilación, el compilador puede elegir una táctica más rápida usando excepciones preasignadas que no proporcionan un seguimiento de pila. Para desactivar completamente el el uso de excepciones preasignadas, use este nuevo indicador: -XX: -OmitStackTraceInFastThrow.

Más aquí:

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

0

Usando su ejemplo de código:

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

puedes encontrar la rastro de pila mostrado.

PS. Hacer Logger un singleton ... (verifique mi declaración) justo después de declarar public class MyClass {

+0

¡Gracias por el consejo! Voy a intentar esto ahora. BTW, para el enfoque singleton no puede usar 'esto' con el getLoggger estático(). Creo que puedo usar getLogger (MyClass.class) – Ryan

+0

True Ryan !. Hace que la creación de instancias sea más rápida ya que el singleton ya existe después de la creación. –

+0

idealmente, no debería necesitar este – Bozho

0

No veo nada de malo en su configuración, por lo que intente actualizar log4j a una versión más nueva (no necesariamente la última).

Aunque no es el problema en este caso, es mejor que haga sus registradores private static final

1

no he usado la llamada fillStackTrace, así que no puedo comentar si eso va a trabajar. Otro enfoque es usar un pequeño método que devuelve el texto formateado desde una excepción.

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

En su código de registro, se podría escribir:

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

idealmente, no debería necesitar este – Bozho

15

Lo que han publicado debe mostrar el seguimiento de la pila como se indica en la javadoc.

Tenga en cuenta que si no incluye un mensaje (y simplemente llame al logger.error(ex)), entonces no se registra el seguimiento de la pila.

+3

Ah. Ahí está. Esto es lo que me estaba mordiendo. El registro de un error no imprime el seguimiento de la pila. Debe registrar un mensaje con el error para obtenerlo. – rbwhitaker

+0

Esto fue útil. Gracias. ¿Podemos configurar log4j para que muestre una traza completa incluso si solo proporcionamos el objeto de excepción? –

3

Como respondida por @Luhar anterior, luché con lo mismo y, finalmente, esto funcionó para mí; Lo bueno de este enfoque es que no tenemos que manipular ajustes de nivel de sistema como JVM, Log4J, ya que nunca se sabe que puede conducir a una nueva sorpresa inesperada.

try { 

... 
.. 

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

Puede agregar estas líneas de código en su bloque 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); 
} 
6

Existen dos métodos sobrecargados para el método de error.

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

si utiliza primero método, que sólo se imprimirá el nombre de la excepción. si utiliza el segundo método, aparecerá un mensaje junto con una excepción que imprimirá un seguimiento completo de la pila similar al método e.printStackTrace().

+0

Gracias. Creo que esta es la respuesta correcta. –

Cuestiones relacionadas