2014-06-23 46 views
0

我有一個使用BIT報告的spring mvc webapp。 BIRT報告使用java.util.logging。我正在尋找一種方法將java.util.logging重定向到log4。將java.util.logging重定向到log4j birt

在這個鏈接詳細說明如何做到這一點,但我有一些麻煩得到解決方案的工作。

http://wiki.eclipse.org/BIRT/FAQ/Deployment#Q%3a_Can_I_use_Log4j_with_BIRT.3F

描述我已經添加了類。然後我將logging.properties添加到我的webapp/resources目錄中,其中包含以下內容。

處理器= com.myer.reporting.logging.Log4jHandler

我不認爲該系統參數適用,因爲我使用的web應用程序?

無論如何,我知道它不工作,因爲在我的應用程序日誌目錄中,每當應用程序服務器重新啓動時,我都會得到標準的birt日誌。

enter image description here

有人可以幫我澄清這些指令。

謝謝

回答

2

我不相信這些說明是可以接受的Web應用程序。整個Web服務器/ Servlet容器都有一個JUL。

如果您使用BIRT API生成報告,BIRT允許您設置自己的記錄器。請參閱EngineConfig.setLogger()方法。它至少在BIRT 4.3.1中起作用。我們做如下(重定向BIRT日誌SLF4J,但這個想法應該是Log4J的相同):

EngineConfig config = new EngineConfig(); 
// set logger that forwards log messages to SLF4J 

// as of BIRT 4.3.1 the custom logger will be accepted only if it or one of its parent in the BIRT's root logger list. 
// see http://git.eclipse.org/c/birt/org.eclipse.birt.git/commit/engine/org.eclipse.birt.report.engine/src/org/eclipse/birt/report/engine/api/impl/EngineLogger.java?h=Kepler&id=1cb9507c8ce997bf5407a73d9c23487cef002fa9 
java.util.logging.Logger julLogger = java.util.logging.Logger.getLogger("org.eclipse.birt" + ".myapp.Slf4jBridge"); 
julLogger.setUseParentHandlers(false); 
Handler logHandler = new Slf4jLogHandler(); 
logHandler.setLevel(Level.FINEST); 
julLogger.addHandler(logHandler); 
config.setLogger(julLogger); 

而且Slf4jLogHandler執行如下:

public class Slf4jLogHandler extends Handler { 
private Formatter julFormatter = new SimpleJulFormatter(); 

@Override 
public void publish(LogRecord record) { 
if (record == null) { 
    return; 
} 
ClassLoader hanlderClassLoader = this.getClass().getClassLoader(); 
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); 
if (hanlderClassLoader != contextClassLoader) { 
    // do not log in foreign contexts 
    /* 
    * This check is necessary if several web applications with "JUL to SLF4J" bridge are deployed in the same Servlet container. 
    * Each application has its own instance of SLF4J logger, but they all are mapped to the same JUL logger, 
    * because the JUL logger is loaded by the root classloader. Whereas SLF4J loggers are loaded by their respective 
    * webapp classloaders. Thus comparing classloaders is the only known way to find out whom the JUL log record belongs to. 
    */ 
    return; 
} 
String loggerName = record.getLoggerName(); 
if (loggerName == null) { 
    loggerName = "unknown"; 
} 
Logger slf4jLogger = LoggerFactory.getLogger(loggerName); 
/* 
* JUL levels in descending order are: 
* <ul> 
* <li>SEVERE (highest value) 
* <li>WARNING 
* <li>INFO 
* <li>CONFIG 
* <li>FINE 
* <li>FINER 
* <li>FINEST (lowest value) 
* </ul> 
*/ 
if (record.getLevel().intValue() <= Level.FINEST.intValue()) { 
    if (slf4jLogger.isTraceEnabled()) { 
    slf4jLogger.trace(julFormatter.format(record), record.getThrown()); 
    } 
} else if (record.getLevel().intValue() <= Level.FINE.intValue()) { 
    if (slf4jLogger.isDebugEnabled()) { 
    slf4jLogger.debug(julFormatter.format(record), record.getThrown()); 
    } 
} else if (record.getLevel().intValue() <= Level.INFO.intValue()) { 
    if (slf4jLogger.isInfoEnabled()) { 
    slf4jLogger.info(julFormatter.format(record), record.getThrown()); 
    } 
} else if (record.getLevel().intValue() <= Level.WARNING.intValue()) { 
    if (slf4jLogger.isWarnEnabled()) { 
    slf4jLogger.warn(julFormatter.format(record), record.getThrown()); 
    } 
} else if (record.getLevel().intValue() <= Level.SEVERE.intValue()) { 
    if (slf4jLogger.isErrorEnabled()) { 
    slf4jLogger.error(julFormatter.format(record), record.getThrown()); 
    } 
} else if (record.getLevel().intValue() == Level.OFF.intValue()) { 
    // logger is switched off 
} else { 
    slf4jLogger.warn("Unexpected log level {}.", record.getLevel().intValue()); 
    if (slf4jLogger.isErrorEnabled()) { 
    slf4jLogger.error(julFormatter.format(record), record.getThrown()); 
    } 
} 
} 

@Override 
public void flush() { 
// noop 
} 

@Override 
public void close() throws SecurityException { 
// noop 
} 
} 

這種方法適用即使有幾個Web應用程序在同一臺服務器上使用BIRT。

+2

你自己寫了'Slf4jLogHandler'而不是使用SLF4J'org.slf4j.bridge.SLF4JBridgeHandler'的原因是什麼?是否按照代碼註釋或其他內容在外部環境中進行登錄? – Barney

0

我使用ServletContextListener,它將SLF4JBridgeHandler安裝爲j.u.l的唯一處理程序。 logger:

public class InstallJULHandlerListener implements ServletContextListener { 
    @Override 
    public void contextInitialized(ServletContextEvent arg0) { 
     // Optionally remove existing handlers attached to j.u.l root logger 
     SLF4JBridgeHandler.removeHandlersForRootLogger(); // (since SLF4J 1.6.5) 

     // add SLF4JBridgeHandler to j.u.l's root logger, should be done once 
     // during the initialization phase of your application 
     SLF4JBridgeHandler.install(); 
    } 

    @Override 
    public void contextDestroyed(ServletContextEvent arg0) { 

    } 
}