制作Logback审计日志记录器包装器



我正在编写一个类,作为Logback Logger的包装器。具体来说,它是为了方便审计日志记录。它应该是一个独立的库,人们应该能够导入和使用。我所遇到的问题与以编程方式声明LogBack所需的最少的文档有关。我基于另一个堆栈溢出问题的一般声明(以编程方式设置Logback Appender路径)。

当前的定义如下:目前我有麻烦得到标记过滤器的工作。就像我声明的那样,标记过滤器似乎什么都不做。最后,我想确保除了审计日志之外没有其他信息进入审计日志文件。这就是为什么我在不匹配上设置了Deny。从我的测试来看,它似乎被忽略了。

关于以编程方式创建的Logback文件的任何信息或方向将不胜感激。还有什么是我应该担心的,当用户使用我的类做审计日志记录,然后使Logback.xml做自己单独的日志记录?谢谢你

import ch.qos.logback.classic.Level;
import ch.qos.logback.core.spi.FilterReply;
import org.slf4j.LoggerFactory;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.core.rolling.TimeBasedRollingPolicy;
import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.filter.EvaluatorFilter;
import ch.qos.logback.classic.boolex.OnMarkerEvaluator;

public class AuditLogger {
    private static Logger logbackLogger;
    final static Marker AUDIT = MarkerFactory.getMarker("AUDIT");
    static {
       LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
       RollingFileAppender rfAppender = new RollingFileAppender();
       rfAppender.setContext(loggerContext);
       rfAppender.setFile("auditLogFile.currentDay.log");
       TimeBasedRollingPolicy rollingPolicy = new TimeBasedRollingPolicy();
       rollingPolicy.setContext(loggerContext);
       // rolling policies need to know their parent
       // it's one of the rare cases, where a sub-component knows about its parent
       rollingPolicy.setParent(rfAppender);
       rollingPolicy.setFileNamePattern("auditLogFile.%d{yyyy-MM-dd}.log");
       rollingPolicy.start();
       PatternLayoutEncoder encoder = new PatternLayoutEncoder();
       encoder.setContext(loggerContext);
       encoder.setPattern("[%d{ISO8601}] %5marker - %msg%n");
       encoder.start();
       rfAppender.setEncoder(encoder);
       rfAppender.setRollingPolicy(rollingPolicy);
       rfAppender.start();
       EvaluatorFilter evalFilter= new EvaluatorFilter();
       OnMarkerEvaluator markerEval= new OnMarkerEvaluator();
       markerEval.addMarker("AUDIT");
       evalFilter.setEvaluator(markerEval);
       evalFilter.setOnMatch(FilterReply.ACCEPT);
       evalFilter.setOnMismatch(FilterReply.DENY);
       rfAppender.addFilter(evalFilter);
       logbackLogger = loggerContext.getLogger("AUDIT_LOGGER");
       logbackLogger.addAppender(rfAppender);
       logbackLogger.setLevel(Level.DEBUG);
   }
   public AuditLogger(){}
   public void log(String msg){
       logbackLogger.debug(AUDIT, msg);
   }
}

我从来没有找到很多关于编程创建的Logback文件的信息,但我将分享我从测试和摆弄中发现的信息。

首先,为了适应Ceki对链接文章的回应,我使用了logback.xml示例和在线API的组合。例如,为了找出如何做标记过滤器,我注意到xml有一个链接到类"ch.qos.logback.core.filter"。EvaluatorFilter"one_answers"ch.qos.logback.classic.boolex.OnMarkerEvaluator"。我使用了在这里找到的API: http://logback.qos.ch/apidocs/ch/qos/logback/core/filter/EvaluatorFilter.html。记住(根据我上面的评论),在以编程方式初始化logback实例时,要为每个过滤器、追加器、编码器、滚动策略、求值器和其他任何创建的东西运行start()方法。如果你不这样做,它将无法工作。

对于我用编程创建和xml创建的logback实例的不同组合进行的测试,我得到了有趣的结果。通过编程创建的logback实例和通过xml创建的logback实例似乎可以一起工作。例如,如果我从编程创建的实例调用logger.debug("msg"),"msg"也将被xml创建的实例接收和评估。我相信这是因为它们都共享同一个"根"记录器。

为了使库在用户不使用logback且不输出到控制台时正确工作,我使用以下代码位。它检查默认日志记录器是否是唯一存在的日志记录器,如果是,则删除控制台附加程序。

    if (loggerContext.getLoggerList().size() == 1) {
        Logger root= loggerContext.getLogger("ROOT");
        root.detachAppender("console");
    }

我发现的唯一致命错误是当用户程序使用log4j并导入名为"slf4j-log4j12"的类时。该程序抱怨有多个slf4j实例,然后死亡。通过从项目中删除"slf4j-log4j12"maven库,它可以正常工作。

最新更新