log4j2:注册自定义的TriggeringPolicy[英] log4j2: registering custom TriggeringPolicy

本文是小编为大家收集整理的关于log4j2:注册自定义的TriggeringPolicy的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我已经为log4j2编写了一个自定义触发policy,它应该在每小时/天/day/your_interval的末尾滚动.log文件,以下来自 so so post .

尽管我遵循了TimeBasedTriggeringPolicy惯例(命名等),但我无法看到我的策略正在实例化和使用.

解决方案由3个Java文件 +一个maven文件组成,可在 github . > 在这里,您可以从策略本身中找到主线:

@Plugin(name = "FTimeBasedTriggeringPolicy", category = "Core", printObject = true)
public class FTimeBasedTriggeringPolicy implements TriggeringPolicy {

    private final TimeBasedTriggeringPolicy timeBasedTriggeringPolicy;  
    private RollingFileManager manager;

    private FTimeBasedTriggeringPolicy(final int interval, final boolean modulate) {
        timeBasedTriggeringPolicy = TimeBasedTriggeringPolicy.createPolicy(String.valueOf(interval), String.valueOf(modulate));
        LogRotateThread.registerPolicy(this);
    }

    public void checkRollover(final LogEvent event) {
        this.manager.checkRollover(event);
    }

    @Override
    protected void finalize() throws Throwable {
        LogRotateThread.unregisterPolicy(this);
        super.finalize();
    }

    @Override
    public void initialize(final RollingFileManager manager) {
        this.manager = manager;
        timeBasedTriggeringPolicy.initialize(manager);
    }

    @Override
    public boolean isTriggeringEvent(final LogEvent event) {
        return timeBasedTriggeringPolicy.isTriggeringEvent(event);
    }

    @Override
    public String toString() {
        return "FTimeBasedTriggeringPolicy";
    }

    @PluginFactory
    public static FTimeBasedTriggeringPolicy createPolicy(
            @PluginAttribute("interval") final String interval,
            @PluginAttribute("modulate") final String modulate) {
        final int increment = Integers.parseInt(interval, 1);
        final boolean mod = Boolean.parseBoolean(modulate);
        return new FTimeBasedTriggeringPolicy(increment, mod);
    }
}

log4j2.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug" name="RoutingLoggingConfiguration" packages="org.log4j2plugin" verbose="true">
    <Properties>
        <Property name="routing_filename">${log.path}/table-$${sd:type}.log</Property>
    </Properties>

    <Appenders>
        <Console name="STDOUT">
            <PatternLayout pattern="%d{yyyyMMddHH}{GMT+0} %m%n"/>
        </Console>

        <Routing name="Routing">
            <Routes pattern="$${sd:type}">
                <Route>
                    <RollingFile name="RollingFile-${sd:type}"
                                 fileName="${routing_filename}"
                                 filePattern="${log.path}/%d{yyyyMMdd}{GMT+0}/%d{yyyyMMddHH}{GMT+0}-${sd:type}-${hostName}.%i.log.gz">
                        <PatternLayout>
                            <Pattern>%d{yyyyMMddHH}{GMT+0},'%d{yyyy-MM-dd HH:mm:ss}{GMT+0}',%K{v}%n</Pattern>
                        </PatternLayout>
                        <Policies>
                            <FTimeBasedTriggeringPolicy interval="1"/>
                            <SizeBasedTriggeringPolicy size="64 MB"/>
                        </Policies>
                        <DefaultRolloverStrategy max="999"/>
                    </RollingFile>
                </Route>
            </Routes>
        </Routing>
    </Appenders>

    <Loggers>
        <Logger name="EventLogger" level="debug" additivity="false">
            <AppenderRef ref="Routing"/>
        </Logger>

        <Root level="warn">
            <AppenderRef ref="STDOUT"/>
        </Root>
    </Loggers>
</Configuration>

编辑:

在调试期间,我知道在log4j2.xml解析期间,尚不知道附带附加条件(由$$ {sd:type}定义).因此 - 他们的创建/初始化被延迟到目标 $$ {sd:type} 到达的那一刻.我的下一个计划是:

  • 在Appender
  • 的路线上添加一个结构化的Datafilter
  • 在系统启动时向所有已知 $$ {sd:type} 提供一个空的消息,一方面应初始化路由appender,并导致 ftimebasedtriggeringpolicypolicy 在 logrotateThread 中注册自己,但在另一个中应由结构性datafilter丢弃
  • 允许 logrotatethread 查询注册 ftimebasedtriggeringpolicypolicy ,如果需要,请旋转日志

推荐答案

在调试时,似乎在log4j2.xml解析过程中未知路由附录(由 $$ {sd:type} 定义).因此,他们的创建/初始化被延迟到目标$$ {sd:type}到达的第一篇消息时的时刻. 因此,帖子的原始主题可以回答为"自定义策略已注册,但是并非总是立即(或.xml分析时间)".

然而,最初的问题是强制.log文件在时间段结束时滚动(在我的情况下为一个小时).为了解决这个问题,我已经实现了以下算法:

  1. 写了一个围绕TimeBasedTriggeringPolicy - ftimebasedtriggeringpolicypolicy 在logrotateThread
  2. 上注册自己的薄薄包装纸.
  3. 写了一个简单的 logrotateThread ,每隔几分钟就查询了一次注册的ftimebasedtriggeringpolicypolicy,并使他们在需要时旋转.log
  4. 在路由上添加了 structureddatafilter ,以便它们丢弃特定消息(在我的情况下使用ID = Skip)
  5. 在系统启动时向所有已知$$ {sd:type}提供一个空的消息,哪个:
    A.实例化路由Appender,并导致FTimeBasedTriggeringPolicy在LogrotateThread
    中注册 b.被构造的datafilter丢弃

