Log4j2动态日志未在运行时创建

时间:2018-09-14 10:47:23

标签: java logging log4j2

log4j2.xml文件是在运行时通过Java程序动态创建的。

<?xml version="1.0" encoding="UTF-8"?>
    <Configuration status="error">
        <Appenders>
            <RollingRandomAccessFile
                name="Application" immediateFlush="false"
                fileName="logs/FixGatewayLogs/Application.log"
                append="true"
                filePattern="logs/FixGatewayLogs/Application-%d{dd-MM-yyyy}-%i.log.gz">
                <PatternLayout>
                    <Pattern>%d %-5p [%t] (%F:%L) - %m%n</Pattern>
                </PatternLayout>
                <Policies>
                    <SizeBasedTriggeringPolicy size="100 MB" />
                </Policies>
                <DefaultRolloverStrategy fileIndex="max"
                    max="20" />
            </RollingRandomAccessFile>
            <RollingRandomAccessFile name="FirstUser"
                immediateFlush="false"
                fileName="logs/FixAcceptorLogs/FirstUser.log"
                append="true"
                filePattern="logs/FixAcceptorLogs/FirstUser-%d{dd-MM-yyyy}-%i.log.gz">
                <PatternLayout>
                    <Pattern>%d %F - %m%n</Pattern>
                </PatternLayout>
                <Policies>
                    <SizeBasedTriggeringPolicy size="100 MB" />
                </Policies>
                <DefaultRolloverStrategy fileIndex="max"
                    max="20" />
            </RollingRandomAccessFile>
            <RollingRandomAccessFile name="SecondUser"
                immediateFlush="false"
                fileName="logs/FixAcceptorLogs/SecondUser.log"
                append="true"
                filePattern="logs/FixAcceptorLogs/SecondUser-%d{dd-MM-yyyy}-%i.log.gz">
                <PatternLayout>
                    <Pattern>%d %F - %m%n</Pattern>
                </PatternLayout>
                <Policies>
                    <SizeBasedTriggeringPolicy size="100 MB" />
                </Policies>
                <DefaultRolloverStrategy fileIndex="max"
                    max="20" />
            </RollingRandomAccessFile>
        </Appenders>
        <Loggers>
            <AsyncLogger name="Application" level="debug"
                includeLocation="false" additivity="false">
                <AppenderRef ref="Application" />
            </AsyncLogger>
            <AsyncLogger name="FirstUser" level="debug"
                includeLocation="false" additivity="false">
                <AppenderRef ref="FirstUser" />
            </AsyncLogger>
            <AsyncLogger name="SecondUser" level="debug"
                includeLocation="false" additivity="false">
                <AppenderRef ref="SecondUser" />
            </AsyncLogger>
        </Loggers>
    </Configuration>

主班

public class CreateLog4jApplication {

        static GenerateLog4j generateLog4j = new GenerateLog4j();

        public static void main(String[] args) {
            try {
                createLog4jFile();
                //System.setProperty("log4j.configurationFile","./src/main/resources/log4j2.xml");
            }
            catch(Exception e){
                System.out.println("CreateLog4jApplication Main Exception : " + e);
            }
         }

        public static void createLog4jFile() {
            try{
                // Create instance of OPTopicListener
                System.out.println("run() of CreateLog4jApplication");

                List<String> initiatorList = new ArrayList<String>();
                initiatorList.add("First");

                generateLog4j.generateLog4j2XMLFile(initiatorList);

                //((org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(true)).reconfigure();

                Logger logger = LoggerFactory.getLogger("First");

                logger.info("Enter First File");

                System.out.println("After Logger add First file");

                Thread.sleep(5000);

                initiatorList.add("Second");

                generateLog4j.generateLog4j2XMLFile(initiatorList);

                //((org.apache.logging.log4j.core.LoggerContext) LogManager.getContext(true)).reconfigure();

                Logger logger1 = LoggerFactory.getLogger("Second");

                logger1.info("Enter Second File");

                System.out.println("After Logger add Second file");

                // This prevents program exit
                CountDownLatch  shutdownLatch = new CountDownLatch(1);
                shutdownLatch.await();
            }
            catch(Exception e){
                System.out.println("run() of CreateLog4jApplication Exception : " + e);
            }       
        }

    }

