簡體   English   中英

以編程方式配置 Log4j 記錄器

[英]Configuring Log4j Loggers Programmatically

我第一次嘗試使用 SLF4J(帶有log4j綁定)。

我想配置 3 個不同的命名記錄器,它們可以由 LoggerFactory 返回,它將記錄不同的級別並將消息推送到不同的附加程序:

  • Logger 1 "FileLogger" 記錄 DEBUG DailyRollingFileAppender
  • Logger 2 "TracingLogger" 記錄 TRACE+ JmsAppender
  • Logger 3 "ErrorLogger" 記錄 ERROR+ JmsAppender加到不同的JmsAppender

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

我想,通常,我會在一些引導代碼的某處定義這些Logger ,比如init()方法。 但是,因為我想使用slf4j-log4j ,所以我對在哪里可以定義記錄器並使它們可用於類路徑感到困惑。

我不認為這違反了 SLF4J 的基本目的(作為外觀),因為我使用 SLF4J API 的代碼永遠不會知道這些記錄器的存在。 我的代碼只是對 SLF4J API 進行正常調用,然后將它們轉發到它在類路徑上找到的 log4j 記錄器。

但是我如何在類路徑上配置那些 log4j 記錄器......在 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

我建議你把它放到一個 init() 某個地方,在那里你可以肯定,這將在其他任何事情之前執行。 然后,您可以刪除根記錄器上的所有現有 appender

 Logger.getRootLogger().getLoggerRepository().resetConfiguration();

並開始添加您自己的。 您當然需要在類路徑中使用 log4j 才能使其工作。

評論:
你可以使用任何你喜歡的Logger.getLogger(...)添加 appender。 我只是使用了根記錄器,因為它位於所有事物的底部,並且將處理通過其他類別中的其他附加程序傳遞的所有內容(除非通過設置可加性標志進行了其他配置)。

如果您需要了解日志記錄的工作原理以及如何決定日志的寫入位置,請閱讀本手冊以獲取更多相關信息。
簡而言之:

  Logger fizz = LoggerFactory.getLogger("com.fizz")

將為您提供“com.fizz”類別的記錄器。
對於上面的示例,這意味着用它記錄的所有內容都將被引用到根記錄器上的控制台和文件附加器。
如果您向 Logger.getLogger("com.fizz").addAppender(newAppender) 添加一個 appender,那么來自fizz日志將由根記錄器和newAppender的所有 appender 處理。
您無需使用配置創建記錄器,您只需為系統中所有可能的類別提供處理程序。

聽起來您正在嘗試從“兩端”(消費者端和配置端)使用 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);
    }

使用這種方法,您無需擔心在何處/何時配置 log4j 記錄器。 類路徑第一次請求它們時,它們會被懶惰地構造、傳回並通過 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);

如果有人來尋找在 Java 中以編程方式配置 log4j2,那么此鏈接可能會有所幫助:( https://www.studytonight.com/post/log4j2-programmatic-configuration-in-java-class

以下是配置 Console 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());

這將重新配置默認的rootLogger並且還將創建一個新的 appender

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM