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和其他博客搜索问题,但在消除此错误方面没有任何改进。
答案 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个文件:
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-api
(log4j-slf4j-imp
将其作为传递依赖项)