GenerateLog4j类

public class GenerateLog4j {
public void generateLog4j2XMLFile(List<String> initiatorList) {
    try {
        System.out.println("InitiatorList : " + initiatorList + " " + initiatorList.size());

        File       fileForDelete    = new File("src/main/resources/log4j2.xml");
        fileForDelete.delete();

        File       fileForWrite     = new File("src/main/resources/log4j2.xml");
        FileWriter fileWriterObject = new FileWriter(fileForWrite, true);


        fileWriterObject.write("<?xml version=" + "\"1.0\"" + " " + "encoding=" + "\"UTF-8\"" + "?>" + System.getProperty("line.separator"));
        fileWriterObject.write("<Configuration status="+ "\""+ "error" +"\"" +">" + System.getProperty("line.separator"));
        fileWriterObject.write("<Appenders>" + System.getProperty("line.separator"));

        fileWriterObject.close();

        String beginString       = "FIX.4.4";
        String tradesAcceptorID  = "FIX_44_ACCEPTOR_TR";


        // Iterate through the List and create entry for each Appender in XML file 
        for(int fileIndex = 0; fileIndex < (initiatorList.size() + 1); fileIndex++) {
            String appName     = null;
            String filePath    = null;
            String filePattern = null;
            String pattern     = null;
            String logLevel    = null;

            if(fileIndex == 0) { // FixGateway.log
                appName  = "OrderProcessorApplication";
                filePath = "logs/FixGatewayLogs/" + appName + ".log";
                filePattern = "logs/FixGatewayLogs/" + appName +"-%d{dd-MM-yyyy}-%i.log.gz";
                pattern  = "%d %-5p [%t] (%F:%L) - %m%n";
                logLevel = "trace";

                writeAppenderToLog4j2XMLFile(appName, filePath, filePattern, pattern, logLevel);
            }
            else { //Initiator
                // Create entry for Trades Session in XML file
                //appName = initiatorList.get(fileIndex - 1) + "_TR";
                appName = initiatorList.get(fileIndex-1);
                //filePath = "logs/FixAcceptorLogs/" + beginString + "-" + tradesAcceptorID + "-" + appName + ".log";
                filePath = "logs/FixAcceptorLogs/" + appName + ".log";
                filePattern = "logs/FixAcceptorLogs/" + appName +"-%d{dd-MM-yyyy}-%i.log.gz";
                pattern  = "%d %F - %m%n";
                logLevel = "trace";

                writeAppenderToLog4j2XMLFile(appName, filePath, filePattern, pattern, logLevel);
            }
        }


        File       fileForWriteOne     = new File("src/main/resources/log4j2.xml");
        FileWriter fileWriterObjectOne = new FileWriter(fileForWriteOne, true);

        fileWriterObjectOne.write("</Appenders>" + System.getProperty("line.separator"));
        fileWriterObjectOne.write("<Loggers>" + System.getProperty("line.separator"));

        fileWriterObjectOne.close();


        // Iterate through the List and create entry for each Logger in XML file
        for(int fileIndex = 0; fileIndex < (initiatorList.size() + 1); fileIndex++) {
            String appName  = null;
            String logLevel = null;

            if(fileIndex == 0) { // OrderProcessorApplication.log
                appName  = "OrderProcessorApplication";
                logLevel = "trace";

                writeLoggerToLog4j2XMLFile(appName, logLevel);
            }
            else { // Initiator
                // Create entry for Trades Session in XML file
                appName = initiatorList.get(fileIndex-1);
                logLevel = "trace";

                writeLoggerToLog4j2XMLFile(appName, logLevel);      
            }
        }

        File       fileForWriteTwo     = new File("src/main/resources/log4j2.xml");
        FileWriter fileWriterObjectTwo = new FileWriter(fileForWriteTwo, true);

        fileWriterObjectTwo.write("</Loggers>"+ System.getProperty("line.separator"));
        fileWriterObjectTwo.write("</Configuration>"+ System.getProperty("line.separator"));

        // Close file handle
        fileWriterObjectTwo.close();

        System.out.println("generateLog4j2XMLFile Completed.");
     }
    catch(Exception e) {
        System.out.println("Exception In generateLog4j2XMLFile: " + e);
    }
}

public void writeLoggerToLog4j2XMLFile(String appName, String logLevel) {
    try {
        File       fileForWrite  = new File("src/main/resources/log4j2.xml");
        FileWriter fileWriterObject = new FileWriter(fileForWrite, true);

        fileWriterObject.write("<AsyncLogger name="+"\""+ appName +  "\"" +" " +"level="+"\"" + logLevel + "\""+" "+"includeLocation="+"\"true\""+" "+ "additivity="+"\"false\""+">"+ System.getProperty("line.separator"));
        fileWriterObject.write("<AppenderRef ref="+"\"" + appName +"\"" + "/>" + System.getProperty("line.separator"));
        fileWriterObject.write("</AsyncLogger>"+ System.getProperty("line.separator"));

        fileWriterObject.close();
    }
    catch(Exception e) {
        System.out.println("Exception In writeLoggerToLog4j2XMLFile : " + e);
    }
}

public void writeAppenderToLog4j2XMLFile(
        String appName, String filePath, String filePattern, String pattern, String logLevel) { 
        try {
            File       fileForWrite  = new File("src/main/resources/log4j2.xml");
            FileWriter fileWriterObject = new FileWriter(fileForWrite, true);

            String fileRollOverSize = "100 MB";
            String maxNumberOfFiles = "20";  

            fileWriterObject.write("<RollingRandomAccessFile name=" + "\"" + appName + "\"" + " immediateFlush=" + "\""  + "false" + "\"" + " fileName=" + "\""+ filePath +"\""+" "+ "append=" + "\"true\"" +" "+ "filePattern=" + "\"" + filePattern + "\">"+ System.getProperty("line.separator"));
            fileWriterObject.write("<PatternLayout>" + System.getProperty("line.separator"));
            fileWriterObject.write("<Pattern>" + pattern + "</Pattern>" + System.getProperty("line.separator"));
            fileWriterObject.write("</PatternLayout>" + System.getProperty("line.separator"));

            fileWriterObject.write("<Policies>" + System.getProperty("line.separator"));
            fileWriterObject.write("<SizeBasedTriggeringPolicy size="+"\"" + fileRollOverSize + "\""+ "/>" + System.getProperty("line.separator"));
            fileWriterObject.write("</Policies>" + System.getProperty("line.separator"));
            fileWriterObject.write("<DefaultRolloverStrategy fileIndex="+"\"max\""+" "+"max="+"\"" + maxNumberOfFiles + "\""+"/>"+ System.getProperty("line.separator"));
            fileWriterObject.write("</RollingRandomAccessFile>" + System.getProperty("line.separator"));

            fileWriterObject.close();
        }
        catch(Exception e) {
            System.out.println("Exception In writeAppenderToLog4j2XMLFile: " + e);
        }
    }

}

