以编程方式配置Log4j记录器

IAm*_*aja 183 java logging log4j slf4j

我是log4j第一次尝试使用SLF4J(带绑定).

我想配置3个不同的名为Logger,它们可以由LoggerFactory返回,它将记录不同的级别并将消息推送到不同的appender:

  • 记录器1"FileLogger"记录DEBUG并附加到 DailyRollingFileAppender
  • 记录器2"TracingLogger"记录TRACE +并附加到a JmsAppender
  • 记录器3"ErrorLogger"记录ERROR +并附加到其他变量 JmsAppender

此外,我希望它们以编程方式配置(在Java中,而不是XML或log4j.properties文件).

我想,通常情况下,我会Logger在某些引导代码中将它们定义为某个init()方法,就像方法一样.但是,因为我想使用slf4j-log4j,我很困惑我可以在哪里定义记录器并使它们可用于类路径.

我不认为这违反了SLF4J的基本目的(作为一个外观),因为我使用SLF4J API的代码永远不会知道这些记录器存在.我的代码只是对SLF4J API进行正常调用,然后将它们转发到它在类路径上找到的log4j Loggers.

但是如何在类路径中配置那些log4j记录器...在Java中?!

oer*_*ers 273

您可以通过编程方式向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
Run Code Online (Sandbox Code Playgroud)

我建议你把它放在一个init()的某个地方,你确定,这将在其他任何事情之前执行.然后,您可以删除根记录器上的所有现有appender

 Logger.getRootLogger().getLoggerRepository().resetConfiguration();
Run Code Online (Sandbox Code Playgroud)

并开始添加自己的.当然,您需要在类路径中使用log4j才能使用它.

备注:
您可以随意Logger.getLogger(...)添加任何appender.我只是拿了根记录器,因为它位于所有东西的底部,并将处理通过其他类别中的其他appender传递的所有内容(除非通过设置additivity标志另外配置).

如果您需要了解日志记录的工作原理以及如何确定日志的编写位置,请阅读本手册以获取更多信息.
简而言之:

  Logger fizz = LoggerFactory.getLogger("com.fizz")
Run Code Online (Sandbox Code Playgroud)

会给你一个"com.fizz"类别的记录器.
对于上面的示例,这意味着使用它记录的所有内容都将被引用到根记录器上的控制台和文件追加器.
如果你将一个appender添加到Logger.getLogger("com.fizz").addAppender(newAppender),那么登录fizz将由来自root logger的appender和newAppender.
您不使用配置创建记录器,只需为系统中的所有可能类别提供处理程序.

  • @AdamTannon您可以选择任何您喜欢的Logger.getLogger(...).我只是拿了根记录器,因为它位于所有东西的底部,并将处理通过其他类别中的其他appender传递的所有内容(除非另有配置).[见记录器层次结构](https://logging.apache.org/log4j/1.2/manual.html) (3认同)
  • 谢谢你!快速问题 - 我注意到你正在将追加器添加到根Logger中.是否有一个原因? (2认同)
  • oers - 我很感激你的精彩反馈,但我没有在这里连接所有的点.您是否可以修改您的示例以显示添加新的Logger(不是根记录器),一旦添加到系统中,它将可用于要求它的任何其他类?例如,通常可以通过"Logger fizz = LoggerFactory.getLogger("com.fizz")访问的Logger;`谢谢! (2认同)

IAm*_*aja 45

听起来你正试图从"两端"(消费者端和配置端)使用log4j.

如果你想编写针对SLF4J API,但提前确定(和编程)log4j的记录仪的配置的类路径返回,你绝对必须有某种记录适应的,这使得使用延迟建设.

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);
    }
Run Code Online (Sandbox Code Playgroud)

使用此方法,您无需担心log4j记录器的配置位置/时间.类路径第一次要求它们时,它们被懒惰地构造,传回并通过slf4j提供.希望这有帮助!

  • 搞定了!非常感谢您提供有用的示例!@Oers - 谢谢你试图引导我朝着正确的方向前进 - 我会给你绿色检查你的奉献精神但是必须给zharvey赏金,因为它正是我想要的.再次感谢大家! (2认同)

iam*_*hek 7

如果有人想用 Java 以编程方式配置 log4j2,那么此链接可能会有所帮助:(https://www.studytonight.com/post/log4j2-programmatic-configuration-in-java-class )

以下是配置控制台 Appender 的基本代码:

ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();

builder.setStatusLevel(Level.DEBUG);
// naming the logger configuration
builder.setConfigurationName("DefaultLogger");

// create a console appender
AppenderComponentBuilder appenderBuilder = builder.newAppender("Console", "CONSOLE")
                .addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
// add a layout like pattern, json etc
appenderBuilder.add(builder.newLayout("PatternLayout")
                .addAttribute("pattern", "%d %p %c [%t] %m%n"));
RootLoggerComponentBuilder rootLogger = builder.newRootLogger(Level.DEBUG);
rootLogger.add(builder.newAppenderRef("Console"));

builder.add(appenderBuilder);
builder.add(rootLogger);
Configurator.reconfigure(builder.build());
Run Code Online (Sandbox Code Playgroud)

这将重新配置默认的rootLogger创建一个新的appender