以编程方式configurationLog4jlogging器
我正在尝试第一次使用SLF4J(与log4j
绑定)。
我想configuration3个不同的Logger,它们可以被LoggerFactory返回,LoggerFactory会logging不同的级别,并将消息推送给不同的appender:
- logging器1“FileLogger”loggingDEBUG
DailyRollingFileAppender
- logging器2“TracingLogger”loggingTRACE +
JmsAppender
- logging器3“ErrorLogger”loggingERROR +
JmsAppender
加到不同的JmsAppender
此外,我希望他们configuration编程(在Java中,而不是XML或log4j.properties
文件)。
我想,通常我会在某些引导代码中的某处init()
如init()
方法init()
定义这些Logger
。 但是,因为我想使用slf4j-log4j
,所以我很困惑我可以在哪里定义logging器,并将它们提供给类path。
我不相信这是违反SLF4J的底层目的(作为一个门面),因为我使用SLF4J API的代码不会知道这些logging器存在。 我的代码只是正常调用SLF4J API,然后将它们转发到它在类path中find的log4j Logger。
但是,我怎么configuration这些log4jlogging器在类path…在Java?
您可以以编程方式向Log4j添加/删除Appender:
ConsoleAppender console = new ConsoleAppender(); //create appender //configure the appender String PATTERN = "%d [%p|%c|%C{1}] %m%n"; console.setLayout(new PatternLayout(PATTERN)); console.setThreshold(Level.FATAL); console.activateOptions(); //add appender to any Logger (here is root) Logger.getRootLogger().addAppender(console); FileAppender fa = new FileAppender(); fa.setName("FileLogger"); fa.setFile("mylog.log"); fa.setLayout(new PatternLayout("%d %-5p [%c{1}] %m%n")); fa.setThreshold(Level.DEBUG); fa.setAppend(true); fa.activateOptions(); //add appender to any Logger (here is root) Logger.getRootLogger().addAppender(fa); //repeat with all other desired appenders
我build议你把它放在一个init()的地方,你可以肯定的是,这将在其他任何事情之前执行。 然后,您可以删除根logging器上的所有现有appender
Logger.getRootLogger().getLoggerRepository().resetConfiguration();
并开始添加自己的。 当然你需要在classpath中使用log4j来工作。
备注:
你可以使用任何你喜欢的Logger.getLogger(...)
来添加appender。 我只是把根logging器,因为它在所有事情的底部,并将处理通过其他类别的其他appender传递的一切(除非通过设置可加性标志另有configuration)。
如果您需要了解日志如何工作以及如何确定日志的写入方式,请阅读本手册以获取更多信息。
简而言之:
Logger fizz = LoggerFactory.getLogger("com.fizz")
会给你一个“com.fizz”类别的logging器。
对于上面的例子,这意味着所有logging的东西都会被引用到根logging器上的控制台和文件appender。
如果你添加一个appender到Logger.getLogger(“com.fizz”)。addAppender(newAppender),那么从fizz
logging将被从根logging器和newAppender
的appender处理。
您不需要使用configuration创buildlogging器,只需在系统中为所有可能的类别提供处理程序。
这听起来像你试图从“两端”(消费者端和configuration端)使用log4j。
如果你想对slf4j api进行编码,但是要提前确定(以及以编程的方式)log4j Logger的configuration,那么classpath将返回,你必须有一些使用惰性构造的日志logging适配。
public class YourLoggingWrapper { private static boolean loggingIsInitialized = false; public YourLoggingWrapper() { // ...blah } public static void debug(String debugMsg) { log(LogLevel.Debug, debugMsg); } // Same for all other log levels your want to handle. // You mentioned TRACE and ERROR. private static void log(LogLevel level, String logMsg) { if(!loggingIsInitialized) initLogging(); org.slf4j.Logger slf4jLogger = org.slf4j.LoggerFactory.getLogger("DebugLogger"); switch(level) { case: Debug: logger.debug(logMsg); break; default: // whatever } } // log4j logging is lazily constructed; it gets initialized // the first time the invoking app calls a log method private static void initLogging() { loggingIsInitialized = true; org.apache.log4j.Logger debugLogger = org.apache.log4j.LoggerFactory.getLogger("DebugLogger"); // Now all the same configuration code that @oers suggested applies... // configure the logger, configure and add its appenders, etc. debugLogger.addAppender(someConfiguredFileAppender); }
采用这种方法,您无需担心log4jlogging器的configuration位置/时间。 classpath第一次要求他们,他们得到了懒散的构造,通过slf4j传回。 希望这有助于!
如果您已经在log4j属性中定义了一个appender,并且希望以编程方式更新它,请在log4j属性中设置该名称并按名称获取该名称。
这是一个log4j.properties条目的例子:
log4j.appender.stdout.Name=console log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.Threshold=INFO
要更新它,请执行以下操作:
((ConsoleAppender) Logger.getRootLogger().getAppender("console")).setThreshold(Level.DEBUG);