Cấu hình Log4j Loggers lập trình


189

Tôi đang cố gắng sử dụng SLF4J (có log4jràng buộc) lần đầu tiên.

Tôi muốn cấu hình 3 Logger có tên khác nhau có thể được trả về bởi LoggerFactory, nó sẽ ghi lại các cấp độ khác nhau và đẩy các thông báo đến các appender khác nhau:

  • Logger 1 "FileLogger" ghi nhật ký DEBUG và nối vào DailyRollingFileAppender
  • Logger 2 "TraceLogger" ghi nhật ký TRACE + và nối thêm vào JmsAppender
  • Logger 3 "ErrorLogger" ghi nhật ký ERROR + và nối thêm vào khác JmsAppender

Hơn nữa, tôi muốn chúng được cấu hình theo chương trình (bằng Java, trái ngược với XML hoặc log4j.propertiestệp).

Tôi tưởng tượng rằng, thông thường, tôi sẽ định nghĩa những cái này Loggerở đâu đó trong một số mã bootstrapping, giống như một init()phương thức. Tuy nhiên, vì tôi muốn sử dụng slf4j-log4j, tôi bối rối về nơi tôi có thể định nghĩa logger và làm cho chúng có sẵn cho đường dẫn lớp.

Tôi không tin rằng điều này vi phạm mục đích cơ bản của SLF4J (như một mặt tiền), bởi vì mã của tôi sử dụng API SLF4J sẽ không bao giờ biết rằng các logger này tồn tại. Mã của tôi chỉ thực hiện các cuộc gọi bình thường tới API SLF4J, sau đó chuyển tiếp chúng tới log4j Loggers mà nó tìm thấy trên đường dẫn lớp.

Nhưng làm cách nào để định cấu hình các logger log4j trên đường dẫn lớp ... trong Java?!



3
Đối với log4j 1.x sử dụng câu trả lời được chấp nhận dưới đây để biết 2.x see logging.apache.org/log4j/2.x/manual/customconfig.html
earcam

Câu trả lời:


277

Bạn có thể thêm / xóa Appender theo chương trình vào Log4j:

  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

Tôi khuyên bạn nên đặt nó vào một init () ở đâu đó, nơi bạn chắc chắn, rằng điều này sẽ được thực thi trước bất cứ điều gì khác. Sau đó, bạn có thể xóa tất cả các appender hiện có trên logger gốc với

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

và bắt đầu với việc thêm của riêng bạn. Bạn cần log4j trong classpath tất nhiên để làm việc này.

Ghi chú:
Bạn có thể lấy bất kỳ thứ gì Logger.getLogger(...)bạn muốn để thêm phần bổ sung. Tôi chỉ lấy logger gốc vì nó ở dưới cùng của tất cả mọi thứ và sẽ xử lý tất cả mọi thứ được chuyển qua các appender khác trong các danh mục khác (trừ khi được cấu hình khác bằng cách đặt cờ nghiện).

Nếu bạn cần biết cách ghi nhật ký hoạt động và cách quyết định nơi ghi nhật ký, hãy đọc hướng dẫn này để biết thêm thông tin về điều đó.
Nói ngắn gọn:

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

sẽ cung cấp cho bạn một logger cho danh mục "com.fizz".
Đối với ví dụ trên, điều này có nghĩa là mọi thứ được ghi lại sẽ được chuyển đến giao diện điều khiển và tệp trên trình ghi nhật ký gốc.
Nếu bạn thêm một appender vào Logger.getLogger ("com.fizz"). AddAppender (newAppender) thì việc đăng nhập từ fizzsẽ được xử lý bởi alle các appender từ root logger và newAppender.
Bạn không tạo Loggers với cấu hình, bạn chỉ cung cấp trình xử lý cho tất cả các danh mục có thể có trong hệ thống của bạn.


2
Cảm ơn oers! Câu hỏi nhanh - Tôi nhận thấy bạn đang thêm các phần bổ sung vào Logger gốc. Có một lý do cho điều này?
IAmYourFaja

Và, quan trọng hơn, tôi sẽ cần chỉ định Logger nào sẽ lấy từ LoggerFactory của SLF4J. Có thể yêu cầu SLF4J cho logger gốc của log4j không?
IAmYourFaja

3
@AdamTannon Bạn có thể lấy bất kỳ Logger.getLogger (...) nào bạn thích. Tôi chỉ lấy logger gốc vì nó ở dưới cùng của tất cả mọi thứ và sẽ xử lý tất cả mọi thứ được chuyển qua các appender khác trong các danh mục khác (trừ khi được cấu hình khác). Xem hệ thống phân cấp logger
oers

@AdamTannon bạn không thể sử dụng nhà máy sl4j để lấy logger log4j. SL4j là một mặt tiền đăng nhập. Bạn sẽ không nhận được bất cứ điều gì log4j cụ thể từ nó.
oers

2
oers - Tôi đánh giá cao phản hồi tuyệt vời của bạn, nhưng tôi không kết nối tất cả các dấu chấm ở đây. Bạn có thể sửa đổi ví dụ của mình để hiển thị việc bổ sung một Trình ghi nhật ký mới (không phải là trình ghi nhật ký gốc) mà sau khi được thêm vào hệ thống, sẽ có sẵn cho bất kỳ lớp nào khác yêu cầu không? Ví dụ, một Logger thường được truy cập bởi, nói, Logger fizz = LoggerFactory.getLogger("com.fizz");Cảm ơn!
IAmYourFaja

47

Có vẻ như bạn đang cố gắng sử dụng log4j từ "cả hai đầu" (kết thúc của người tiêu dùng và kết thúc cấu hình).

Nếu bạn muốn mã hóa với slf4j api nhưng xác định trước (và lập trình) cấu hình của Log4j Loggers mà classpath sẽ trả về, bạn hoàn toàn phải có một số loại thích ứng ghi nhật ký sử dụng việc xây dựng lười biếng.

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);
    }

Với phương pháp này, bạn không cần phải lo lắng về nơi / khi logger log4j của bạn được cấu hình. Lần đầu tiên classpath yêu cầu chúng, chúng được xây dựng một cách uể oải, được trả lại và được cung cấp qua slf4j. Hy vọng điều này sẽ giúp!


2
Đóng đinh nó! Cảm ơn bạn rất nhiều cho một ví dụ hữu ích! @Oers - cảm ơn bạn đã cố gắng điều khiển tôi đi đúng hướng - Tôi sẽ cung cấp cho bạn kiểm tra màu xanh lá cây cho sự cống hiến của bạn nhưng phải đưa zharvey tiền thưởng vì đó chính xác là những gì tôi đang tìm kiếm. Cảm ơn mọi người một lần nữa!
IAmYourFaja

4

Trong trường hợp bạn đã xác định một appender trong thuộc tính log4j và muốn cập nhật nó theo chương trình, hãy đặt tên trong thuộc tính log4j và lấy tên theo tên.

Dưới đây là một ví dụ mục nhập log4j.properIES:

log4j.appender.stdout.Name=console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.Threshold=INFO

Để cập nhật nó, hãy làm như sau:

((ConsoleAppender) Logger.getRootLogger().getAppender("console")).setThreshold(Level.DEBUG);

1

Nếu ai đó tìm cách định cấu hình log4j2 bằng Java, thì liên kết này có thể giúp: ( https://www.studytonight.com/post/log4j2-programmatic-configuration-in-java- class )

Đây là mã cơ bản để cấu hình 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());

Điều này sẽ cấu hình lại rootLogger mặc định và cũng sẽ tạo ra một appender mới .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.