2010-06-29 27 views
3

我想打印由pages.xml捕獲的異常的堆棧跟蹤,但是我只想在最粒度日誌記錄級別比warn更細化。這樣,測試人員可以複製/粘貼堆棧跟蹤,但最終用戶永遠不會看到它。根據使用Facelets,Seam和Logback的日誌級別在錯誤頁面上有條件地打印堆棧跟蹤

環境細節:

這裏是如何的異常,目前正在處理......

從在pages.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<pages xmlns="http://jboss.com/products/seam/pages" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://jboss.com/products/seam/pages http://jboss.com/products/seam/pages-2.2.xsd"> 

    <!-- ... --> 

    <exception class="javax.faces.application.ViewExpiredException"> 
     <end-conversation /> 
     <redirect view-id="/exceptionSessionTimeout.xhtml" /> 
    </exception> 

    <!-- 
     Prevent the Facelets error page from appearing. 
     This is where I want to conditionally print the stack trace. 
     Currently it's more or less just a generic error page. 
    --> 
    <exception> 
     <end-conversation /> 
     <redirect view-id="/exception.xhtml" /> 
    </exception> 
</pages> 

從web.xml中:

<?xml version="1.0" encoding="UTF-8"?> 
<web-app id="WebApp_ID" version="2.5" 
     xmlns="http://java.sun.com/xml/ns/javaee" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 

    <!-- ... --> 

    <!-- Fallback static HTML page --> 
    <error-page> 
     <exception-type>java.lang.Exception</exception-type> 
     <location>/unhandledException.html</location> 
    </error-page> 
</web-app> 

從logback.xml:

<?xml version="1.0" encoding="UTR-8"?> 
<configuration scan="true"> 
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> 
     <encoder> 
      <pattern>[%date] [%thread] [%level] [%mdc] [%logger:%method:%line]: %msg%n</pattern> 
     </encoder> 
    </appender> 

    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> 
     <file>/path/to/app-logs-dir/AppName.log</file> 
     <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> 
      <fileNamePattern>/path/to/app-logs-dir/AppName.%d{yyyy-MM-dd-a}.gz</fileNamePattern> 
     </rollingPolicy> 
     <encoder> 
      <pattern>[%date] [%thread] [%level] [%mdc] [%logger:%method:%line]: %msg%n</pattern> 
     </encoder> 
    </appender> 

    <logger name="com.example" level="trace" /> 
    <logger name="com.example.auth" level="error" /> 

    <root level="warn"> 
     <appender-ref ref="FILE" /> 
     <appender-ref ref="CONSOLE" /> 
    </root> 
</configuration> 

隨着對這個問題的理想解決方案,這將導致在/error.xhtml(從pages.xml中)要被打印的堆棧跟蹤:

<logger name="com.example" level="trace" /> 

雖然這不會:

<logger name="com.example" level="warn" /> 

ü用Seam唱Facelets,有沒有辦法確定Logback的日誌級別?

回答

2

無縫它可能有一個錯誤處理的servlet:

web.xml

<servlet> 
    <servlet-name>ErrorHandlerServlet</servlet-name> 
    <servlet-class>com.example.ErrorHandlerServlet</servlet-class> 
</servlet> 

<servlet-mapping> 
    <servlet-name>ErrorHandlerServlet</servlet-name> 
    <url-pattern>/ErrorHandlerServlet</url-pattern> 
</servlet-mapping> 

<error-page> 
    <exception-type>java.lang.Exception</exception-type> 
    <location>/ErrorHandlerServlet</location> 
</error-page> 

'ErrorHandlerServlet.java':

import java.io.IOException; 
import java.io.PrintWriter; 

import javax.servlet.RequestDispatcher; 
import javax.servlet.ServletException; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

public class ErrorHandlerServlet extends HttpServlet { 
    private static final long serialVersionUID = 1L; 

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

    @Override 
    protected void doGet(final HttpServletRequest request, 
      final HttpServletResponse response) 
      throws ServletException, IOException { 
     logger.info("handler"); 

     final Object errorMessage = request 
       .getAttribute(RequestDispatcher.ERROR_MESSAGE); 
     final Object throwableObj = request 
       .getAttribute(RequestDispatcher.ERROR_EXCEPTION); 
     logger.warn("error message: {}", errorMessage, throwableObj); 

     final Logger appLogger = LoggerFactory 
       .getLogger("com.example"); 
     if (!appLogger.isInfoEnabled()) { 
      final RequestDispatcher requestDispatcher = 
        request.getRequestDispatcher("/error.html"); 
      requestDispatcher.forward(request, response); 
      return; 
     } 

     final PrintWriter writer = response.getWriter(); 
     writer.println("<pre>"); 

     if (throwableObj != null && throwableObj instanceof Throwable) { 
      final Throwable throwable = (Throwable) throwableObj; 
      throwable.printStackTrace(writer); 
     } 
     writer.println("</pre>"); 
    } 
} 

無論如何,我不認爲這將是一個很好的習慣,很少有人期望改變日誌配置會影響應用程序的行爲。在生產環境中產生這種副作用可能會有問題。 A show-stacktracesweb.xml上下文參數可能是更好的方法。