当前位置: 首页 > 知识库问答 >
问题:

动态选择日志文件

商同
2023-03-14

我有一个应用程序,其中包含许多在数据库中创建数据的组件。每个组件记录创建数据时所做的事情。有很多这样的组件,而且应用程序非常灵活,因此每次运行时不必总是执行相同的一组数据创建组件。

目前,所有内容都记录到一个文件中,这会生成一些开始变得不可管理的文件。我希望每个组件都可以登录到一个文件,该文件的名称描述了编写它的组件-ComponentA应该登录到componentadatacreationphase。日志

我见过的大多数解决方案似乎都假设不同的记录器是静态的,所以可以按名称查找它们,例如LogManager.getLogger(ComponentA);-假设在我的log4j2.xml.中已经配置了具有该名称的记录器,我见过的其他解决方案使用了路由和线程上下文-但我不确定这是否有效,因为这些组件可能都在同一个线程中执行。

如何让每个组件(许多是不同的类,但有些只是同一类的不同实例,只是配置不同)登录到自己的日志文件?理想情况下,这将基于现有的log4j2完成。xml文件,如log4j2。xml可能有一些用户指定的配置,我希望将这些配置传播到特定于组件的记录器,例如日志路径和日志级别。

共有1个答案

颜君浩
2023-03-14

我找到了这个答案:

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插件生成的,不幸的是,我无法编辑它。也就是