Maven依赖项

<!-- https://mvnrepository.com/artifact/com.lmax/disruptor -->
        <dependency>
            <groupId>com.lmax</groupId>
            <artifactId>disruptor</artifactId>
            <version>3.3.0</version>
        </dependency>


        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.8.2</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.8.2</version>
        </dependency> 

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.8.2</version>
         </dependency>

通过代码将一个用户添加到xml文件中时,将创建日志文件,但是通过代码将第二个用户动态添加时,则不会创建日志文件。

注意:日志下有两个不同的文件夹。一个用于FixGateway,另一个用于FixAcceptor。

我尝试通过google和其他博客搜索问题,但在消除此错误方面没有任何改进。

2 个答案:

答案 0 :(得分:0)

我认为您正在使自己变得更难做。 Log4j2提供了RoutingAppender,可用于dynamically write to separate log files,而根本无需修改配置文件。

我使用您的一些配置创建了一个简单的示例,以说明无需编程修改配置文件即可如何完成所需的工作。

这是一个包含main方法的类,我们将使用该方法来运行log4j2:

package pkg;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;

public class Log4j2DiffFilePerUserMain {
    private static final Logger LOG = LogManager.getLogger();
    private static final Logger USER_LOG = LogManager.getLogger("Users");

    public static void main(String[] args){

        ThreadContext.put("userId", "user1");
        LOG.info("Now generating user1 log entry");
        USER_LOG.info("This should appear in user1 log file");

        ThreadContext.put("userId", "user2");
        LOG.info("Now generating user2 log entry");
        USER_LOG.info("This should appear in user2 log file");
    }
}

