log4j2:注册自定义TriggeringPolicy

时间:2014-10-24 00:04:52

标签: log4j2 rollingfileappender

我已经为log4j2编写了一个自定义TriggeringPolicy,假设在this SO post之后的每个小时/每天/ your_interval结束时翻转.log文件。

虽然我遵循了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解析期间不知道Routes appender(在我的情况下由$$ {sd:type}定义)。因此 - 它们的创建/初始化会延迟到目标 $$ {sd:type} 的第一条消息到达的那一刻。我的下一个计划是:

  • 将StructuredDataFilter添加到Routes appender
  • 在系统启动时向所有已知的 $$ {sd:type} 提供一条空消息,该消息一方面应初始化Route appender并导致 FTimeBasedTriggeringPolicy LogRotateThread 中注册自己,但在其他方面 - 应该被StructuredDataFilter丢弃
  • 允许 LogRotateThread 查询已注册的 FTimeBasedTriggeringPolicy 并根据需要轮换日志

1 个答案:

答案 0 :(得分:1)

在调试时,似乎在log4j2.xml解析期间不知道Routes appender(在我的情况下由 $$ {sd:type} 定义)。因此,它们的创建/初始化被延迟到目的地$$ {sd:type}的第一条消息到达的那一刻。 因此,帖子的原始主题可以回答为&#34;自定义策略已注册,但并不总是立即(或在.xml分析时间内)&#34;。

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

  1. 在TimeBasedTriggeringPolicy周围写了一个瘦包装器 - FTimeBasedTriggeringPolicy ,它在LogRotateThread实例化时自我注册
  2. 编写了一个简单的 LogRotateThread ,每隔几分钟查询一次注册的FTimeBasedTriggeringPolicy并根据需要将它们旋转.log
  3. 在Routes appender中添加了 StructuredDataFilter ,以便它们丢弃特定的消息(在我的情况下id = SKIP)
  4. 在系统启动时向所有已知的$$ {sd:type}提供一条空消息,其中:
    一个。实例化Route appender并使FTimeBasedTriggeringPolicy在LogRotateThread中注册自己
    湾被StructuredDataFilter
  5. 丢弃

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

    获取