解决方案在Apache 2.0许可下发布,可在 github

本文地址:https://www.itbaoku.cn/post/1575214.html

问题描述

I have written a custom TriggeringPolicy for log4j2 that is suppose to roll-over .log file at the end of every hour/day/your_interval following advices from this SO post.

Though I followed TimeBasedTriggeringPolicy conventions (naming, etc) I am not able to see my policy being instantiated and used.

Solution comprise of 3 java files + a maven file and is available at the github.
Here you can find main lines from the policy itself:

@Plugin(name = "FTimeBasedTriggeringPolicy", category = "Core", printObject = true)
public class FTimeBasedTriggeringPolicy implements TriggeringPolicy {

    private final TimeBasedTriggeringPolicy timeBasedTriggeringPolicy;  
    private RollingFileManager manager;

    private FTimeBasedTriggeringPolicy(final int interval, final boolean modulate) {
        timeBasedTriggeringPolicy = TimeBasedTriggeringPolicy.createPolicy(String.valueOf(interval), String.valueOf(modulate));
        LogRotateThread.registerPolicy(this);
    }

    public void checkRollover(final LogEvent event) {
        this.manager.checkRollover(event);
    }

    @Override
    protected void finalize() throws Throwable {
        LogRotateThread.unregisterPolicy(this);
        super.finalize();
    }

    @Override
    public void initialize(final RollingFileManager manager) {
        this.manager = manager;
        timeBasedTriggeringPolicy.initialize(manager);
    }

    @Override
    public boolean isTriggeringEvent(final LogEvent event) {
        return timeBasedTriggeringPolicy.isTriggeringEvent(event);
    }

    @Override
    public String toString() {
        return "FTimeBasedTriggeringPolicy";
    }

    @PluginFactory
    public static FTimeBasedTriggeringPolicy createPolicy(
            @PluginAttribute("interval") final String interval,
            @PluginAttribute("modulate") final String modulate) {
        final int increment = Integers.parseInt(interval, 1);
        final boolean mod = Boolean.parseBoolean(modulate);
        return new FTimeBasedTriggeringPolicy(increment, mod);
    }
}

The log4j2.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug" name="RoutingLoggingConfiguration" packages="org.log4j2plugin" verbose="true">
    <Properties>
        <Property name="routing_filename">${log.path}/table-$${sd:type}.log</Property>
    </Properties>

    <Appenders>
        <Console name="STDOUT">
            <PatternLayout pattern="%d{yyyyMMddHH}{GMT+0} %m%n"/>
        </Console>

        <Routing name="Routing">
            <Routes pattern="$${sd:type}">
                <Route>
                    <RollingFile name="RollingFile-${sd:type}"
                                 fileName="${routing_filename}"
                                 filePattern="${log.path}/%d{yyyyMMdd}{GMT+0}/%d{yyyyMMddHH}{GMT+0}-${sd:type}-${hostName}.%i.log.gz">
                        <PatternLayout>
                            <Pattern>%d{yyyyMMddHH}{GMT+0},'%d{yyyy-MM-dd HH:mm:ss}{GMT+0}',%K{v}%n</Pattern>
                        </PatternLayout>
                        <Policies>
                            <FTimeBasedTriggeringPolicy interval="1"/>
                            <SizeBasedTriggeringPolicy size="64 MB"/>
                        </Policies>
                        <DefaultRolloverStrategy max="999"/>
                    </RollingFile>
                </Route>
            </Routes>
        </Routing>
    </Appenders>

    <Loggers>
        <Logger name="EventLogger" level="debug" additivity="false">
            <AppenderRef ref="Routing"/>
        </Logger>

        <Root level="warn">
            <AppenderRef ref="STDOUT"/>
        </Root>
    </Loggers>
</Configuration>

EDIT:

During debugging I understood that Routes appenders (defined by the $${sd:type} in my case) are not known during log4j2.xml parsing. Thus - their creation/initialization is delayed in time to the moment when the first message for destination $${sd:type} arrives. My next plan is to:

  • add a StructuredDataFilter to the Routes appender
  • provide an empty message at the system start-up to all known $${sd:type}, which on one hand should initialize Route appender and cause FTimeBasedTriggeringPolicy to register itself in the LogRotateThread, but on other - should be discarded by the StructuredDataFilter
  • allow LogRotateThread to query registered FTimeBasedTriggeringPolicy and rotate logs if needed

推荐答案

While debugging, it appeared that Routes appenders (defined by the $${sd:type} in my case) are not known during log4j2.xml parsing. Thus, their creation/initialization is delayed in time to the moment when the first message for the destination $${sd:type} arrives. Thus, the original subject of the post could be answered as "custom policy is registered, however not always instantly (or during the .xml parse time)".

The original problem, however, was to force .log files to roll-over at the end of the time period (an hour in my case). To address it, I have implemented following algorithm:

  1. wrote a thin wrapper around TimeBasedTriggeringPolicy - FTimeBasedTriggeringPolicy that registers itself on instantiation at LogRotateThread
  2. wrote a simple LogRotateThread that queries registered FTimeBasedTriggeringPolicy once every few minutes and makes them rotate .log if needed
  3. added a StructuredDataFilter to the Routes appender, so that they discard specific messages (with id=SKIP in my case)
  4. provide an empty message at the system start-up to all known $${sd:type}, which:
    a. instantiate Route appender and cause FTimeBasedTriggeringPolicy to register itself in the LogRotateThread
    b. are discarded by the StructuredDataFilter

Solution is published under Apache 2.0 license, and is available at github