将Log4j重定向到特定文件

时间:2014-07-17 14:51:45

标签: java logging log4j slf4j

在读取和解析多个文件的批处理应用程序中,规范要求我分别输出每个文件的日志。

我该怎么做?

示例:

for(File f : allFiles) {
     //TODO after this line all log should be output to "<f.getName()>.log"

     LOGGER.debug('Start processing '+f.getName());

     // process the file by calling librairies (JPA, spring, whatever ...)

     LOGGER.debug('End processing '+f.getName());
}

所以,如果我要处理3个文件,最后我想要3个日志文件。

到目前为止我所做的是以下课程。

import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;

public final class LoggerHelper {

    /**
     * Functional logger
     */
    private static final Logger LOGGER = Logger.getLogger("BATCH_LOGGER");

    /**
     * Pattern for the layout of the logger
     */
    private static final String PATTERN_LAYOUT = "%d{yyyy-MM-dd [HH:mm:ss]} %m%n";

    /**
     * Constructor
     */
    private LoggerHelper() {
    }

    /**
     * Initialize the loggers
     * 
     * @param filename
     *            the name of the file where the logs will be written
     * @throws IOException
     *             if a problem occur when instantiate a file appender
     */
    public static void initLoggers(String filename) throws IOException {
        // change functional appender
        LOGGER.removeAllAppenders();
        LOGGER.addAppender(new FileAppender(new PatternLayout(PATTERN_LAYOUT), filename));
        LOGGER.setLevel(Level.DEBUG);
    }

    /**
     * Get the batch logger
     * 
     * @return the batch Logger
     */
    public static Logger getLogger() {
        return LOGGER;
    }
}

但我必须用LoggerHelper.getLogger().debug(...)替换所有LOGGER调用。 使用此解决方案,我无法记录框架日志。

for(File f : allFiles) {
     //TODO after this line all log should be output to "<f.getName()>.log"
     LoggerHelper.initLoggers(f.getName());

     LoggerHelper.getLogger().debug('Start processing '+f.getName());

     // process the file by calling librairies (JPA, spring, whatever ...)

     LoggerHelper.getLogger().debug('End processing '+f.getName());
}

我该怎么做?

2 个答案:

答案 0 :(得分:1)

你已经走上了良好的轨道。我想你的错误是创造新的记录器。解决方案可能是向同一记录器添加不同的appender。因此,您的记录器助手只需要替换appender(就像您在代码中所做的那样):

private static final class LoggerHelper {

    private static final String PATTERN_LAYOUT = "%d{yyyy-MM-dd [HH:mm:ss]} %m%n";

    private static final Layout LAYOUT = new PatternLayout(PATTERN_LAYOUT);

    public static final void setFileOutputOfLogger(Logger log, String fileName) throws IOException {
        log.removeAllAppenders();
        log.addAppender(new FileAppender(LAYOUT, fileName));
    }
}

这是你可以在循环中调用的东西。

Logger log = Logger.getLogger(FileStuff.class);

for(File f : allFiles) {
     LoggerHelper.setFileOutputOfLogger(log, f.getName());

不会触及所有框架输出。

答案 1 :(得分:1)

这是我最终实施的解决方案。 我在这里分享,如果这可以帮助别人......

首先,重新加载log4j配置的帮助程序类 请注意,它(重新)设置了一些系统属性。这些属性将直接用在log4j文件中。

import org.apache.log4j.xml.DOMConfigurator;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

public final class LogHelper {

    private final static String LOG4J_XML_FILENAME = "log4j.xml";
    private final static String LOG_APPLI_DIRECTORY = "LOG_APPLI_DIRECTORY";
    private final static String FILENAME = "FILENAME";

    public static void initLogsForCurrentFile(String currentFile, String logDir) {
        Assert.hasLength(currentFile);
        Assert.doesNotContain(currentFile, File.pathSeparator);

        ClassPathResource log4jxml = new ClassPathResource(LOG4J_XML_FILENAME);
        if (!log4jxml.exists()) {
            throw new IllegalArgumentException(
                    "The [log4j.xml] configuration file has not been found on the classpath.");
        }

        // TODO Define variables that could be used inside the log4j
        // configuration file
        System.setProperty(FILENAME, FileUtils.removeExtension(currentFile));
        System.setProperty(LOG_APPLI_DIRECTORY, logDir);

        // Reload the log4j configuration
        try {
            DOMConfigurator.configure(log4jxml.getURL());
        } catch (Exception e) {
            throw new IllegalArgumentException(
                    "A problem occured while loading the log4j configuration.",
                    e);
        }
    }
}

和相应的log4j文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

    <!-- This log4j file will be reloaded multiple times -->
    <!-- so that each files processed by the applicatin will have their own log file -->
    <!-- ${LOG_APPLI_DIRECTORY} = the log directory -->
    <!-- ${FILENAME} = the basename of the current file processed by the batch -->

    <appender name="batch-appender" class="org.apache.log4j.RollingFileAppender">
        <param name="file"
            value="${LOG_APPLI_DIRECTORY}/batch-${FILENAME}.log" />
        <param name="MaxFileSize" value="1MB" />
        <param name="MaxBackupIndex" value="3" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d{ISO8601} %-5p  %-40.40c{1} - %m%n" />
        </layout>
    </appender>

    <!-- ================ -->
    <!-- Root logger -->
    <!-- ================ -->
    <root>
        <priority value="info" />
        <appender-ref ref="batch-appender" />
    </root>
</log4j:configuration>

使用这样的解决方案,我们尽可能地保持我们通常用来配置log4j的程度。 此外,此解决方案将配置保留在log4j文件中,而不在java源代码中进行配置。