制作Logback审计记录器包装器

时间:2014-06-10 14:26:08

标签: logging logback audit-logging programmatically-created

我正在编写一个用作Logback Logger包装器的类。特别是它有助于审计日志记录。它应该是一个人们应该能够导入和使用的独立库。我所遇到的问题与用于以编程方式声明LogBack的最少量文档有关。我基于另一个堆栈溢出问题(Setting Logback Appender path programmatically)的一般声明。

我目前的定义如下。目前我无法让Marker过滤器工作。看起来像标记过滤器,正如我所宣称的那样,并没有做任何事情。最后,我想确保除了审计日志记录之外没有其他信息进入审计日志文件。这就是为什么我在不匹配时拒绝它。从我的测试来看,它似乎被忽略了。

非常感谢有关以编程方式创建的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);
   }
}

1 个答案:

答案 0 :(得分:0)

我从来没有找到关于以编程方式创建的Logback文件的大量信息,但我会分享我从测试中找到的内容和摆弄的内容。

首先,为了适应Ceki对链接帖子的响应,我使用了logback.xml示例和在线API的组合。例如,为了找到如何进行标记过滤器,我注意到xml有一个指向类“ch.qos.logback.core.filter.EvaluatorFilter”和“ch.qos.logback.classic.boolex.OnMarkerEvaluator”的链接”。我使用了此处的API:http://logback.qos.ch/apidocs/ch/qos/logback/core/filter/EvaluatorFilter.html。请记住(根据我上面的评论)为每个过滤器,appender,编码器,滚动策略,评估程序以及以编程方式初始化logback实例时创建的任何其他内容运行start()方法。如果你不这样做就行不通。

至于我使用编程创建和xml创建的logback实例的不同组合进行的测试,我得到了有趣的结果。看起来像以编程方式创建的logback实例和由xml创建的实例一起工作。例如,如果我从编程创建的实例中调用logger.debug(“msg”),那么xml创建的实例也将接收并评估“msg”。我相信这是因为他们都拥有相同的“根”记录器。

为了让用户不使用logback并且不输出到控制台时库正常工作,我使用下面的代码。它检查默认记录器是否是唯一存在的记录器,如果是,则删除控制台appender。

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

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