请注意main如何两次调用ThreadContext.put。这模拟了让不同的用户执行代码。另请注意,有两个记录器-一个用于“应用程序”,一个用于“用户”。根据您的配置,我相信您希望将它们分开。

这是log4j2.xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <RollingRandomAccessFile
            name="Application" immediateFlush="false"
            fileName="logs/FixGatewayLogs/Application.log"
            append="true"
            filePattern="logs/FixGatewayLogs/Application-%d{dd-MM-yyyy}-%i.log.gz">
            <PatternLayout>
                <Pattern>%d %-5p [%t] (%F:%L) - %m%n</Pattern>
            </PatternLayout>
            <Policies>
                <SizeBasedTriggeringPolicy size="100 MB" />
            </Policies>
            <DefaultRolloverStrategy fileIndex="max"
                max="20" />
        </RollingRandomAccessFile>
        <Routing name="UsersAppender">
            <Routes pattern="$${ctx:userId}">
                <Route>
                    <RollingRandomAccessFile name="user-${ctx:userId}"
                        immediateFlush="false"
                        fileName="logs/FixAcceptorLogs/${ctx:userId}.log"
                        append="true"
                        filePattern="logs/FixAcceptorLogs/${ctx:userId}-%d{dd-MM-yyyy}-%i.log.gz">
                        <PatternLayout>
                            <Pattern>%d %F - %m%n</Pattern>
                        </PatternLayout>
                        <Policies>
                            <SizeBasedTriggeringPolicy size="100 MB" />
                        </Policies>
                        <DefaultRolloverStrategy fileIndex="max"
                            max="20" />
                    </RollingRandomAccessFile>
                </Route>
            </Routes>
        </Routing>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Application" />
        </Root>
        <Logger name="Users" level="debug"
            includeLocation="false" additivity="false">
            <AppenderRef ref="UsersAppender" />
        </Logger>
    </Loggers>
</Configuration>

如您所见,我使用RoutingAppender的方式与log4j2 FAQ page中使用的方式非常相似。它使用userId上下文变量来动态决定向其发送消息的日志。

运行上述代码和配置,将在2个文件夹中生成3个文件:

enter image description here

user1.log文件包含: 2018-09-18 20:12:42,482 - This should appear in user1 log file

user2.log文件包含: 2018-09-18 20:12:42,485 - This should appear in user2 log file

最后,应用程序日志包含:

2018-09-18 20:12:42,480 INFO  [main] (Log4j2DiffFilePerUserMain.java:14) - Now generating user1 log entry
2018-09-18 20:12:42,485 INFO  [main] (Log4j2DiffFilePerUserMain.java:19) - Now generating user2 log entry

希望这对您有所帮助。

答案 1 :(得分:0)

不确定您在那做什么,尤其是

File fileForDelete = new File("src/main/resources/log4j2.xml");

无论如何,您可以使用org.apache.logging.log4j.core.LoggerContext.setConfigLocation(URI)用新的配置替换当前的配置:

((LoggerContext) LogManager.getContext(false)).setConfigLocation(newUri);

我猜您的代码似乎第一次起作用,因为您在初始化 log4j2之前替换了xml文件-如果您在调用createLog4jFile()之前记录了任何消息,我敢打赌别欺骗您,让它相信它是有效的。

程序配置可能比您当前正在使用的... hack更适合您的用例-有关某些指针,请参见https://logging.apache.org/log4j/2.x/manual/customconfig.html

PS:如果您将log4j-slf4j-imp作为依赖项,则不需要slf4j-apilog4j-slf4j-imp将其作为传递依赖项)