我正在编写一个类,作为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库,它可以正常工作。