1

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

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

任何有关以编程方式创建的 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);
   }
}
4

1 回答 1

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。请记住(根据我上面的评论)为每个过滤器、附加器、编码器、滚动策略、评估器以及您在以编程方式初始化 logback 实例时创建的任何其他内容运行 start() 方法。如果你不这样做,它就行不通。

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

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

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

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

于 2014-06-16T15:09:47.223 回答