我有一个应用程序,其中包含许多在数据库中创建数据的组件。每个组件记录创建数据时所做的事情。有很多这样的组件,而且应用程序非常灵活,因此每次运行时不必总是执行相同的一组数据创建组件。
目前,所有内容都记录到一个文件中,这会生成一些开始变得不可管理的文件。我希望每个组件都可以登录到一个文件,该文件的名称描述了编写它的组件-ComponentA
应该登录到componentadatacreationphase。日志
。
我见过的大多数解决方案似乎都假设不同的记录器是静态的,所以可以按名称查找它们,例如LogManager.getLogger(ComponentA);
-假设在我的log4j2.xml.中已经配置了具有该名称的记录器,我见过的其他解决方案使用了路由和线程上下文-但我不确定这是否有效,因为这些组件可能都在同一个线程中执行。
如何让每个组件(许多是不同的类,但有些只是同一类的不同实例,只是配置不同)登录到自己的日志文件?理想情况下,这将基于现有的log4j2完成。xml文件,如log4j2。xml可能有一些用户指定的配置,我希望将这些配置传播到特定于组件的记录器,例如日志路径和日志级别。
我找到了这个答案:
https://stackoverflow.com/a/38096181/192801
我使用它作为一个新函数的基础,我通过顶级界面中的默认方法将它添加到所有组件中。
添加到所有组件的接口:
public interface Component {
default Logger createLogger(String logFileName, String oldAppenderName, String newAppenderName, boolean append, Level level)
{
LoggerContext context = (LoggerContext) LogManager.getContext(false);
Configuration configuration = context.getConfiguration();
Appender oldAppender = configuration.getAppender(oldAppenderName);
Layout<? extends Serializable> oldLayout = oldAppender.getLayout();
// create new appender/logger
LoggerConfig loggerConfig = new LoggerConfig(logFileName, level, false);
Appender appender ;
// In my case, it is possible that the old appender could
// either be a simple FileAppender, or a RollingRandomAccessFileAppender,
// so I'd like the new one to be of the same type as the old one.
// I have yet to find a more elegant way to do create a new Appender
// of *any* type and then copy all relevant config.
if (oldAppender instanceof RollingRandomAccessFileAppender)
{
int bufferSize = ((RollingRandomAccessFileAppender)oldAppender).getBufferSize();
RollingRandomAccessFileManager oldMananger = (RollingRandomAccessFileManager)((RollingRandomAccessFileAppender) oldAppender).getManager();
TriggeringPolicy triggerPolicy = oldMananger.getTriggeringPolicy();
RolloverStrategy rollStrategy = oldMananger.getRolloverStrategy();
Filter filter = ((RollingRandomAccessFileAppender)oldAppender).getFilter();
// Inject new log file name into filePattern so that file rolling will work properly
String pattern = ((RollingRandomAccessFileAppender)oldAppender).getFilePattern().replaceAll("/[^/]*-\\%d\\{yyyy-MM-dd\\}\\.\\%i\\.log\\.gz", "/"+logFileName+"-%d{yyyy-MM-dd}.%i.log.gz");
appender = RollingRandomAccessFileAppender.newBuilder()
.withFileName("logs/" + logFileName + ".log")
.withFilePattern(pattern)
.withAppend(append)
.withName(newAppenderName)
.withBufferSize(bufferSize)
.withPolicy(triggerPolicy)
.withStrategy(rollStrategy)
.withLayout(oldLayout)
.withImmediateFlush(true)
.withFilter(filter)
.build();
}
else
{
appender = FileAppender.newBuilder()
.withFileName("logs/" + logFileName + ".log")
.withAppend(append)
.withName(newAppenderName)
.withLayout(oldLayout)
.setConfiguration(configuration)
.withLocking(false)
.withImmediateFlush(true)
.withIgnoreExceptions(true)
.withBufferSize(8192)
.withFilter(null)
.withAdvertise(false)
.withAdvertiseUri("")
.build();
}
appender.start();
loggerConfig.addAppender(appender, level, null);
configuration.addLogger(logFileName, loggerConfig);
context.updateLoggers();
return context.getLogger(logFileName);
}
此函数的使用发生在组件的构造函数中:
public class ComponentA implements Component
{
private Logger logger = LogManager.getLogger();
public ComponentA(String componentName)
{
this.logger = this.createLogger(componentName, "MyOriginalFileAppender", componentName+"Appender", true, Level.DEBUG, this.logger);
}
}
和其他地方:
ComponentA fooSubtypeAComponent = new ComponentA("FooA");
ComponentA barSubtypeAComponent = new ComponentA("BarA");
ComponentB fooVariantTypeBComponent = new ComponentB("FooB");
原始Appenders Loggers片段来自Log4j配置:
<Appenders>
<!-- STDOUT appender. -->
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout
pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36}#%M - %msg%n" />
</Console>
<RollingRandomAccessFile name="MyOriginalFileAppender" fileName="${baseDir}/${defaultLogName}.log" filePattern="${baseDir}/$${date:yyyy-MM}/${defaultLogName}-%d{MM-dd-yyyy}.%i.log.gz">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36}#%M - %msg%n" />
<Policies>
<!-- <TimeBasedTriggeringPolicy /> -->
<!-- Let's try cron triggering policy configured to trigger every day at midnight -->
<CronTriggeringPolicy schedule="0 0 0 * * ?"/>
<SizeBasedTriggeringPolicy size="25 MB" />
</Policies>
</RollingRandomAccessFile>
</Appenders>
<Loggers>
<Root level="debug">
<!-- only write INFO level to the file. -->
<AppenderRef ref="MyOriginalFileAppender" level="debug"/>
<!-- Console shows everything at DEBUG level-->
<AppenderRef ref="Console" level="info" />
</Root>
</Loggers>
结果应该是三个日志文件:
logs/FooA。日志
,日志/BarA。日志
,日志/FooB。日志
-上面显示的每个实例都有一个日志文件。仍有一些问题需要解决,但我认为这会很好。
问题内容: 我当前正在创建一个可以包含模块的系统(将它们视为插件),其中每个模块可以拥有自己的专用日志。 我想使用log4j2项目进行日志记录,但是文件附加器似乎有些麻烦。 主项目(整个模块的模块加载器和“核心”)应具有自己的日志文件,而模块应具有自己的日志文件(如)。 通过阅读有关追加程序的文档,我发现了该类,并且我将使用它。直到我发现不能简单地将追加器添加到由创建的默认记录器中。 LogMan
我目前正在创建一个系统,可以有模块(把它们看作插件),其中每一个都可以有自己的日志,专用的。 我想使用log4j2项目进行日志记录,但我似乎在文件附加符方面遇到了一些麻烦。 主项目(模块加载器和整个事情的“核心”)应该有自己的日志文件,而模块应该有自己的日志文件(像)。 即使搜索也没有给我提供任何接近的解决方案,我找到的只是xml配置中预定义的文件日志--这不是我想要的。 感谢你的阅读;即使是最轻
我想在Log4j2中设置一个目录。xml动态。 Log4j2。xml 运行: 输出: 2017-03-15 18:20:27131主要错误 无法创建文件${sys:logDirectory}/app。记录java。伊奥。IOException: 文件名、目录名或驱动器名的语法错误 ---编辑:德语中的原始错误消息是:-- (Dateinamen,Verzeichnisnamen或Datenträg
你可以在命令行中选择如表 17.2.Log 等级命令行选项所示的选项选择不同的日志级别.如表 17.3.堆栈信息选项中所示的选项来选择堆栈信息. 表17.2.Log 等级命令行选项 选项 输出日志等级 no logging options LIFECYCLE及更高 -q or —quiet QUIET及更高 -i or —info INFO及更高 -d or —debug DEBUG及更高(所有日
问题内容: 我想要一个log4j配置,这样日志文件名应该像$ {System-name} log.log。也就是说,如果该应用程序在任何系统上启动,则无需更改配置文件或代码。它应该生成提到的日志文件名。谢谢。 问题答案: 我这样做: 1)通过以下方式初始化记录器: 2)在log4j.xml中我使用变量:
我有一个选择元素,里面有多个选项: 对于这里看到的每个选项元素,我都有另一个select元素。基本上,我在一个选择元素中列出了一系列音乐流派,在它下面,是与每一个“主流派”相关的子流派。 我想做的是使子体裁只有在相对体裁被选中时才可见。例如,如果用户选择“Pop”,我想向他们显示包含Pop子类型的相关选择字段。 我的HTML标记实际上是由WordPress插件生成的,不幸的是,我无法编辑它。也就是