以编程方式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),那么从fizzlogging将被从根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);