동적으로 log4j 로그 레벨 변경


127

log4j 로그 레벨을 동적으로 변경하여 응용 프로그램을 재배치 할 필요가없는 다른 접근법은 무엇입니까? 이 경우 변경 사항이 영구적입니까?




3
log4j2에 대한 업데이트 된 질문 : stackoverflow.com/questions/23434252/…
slaadvak

1
이 페이지의 (거의) 모든 것은 log4j2가 아니라 log4j에 관한 것입니다. 이 전체 페이지는 혼동과 오해로 가득하여 유용합니다. @slaadvak이 권장하는대로 stackoverflow.com/questions/23434252/… 로 이동하십시오 .
Lambart

답변:


86

로그 레벨 변경은 간단합니다. 구성의 다른 부분을 수정하면 더 깊이 접근 할 수 있습니다.

LogManager.getRootLogger().setLevel(Level.DEBUG);

변화는 생명주기를 통해 영구적입니다 Logger 입니다. 재 초기화시 구성을 읽고 런타임시 레벨을 설정하는 것으로 레벨 변경이 지속되지 않습니다.

업데이트 : Log4j 2를 사용하는 경우 구현 클래스를 통해 달성 할 수 있으므로 설명서setLevel 당 호출을 제거해야합니다 .

logger.setLevel () 또는 이와 유사한 메소드에 대한 호출은 API에서 지원되지 않습니다. 응용 프로그램은이를 제거해야합니다. 동등한 기능이 Log4j 2 구현 클래스에 제공되지만 응용 프로그램이 Log4j 2 내부의 변경에 영향을받을 수 있습니다.


5
런타임 종속성에만 해당LogManager.getLogger(Class.forName("org.hibernate.util.JDBCExceptionReporter")).setLevel(Level.FATAL);
CelinHC

8
log4j 2 API는 "setLevel"메소드를 제공하지 않습니다.
ChrisCantrell

5
그러나 이것은 루트 로거 만 설정합니까? 루트 아래의 로거에 대해 개별 레벨이 설정된 경우 루트 로거를 설정해도 해당 로거에는 영향을 미치지 않습니다. root.getLoggerRepository (). getCurrentCategories ()와 같은 작업을 수행 할 필요가 없습니까? 로거의 각 인스턴스를 반복하고 각 로거에 대해 LEVEL을 설정해야합니까? @AaronMcIver
TheMonkWhoSoldHisCode

8
@ChrisCantrell Log4j 2 는 그렇게 간단하지는 않지만 이것을 수행하는 방법을 제공합니다 .
CorayThan

2
지정된 간격으로 log4j2.xml 파일 (또는 동등한 파일)을 스캔하여 구성을 새로 고치도록 Log4j2를 구성 할 수 있습니다. 예 : <Configuration status = "warn"monitorInterval = "5"name = "tryItApp"packages = "">
Kimball Robinson

89

파일 감시

