프로그래밍 방식으로 Log4j 로거 구성


191

SLF4J ( log4j바인딩 포함)를 처음으로 사용하려고합니다 .

LoggerFactory가 반환 할 수있는 3 개의 다른 명명 된 Logger를 구성하고 싶습니다.

  • 로거 1 "FileLogger"는 DEBUG를 기록하고 추가합니다. DailyRollingFileAppender
  • 로거 2 "TracingLogger"는 TRACE +를 기록하고 JmsAppender
  • 로거 3 "ErrorLogger"는 ERROR +를 기록하고 다른 오류에 추가합니다. JmsAppender

또한 프로그래밍 방식으로 구성하기를 원합니다 (XML 또는 log4j.properties파일이 아닌 Java로 ).

나는 일반적으로 메소드 Logger와 같은 부트 스트랩 코드의 어딘가에 이들을 정의한다고 생각합니다 init(). 그러나을 사용하고 싶기 때문에 slf4j-log4j로거를 정의하고 클래스 경로에서 사용할 수있는 위치에 대해 혼란 스럽습니다.

SLF4J API를 사용하는 코드가 이러한 로거가 존재한다는 것을 알 수 없기 때문에 이것이 SLF4J의 기본 목적 (외관)을 위반 한다고 생각 하지 않습니다 . 내 코드는 SLF4J API를 정상적으로 호출 한 다음 클래스 경로에서 찾은 log4j 로거로 전달합니다.

그러나 Java의 클래스 경로에서 log4j 로거를 어떻게 구성합니까?!



3
log4j 1.x의 경우 2.x에 대해 아래의 허용 된 대답을 사용하십시오. logging.apache.org/log4j/2.x/manual/customconfig.html
earcam

답변:


279

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(...). 루트 로거는 모든 것의 맨 아래에 있기 때문에 루트 로거를 가져 갔으며 (추가 플래그를 설정하여 다르게 구성되지 않는 한) 다른 카테고리의 다른 어 펜더를 통해 전달되는 모든 것을 처리합니다.

로깅 작동 방식과 로그 작성 위치를 결정해야하는 경우이 매뉴얼읽고 이에 대한 자세한 정보를 확인하십시오.
한마디로 :

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

"com.fizz"범주에 대한 로거를 제공합니다.
위의 예에서 이것은 로그 된 모든 것이 루트 로거의 콘솔 및 파일 어 펜더에 의해 참조됨을 의미합니다.
Logger.getLogger ( "com.fizz"). addAppender (newAppender) fizz에 어 펜더를 추가하면 루트 로거 및의 어 펜더가 aller에 의해 로그인을 처리합니다 newAppender.
구성을 사용하여 로거를 작성하지 않고 시스템의 모든 가능한 카테고리에 대한 핸들러 만 제공합니다.


2
고마워요! 빠른 질문-어 펜더를 루트 로거에 추가하는 것으로 나타났습니다. 이것에 대한 이유가 있습니까?
IAmYourFaja

그리고 더 중요한 것은 SLF4J의 LoggerFactory에서 검색 할 로거를 지정해야합니다. SLF4J에 log4j의 루트 로거를 요청할 수 있습니까?
IAmYourFaja

3
@AdamTannon 원하는 Logger.getLogger (...)를 사용할 수 있습니다. 루트 로거는 모든 것의 맨 아래에 있기 때문에 루트 로거를 가져 갔으며 다른 범주의 다른 어 펜더를 통해 전달되는 모든 것을 처리합니다 (달리 구성되지 않은 한). 로거 계층보기
oers

@AdamTannon 당신은 log4j 루트 로거를 얻기 위해 sl4j 팩토리를 사용할 수 없습니다. SL4j는 로깅 외관입니다. log4j와 관련된 것은 없습니다.
oers

2
oers-귀하의 훌륭한 의견에 감사하지만 여기에 모든 점을 연결하지는 않습니다. 시스템에 한 번 추가 된 새로운 로거 (루트 로거가 아님)를 추가하도록 표시하도록 예제를 수정할 수 있습니까? 예를 들어, 일반적으로 Logger fizz = LoggerFactory.getLogger("com.fizz");감사합니다!
IAmYourFaja

47

"모두 끝"(소비자 끝 및 구성 끝)에서 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를 통해 사용할 수있게됩니다. 이것이 도움이 되었기를 바랍니다!


2
못을 박았다! 유용한 예를 주셔서 대단히 감사합니다! @Oers-올바른 방향으로 나를 조종 해주셔서 감사합니다-나는 당신에게 헌신에 대한 녹색 체크를 줄 것이지만 zharvey에게 현상금을 주어야합니다. 다시 한번 감사합니다!
IAmYourFaja

4

log4j 특성에서 어 펜더를 정의하고이를 프로그래밍 방식으로 업데이트하려는 경우 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);

1

누군가가 프로그래밍 방식으로 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생성합니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.