[英]How to create multiple log file programatically in log4j2?
我正在开发一个与许多设备通信的 java 应用程序。 对于每个设备,我需要创建一个不同的日志文件来记录它与设备的通信。 这是我开发的包装类。 它创建两个日志文件,但数据只写入第一个。 创建了第二个文件,但没有写入任何内容。 应该转到第二个文件的输出转到控制台。 如果我在构造函数中取消对 createRootLogger() 的注释,则两个文件都不会写入任何内容,所有内容都会进入控制台。 我已经阅读了 log4j2 文档,但它写得不好,代码示例很少。 这是我的包装类,错误在哪里? 我正在使用 log4j-api-2.9.0.jar 和 log4j-core-2.9.0.jar。
package xyz;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.Logger;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.ConsoleAppender;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.Configurator;
import org.apache.logging.log4j.core.config.builder.api.*;
import java.util.Hashtable;
public class LogManager
{
static protected LogManager m_clsInstance = null;
protected Hashtable<String, Logger> m_clsLoggers = new Hashtable<String, Logger>();
private LogManager()
{
//createRootLogger();
}
/**
* getInstance is used to get reference to the singalton class obj ......
*/
static synchronized public LogManager getInstance()
{
try
{
if (m_clsInstance == null)
{
m_clsInstance = new LogManager();
//Configurator.setRootLevel(Level.TRACE);
}
}
catch (Exception xcpE)
{
System.err.println(xcpE);
}
return m_clsInstance;
}
static public Logger getLogger(String sLogger)
{
try
{
return getInstance().m_clsLoggers.get(sLogger);
}
catch (Exception xcpE)
{
System.err.println(xcpE);
}
return null;
}
public Logger createLogger(String strName, String sPath, int nBackupSize, long lngMaxSize, String strPattern, String strLevel)
{
try
{
ConfigurationBuilder builder = ConfigurationBuilderFactory.newConfigurationBuilder();
builder.setStatusLevel(Level.getLevel(strLevel));
builder.setConfigurationName("RollingBuilder"+strName);
// create a console appender
AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE").addAttribute("target",
ConsoleAppender.Target.SYSTEM_OUT);
appenderBuilder.add(builder.newLayout("PatternLayout")
.addAttribute("pattern", strPattern));
builder.add( appenderBuilder );
// create a rolling file appender
LayoutComponentBuilder layoutBuilder = builder.newLayout("PatternLayout")
.addAttribute("pattern", strPattern);
ComponentBuilder triggeringPolicy = builder.newComponent("Policies")
// .addComponent(builder.newComponent("CronTriggeringPolicy").addAttribute("schedule", "0 0 0 * * ?"))
.addComponent(builder.newComponent("SizeBasedTriggeringPolicy").addAttribute("size", lngMaxSize));
appenderBuilder = builder.newAppender("rolling"+strName, "RollingFile")
.addAttribute("fileName", sPath)
.addAttribute("filePattern", "d:\\trash\\archive\\rolling-%d{MM-dd-yy}.log.gz")
.add(layoutBuilder)
.addComponent(triggeringPolicy);
builder.add(appenderBuilder);
// create the new logger
builder.add( builder.newLogger( strName, Level.getLevel(strLevel) )
.add( builder.newAppenderRef( "rolling"+strName ) )
.addAttribute( "additivity", false ) );
Configuration clsCnfg = (Configuration) builder.build();
LoggerContext ctx = Configurator.initialize(clsCnfg);
Logger clsLogger = ctx.getLogger(strName);
m_clsLoggers.put(strName, clsLogger);
return clsLogger;
}
catch (Exception xcpE)
{
System.err.println(xcpE);
}
return null;
}
protected void createRootLogger()
{
try
{
ConfigurationBuilder builder = ConfigurationBuilderFactory.newConfigurationBuilder();
builder.setStatusLevel(Level.getLevel("TRACE"));
builder.setConfigurationName("rootConfig");
// create a console appender
AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE").addAttribute("target",
ConsoleAppender.Target.SYSTEM_OUT);
appenderBuilder.add(builder.newLayout("PatternLayout")
.addAttribute("pattern", "[%d{yyyy-MMM-dd HH:mm:ss:SSS}][%-5p %l][%t] %m%n"));
builder.add( appenderBuilder );
builder.add( builder.newRootLogger( Level.getLevel("TRACE"))
.add( builder.newAppenderRef( "Stdout") ) );
Configuration clsCnfg = (Configuration) builder.build();
LoggerContext ctx = Configurator.initialize(clsCnfg);
Logger clsLogger = ctx.getRootLogger();
m_clsLoggers.put("root", clsLogger);
}
catch (Exception xcpE)
{
System.err.println(xcpE);
}
}
static public void main(String args[])
{
//Logger clsLogger = setLogger();
Logger clsLogger = Emflex.LogManager.getInstance().createLogger(
"AnsiAmrController_" + 5555,
"d:\\trash\\LogManagerTest5555.log",
10,
100000000,
"[%d{yyyy-MMM-dd HH:mm:ss:SSS}][%-5p %l][%t] %m%n",
"TRACE"
);
Logger clsLogger2 = Emflex.LogManager.getInstance().createLogger(
"AnsiAmrController_" + 6666,
"d:\\trash\\LogManagerTest6666.log",
10,
100000000,
"[%d{yyyy-MMM-dd HH:mm:ss:SSS}][%-5p %l][%t] %m%n",
"TRACE"
);
for (int i=0;i<100;i++)
{
clsLogger.error("Testing - ["+i+"]");
clsLogger2.error("Testing - ["+(i*i)+"]");
}
}
}
你说你的目标是:
对于每个设备,我需要创建一个不同的日志文件来记录它与设备的通信。
有许多不同的方法可以在没有编程配置的情况下完成此操作。 编程配置很糟糕,因为它迫使您依赖日志记录实现而不是公共接口。
例如,您可以将上下文映射键与Routing Appender结合使用来分隔日志,类似于我在另一个答案中给出的示例。 请注意,在另一个答案中,我使用变量作为存储日志的文件夹,但如果您愿意,可以将其用作日志名称。
另一种做你想做的事情的方法是使用一个MapMessage ,如log4j2 手册中所示。
另一种方法是将标记与RoutingAppender结合使用。 以下是此方法的一些示例代码:
package example;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
public class LogLvlByMarkerMain {
private static final Logger log = LogManager.getLogger();
private static final Marker DEVICE1 = MarkerManager.getMarker("DEVICE1");
private static final Marker DEVICE2 = MarkerManager.getMarker("DEVICE2");
public static void main(String[] args) {
log.info(DEVICE1, "The first device got some input");
log.info(DEVICE2, "The second device now has input");
}
}
配置:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Routing name="MyRoutingAppender">
<Routes pattern="$${marker:}">
<Route>
<File
fileName="logs/${marker:}.txt"
name="appender-${marker:}">
<PatternLayout>
<Pattern>[%date{ISO8601}][%-5level][%t] %m%n</Pattern>
</PatternLayout>
</File>
</Route>
</Routes>
</Routing>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="[%date{ISO8601}][%-5level][%t] %m%n" />
</Console>
</Appenders>
<Loggers>
<Logger name="example" level="TRACE" additivity="false">
<AppenderRef ref="STDOUT" />
<AppenderRef ref="MyRoutingAppender" />
</Logger>
<Root level="WARN">
<AppenderRef ref="STDOUT" />
</Root>
</Loggers>
</Configuration>
输出:
这将生成 2 个日志文件 - DEVICE1.txt 和 DEVICE2.txt,如下图所示。
第一个日志将仅包含标记为 DEVICE1 的消息,第二个将仅包含 DEVICE2 日志。
即第一个日志包含:
[2017-09-21T09:52:04,171][INFO ][main] The first device got some input
第二个包含:
[2017-09-21T09:52:04,176][INFO ][main] The second device now has input
方法log4j2
以编程方式初始化,稍后修改的配置不同。 而您尝试使用初始化方法添加动态appender
和logger
。
因此,首先您应该使用在您的代码中似乎正确的初始化方法来初始化您的 RootLogger。
之后,使用这里提到的方法添加动态appender
和logger
添加数据库答案:
我无法将此写入文件。 (是的,我尝试使用 log4j2 2.8.1 版,但仍然无效)
为了使它工作,我编辑了这部分
<Root level="WARN">
<AppenderRef ref="STDOUT" />
</Root>
对此:
<Root level="WARN">
<AppenderRef ref="STDOUT" />
<AppenderRef ref="MyRoutingAppender" />
</Root>
并且由于调试级别设置为 WARN
<Configuration status="WARN">
我们试图记录信息
log.info(DEVICE$, "The $ device now has input");
不会写入信息日志(WARN 只会打印:警告、错误、致命检查此链接log4j 日志记录级别)
你可以简单地改变
log.info() --> log.warn()
只是作为概念的证明。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.