Log4j는 log4j.xml파일의 구성 변경 을 감시 할 수 있습니다. log4j 파일을 변경하면 log4j는 변경 사항에 따라 자동으로 로그 수준을 새로 고칩니다. 의 설명서를 참조하십시오org.apache.log4j.xml.DOMConfigurator.configureAndWatch(String,long 하십시오. 확인 사이의 기본 대기 시간은 60 초입니다. 파일 시스템에서 구성 파일을 직접 변경하기 때문에 이러한 변경 사항은 영구적입니다. DOMConfigurator.configureAndWatch ()를 한 번만 호출하면됩니다.

주의 : configureAndWatch 메소드는 스레드 누출로 인해 J2EE 환경에서 사용하기에 안전하지 않습니다.

JMX

로그 레벨 (또는 일반적으로 재구성)을 설정하는 다른 방법은 JMX를 사용하는 것입니다. Log4j는 로거를 JMX MBean으로 등록합니다. 애플리케이션 서버 MBeanServer 콘솔 (또는 JDK의 jconsole.exe)을 사용하여 각 개별 로거를 재구성 할 수 있습니다. 이러한 변경 사항은 영구적이지 않으며 응용 프로그램 (서버)을 다시 시작한 후 구성 파일에 설정된대로 구성으로 재설정됩니다.

스스로 만든

Aaron이 설명한대로 프로그래밍 방식으로 로그 수준을 설정할 수 있습니다. 원하는 방식으로 응용 프로그램에서 구현할 수 있습니다. 예를 들어, 사용자 또는 관리자가 로그 레벨을 변경 setLevel()하고 로거 에서 메소드 를 호출하는 GUI가있을 수 있습니다 . 당신이 설정을 어딘가에 유지할지 여부는 당신에게 달려 있습니다.


8
log4j 워치 독 접근 방식에 대한주의 사항 : "configureAndWatch는 별도의 워치 독 스레드를 시작하므로 log4j 1.2에서이 스레드를 중지 할 방법이 없기 때문에 configureAndWatch 메소드는 애플리케이션이 재활용되는 J2EE 환경에서 사용하기에 안전하지 않습니다." 참조 : Log4J FAQ
Somu

Log4j의 configureAndWatch 기능을 사용한다면 EJB의 @PostDestroy 메소드에서 워치 독 스레드를 멈출 수 있습니다 (컨테이너가 종료되는 시점을 나타내는 충분한 지표입니다). 아니면 내가 빠진 것이 더 있습니다 ..!
Robin Bajaj

미안 해요 의미 @PreDestroy 방법
로빈 바자

" Log4j는 로거를 JMX MBean으로 등록합니다. ". 내 서블릿은 log4j 1.2를 사용합니다. log4j MBean이 표시되지 않습니다.
Abdull

DOMConfigurator.configureAndWatch ()를 한 번만 호출하면됩니다. 어떻게하면 되나요?
gstackoverflow

5

지정된 간격으로 log4j 2 .xml 파일 (또는 동등한 파일) 을 스캔하여 구성을 새로 고치도록 Log4j2를 구성 할 수 있습니다 . " monitorInterval "매개 변수를 구성 태그에 추가하십시오 . 마지막 log 이벤트 이후 5 초 이상 지난 경우 log4j가 구성을 다시 스캔하도록 지시 하는 샘플 log4j 2 .xml 파일의 2 행을 참조하십시오 .

<?xml version="1.0" encoding="UTF-8" ?>
<Configuration status="warn" monitorInterval="5" name="tryItApp" packages="">

    <Appenders>
        <RollingFile name="MY_TRY_IT"
                     fileName="/var/log/tryIt.log"
                     filePattern="/var/log/tryIt-%i.log.gz">
            <Policies>
                <SizeBasedTriggeringPolicy size="25 MB"/>
            </Policies>
            ...
        </RollingFile>
    </Appenders>


    <Loggers>
        <Root level="error">
            <AppenderRef ref="MY_TRY_IT"/>
        </Root>
    </Loggers>

</Configuration>

Tomcat 인스턴스, IDE 내부 또는 스프링 부트를 사용하는 경우이 작업을 수행하기위한 추가 단계가 있습니다. 그것은 다소 범위를 벗어난 것으로 보이며 아마도 별도의 질문이있을 것입니다.


@ vsingh, 스프링 부트, Tomcat 또는 컨테이너 내부 또는 IDE를 배포합니까? 경우에 따라 log4j2의 결함이 아닌 추가 단계가있을 수 있습니다. 기본적으로 앱은 파일이 프레임 워크 또는 도구에 의해 다른 위치로 복사되어 파일이 변경되는 것을 볼 수 없습니다.
킴볼 로빈슨

안녕하세요 .Jboss6.4에서 이것을 테스트했으며 app이 파일을 볼 수있는 위치 (.war 파일 내부)에서 log4j2 구성 파일을 업데이트했습니다. 그러나 여전히 작동하지 않았습니다. 어떠한 제안?
MidTierDeveloper

3

이 답변은 로깅 수준을 동적으로 변경하는 데 도움이되지 않습니다. 서비스를 다시 시작 해야하는 경우 서비스를 다시 시작 해야하는 경우 아래 솔루션을 사용하십시오

나는 log4j 로그 레벨을 변경하기 위해 이것을했고 그것은 나를 위해 일했다. 나는 어떤 문서도 언급하지 않았다. 이 시스템 특성 값을 사용하여 로그 파일 이름을 설정했습니다. 로깅 수준을 설정하기 위해 동일한 기술을 사용했으며 효과가있었습니다.

이것을 JVM 매개 변수로 전달했습니다 (Java 1.7을 사용합니다)

이로 인해 로깅 수준이 동적으로 변경되지는 않으므로 서비스를 다시 시작해야합니다.

java -Dlogging.level=DEBUG -cp xxxxxx.jar  xxxxx.java

log4j.properties 파일 에서이 항목을 추가했습니다.

log4j.rootLogger=${logging.level},file,stdout

나는 시도했다

 java -Dlogging.level=DEBUG -cp xxxxxx.jar  xxxxx.java
 java -Dlogging.level=INFO-cp xxxxxx.jar  xxxxx.java
 java -Dlogging.level=OFF -cp xxxxxx.jar  xxxxx.java

모두 효과가있었습니다. 도움이 되었기를 바랍니다!

내 pom.xml에 다음과 같은 종속성이 있습니다.

<dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
</dependency>

<dependency>
    <groupId>log4j</groupId>
    <artifactId>apache-log4j-extras</artifactId>
    <version>1.2.17</version>
</dependency>

2
언급 한 것은 괜찮은 것처럼 보이지만 문제는 로깅 수준을 동적으로 변경하는 것입니다.
Azim

이렇게하려면 서비스를 다시 시작해야합니다. 로깅 수준은 동적으로 변경되지 않습니다.
kk.

2

log4j 1.x에서는 DOMConfigurator를 사용하여 사전 정의 된 XML 로그 구성 세트 중 하나 (예 : 일반적인 용도 및 디버깅 용)를 제출하는 것이 가장 좋습니다.

이것들을 사용하는 것은 다음과 같이 할 수 있습니다 :

  public static void reconfigurePredefined(String newLoggerConfigName) {
    String name = newLoggerConfigName.toLowerCase();
    if ("default".equals(name)) {
      name = "log4j.xml";
    } else {
      name = "log4j-" + name + ".xml";
    }

    if (Log4jReconfigurator.class.getResource("/" + name) != null) {
      String logConfigPath = Log4jReconfigurator.class.getResource("/" + name).getPath();
      logger.warn("Using log4j configuration: " + logConfigPath);
      try (InputStream defaultIs = Log4jReconfigurator.class.getResourceAsStream("/" + name)) {
        new DOMConfigurator().doConfigure(defaultIs, LogManager.getLoggerRepository());
      } catch (IOException e) {
        logger.error("Failed to reconfigure log4j configuration, could not find file " + logConfigPath + " on the classpath", e);
      } catch (FactoryConfigurationError e) {
        logger.error("Failed to reconfigure log4j configuration, could not load file " + logConfigPath, e);
      }
    } else {
      logger.error("Could not find log4j configuration file " + name + ".xml on classpath");
    }
  }

적절한 구성 이름으로 이것을 호출하고 템플릿을 클래스 경로에 넣었는지 확인하십시오.


이 방법의 시작점은 무엇입니까? log4j 구성이 변경 될 때 마다이 메소드를 호출해야한다는 것을 어떻게 알 수 있습니까?
ass

나는 여전히 "주문형"이라는 의미를 얻지 못합니다. 이 방법을 연결하는 스 니펫을 보여 주시겠습니까?
asg

2
여기 있습니다 : 컨트롤러가 사용하는 스 니펫입니다. 동적으로 로깅을 재구성 할 수있는 링크가있는 관리자 페이지가 있습니다. 그러면 / admin / setLogLevel? level = Error 링크로 GET을 생성 한 다음 컨트롤러에서 @RequestMapping (value = "setLogLevel", method = RequestMethod.GET) public ModelAndView setLogLevel (@RequestParam (value = "level", required = true) 문자열 수준) {Log4jReconfigurator.reconfigureExisting (level);
ISparkes

따라서 "주문형"은 제 경우 "사용자가 버튼을 클릭 할 때"를 의미합니다
ISparkes

아, 잡았다 따라서 관리 콘솔은이 메소드를 호출하도록 요청해야합니다.
ass

0

"org.apache.http"로그의 세부 정보를 줄이기 위해이 방법을 성공적으로 사용했습니다.

ch.qos.logback.classic.Logger logger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger("org.apache.http");
logger.setLevel(Level.TRACE);
logger.setAdditive(false);

0

log4j 2 API의 경우 다음을 사용할 수 있습니다

Logger logger = LogManager.getRootLogger();
Configurator.setAllLevels(logger.getName(), Level.getLevel(level));

-1

모든 로거의 로깅 수준을 변경하려면 아래 방법을 사용하십시오. 모든 로거를 열거하고 로깅 수준을 지정된 수준으로 변경합니다. 당신이 있는지 확인하십시오 하지 마십시오log4j.appender.loggerName.Threshold=DEBUG당신의 속성이 설정 log4j.properties파일.

public static void changeLogLevel(Level level) {
    Enumeration<?> loggers = LogManager.getCurrentLoggers();
    while(loggers.hasMoreElements()) {
        Logger logger = (Logger) loggers.nextElement();
        logger.setLevel(level);
    }
}

-3

다음 코드 스 니펫을 사용할 수 있습니다

((ch.qos.logback.classic.Logger)LoggerFactory.getLogger(packageName)).setLevel(ch.qos.logback.classic.Level.toLevel(logLevel));

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