开发者

Log4j: Configuring FallbackErrorHandler with Properties

I use log4j in my project and wanted to use FallbackErrorHandler for Backup-Reasons. So, when I want to implement a FallbackErrorHandler, you have to use the DOMConfigurator and that for a XML-Configurationfile.

But now, my customer doesn´t really like XML and looking for a way, he can configure the Logging-behaviour himself, I got the idea to load the basic configuration with the help of java-properties und instantiating the higher Appender or ErrorHandler with Java-Code, which I could configure with parameters.

The configuration of the ErrorHandler worked so far, the log4j-debug showing everythings correct, but I ran into a problem I could not solve until yet. My FallbackErrorHandler starts logging to the backupAppender already at the start of the programm, not when a standard append开发者_C百科er failed. I couldn´t figure out what I´ve done wrong, I can post the code of the properties and the java-code if somebody wants to look at it, but at first, I wanted to ask, whether somebody ran into the same problem or has any experiences with configuring log4j within Java?


After weeks of trying I now finally found a solution. The key event was the discovery, that also the PropertyConfigurator has a class for ErrorHandler, although Geki wrote, that there is no possibility to configure a ErrorHandler with the PropertyConfigurator. So I went on trying.

Now I could simply combine the basic declaration in the log4j.properties with the linking of Logger, Appender and ErrorHandler in JavaCode. So following stands in my Properties:

log4j.appender.ServerAppender=org.apache.log4j.FileAppender
log4j.appender.ServerAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.ServerAppender.layout.ConversionPattern=%d{dd MMM yyyy HH:mm:ss,SSS} [%t] %-5p %F - %m%n 
log4j.appender.ServerAppender.file=logs/ServerLog.txt
log4j.appender.ServerAppender.threshold=DEBUG

log4j.logger.com.foo.server=TRACE, ServerAppender

log4j.appender.ServerAppender.errorhandler=org.apache.log4j.varia.FallbackErrorHandler
log4j.appender.ServerAppender.errorhandler.logger-ref=com.foo.server
log4j.appender.ServerAppender.errorhandler.appender-ref=FallbackServerAppender

log4j.appender.FallbackServerAppender=org.apache.log4j.FileAppender
log4j.appender.FallbackServerAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.FallbackServerAppender.layout.ConversionPattern=%d{dd MMM yyyy HH:mm:ss,SSS} [%t] %-5p %F - %m%n 
log4j.appender.FallbackServerAppender.file=C:/Temp/Test/fallbackServerLog.txt

log4j.logger.com.foo.error=DEBUG,FallbackServerAppender

While com.foo.server is a part of my package hierarchy, com.foo.error is only a placeholder, so I can call it within Java-Code. That will look like this.

PropertyConfigurator.configure(LOG4JCONFIG);
FallbackErrorHandler fbeh=(FallbackErrorHandler)LogManager.getLogger("com.foo.server").getAppender("ServerAppender").getErrorHandler();
fbeh.setLogger(LogManager.getLogger("com.foo.server"));
fbeh.setAppender(LogManager.getLogger("com.foo.server").getAppender("ServerAppender"));         
fbeh.setBackupAppender(LogManager.getLogger("com.foo.error").getAppender("FallbackServerAppender"));

A known problem, the fallbackErrorHandler doesn´t reset when the Appender is on again, could be solved by restarting the configure()-method in or after situations, where normally the normal Appender can´t log.

Hope it could help somebody :)


You can think of using log4j2 which provide full control over Failover. It is quite easy as it has been written on top of log4j.

If using Spring framework then only need to add starter:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>

In case already another logger used like logback then exclude from dependencies like from: spring-boot-starter-jdbc

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
        </exclusions>           
    </dependency>

You can use below log4j2.xml file for setting failover. It first try to send log to HTTP appender, if fails it redirect log to file appender. Once, primary appender is back, it start sending to primary appender which is HTTP appender here.

   <?xml version="1.0" encoding="UTF-8"?>
   <Configuration status="INFO" type="">
<Properties>
    <Property name="LOG_PATH">${sys:user.home}</Property>
    <Property name="LOG_PATTERN">[$$${ctx:moduleName}][$$${ctx:userName}][$$${ctx:tenantDomainName}][$$${ctx:sessionId}][$$${ctx:requestId}][$$${ctx:operationName}][%d{yyyy-MM-dd HH:mm:ss}][%t][%-5p][%c{1}:%L] - %msg%n</Property>
    <Property name="moduleName">XModule</Property>
    <Property name="LOG_FILE">XModule.log</Property>
    <Property name="userName">SYSTEM</Property>
    <Property name="tenantDomainName">STG</Property>
    <Property name="sessionId">EMPTY</Property>
    <Property name="requestId">EMPTY</Property>
    <Property name="operationName">EMPTY</Property>
    <Property name="HTTP_HOST">http_appender_host</Property>
    <Property name="HTTP_PORT">Port</Property>
    <Property name="HTTP_CTM">5000</Property>
    <Property name="HTTP_RTM">5000</Property>
</Properties>

<Appenders>

    <Http name="Http" url="http://${sys:HTTP_HOST}:${sys:HTTP_PORT}/" connectTimeoutMillis="${sys:HTTP_CTM}" readTimeoutMillis="${sys:HTTP_RTM}" ignoreExceptions="false">
        <PatternLayout pattern="${sys:LOG_PATTERN}" />
    </Http>
    
    <Console name="Console" target="SYSTEM_OUT" ignoreExceptions="false">
        <PatternLayout pattern="${sys:LOG_PATTERN}" />
    </Console>

    <RollingFile name="RollingFile" filename="${sys:LOG_PATH}/${sys:LOG_FILE}"
        filepattern="${sys:LOG_PATH}/${sys:LOG_FILE}-%i" ignoreExceptions="true">
        <PatternLayout pattern="${sys:LOG_PATTERN}" />
        <Policies>                 
                 <SizeBasedTriggeringPolicy size="${sys:LOG_FILE_MAX_SIZE:-20MB}" />
         </Policies>
         <DefaultRolloverStrategy max="${sys:LOG_FILE_MAX_HISTORY:-20}" />
    </RollingFile>
    
    <Failover name="Failover" primary="Http">
      <Failovers>
        <AppenderRef ref="RollingFile"/>
      </Failovers>
    </Failover>     
    
</Appenders>

<Loggers>
    <Root level="info">
        <AppenderRef ref="Failover"/>
    </Root>
</Loggers>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