slf4j에서 런타임시 메시지의 로그 수준 설정


100

log4j를 사용하는 경우 Logger.log(Priority p, Object message)메서드를 사용할 수 있으며 런타임에 결정된 로그 수준에서 메시지를 기록하는 데 사용할 수 있습니다. 이 사실 과이 팁 을 사용하여 stderr를 특정 로그 수준의 로거로 리디렉션합니다.

slf4j에는 log()내가 찾을 수 있는 일반적인 방법 이 없습니다 . 위를 구현할 방법이 없다는 의미입니까?


4
dev 메일 링리스트의 slf4j 2.0에 이것을 추가하는 것에 대한 논의가있는 것 같습니다 : qos.ch/pipermail/slf4j-dev/2010-March/002865.html
Edward Dale

1
Marker를 살펴보십시오. 이것은 로그 체인에 전달할 수있는 사용자 지정 데이터입니다.
tuxSlayer 2013-07-15

1
@tuxSlayer이 경우 Marker를 사용하는 방법을 자세히 설명해 주시겠습니까?
비참한 변수

아마도 "로깅"에 대한 최선의 아이디어는 아니지만 로그 항목 "우선 순위"(높음 | 낮음 | 보통, 정보 | 경고 | 치명)에 여러 마커를 사용하고 로그 백 또는 사용자 지정 어 펜더에서 필터링을 사용하여 마커를 사용하고 로그 항목을 구동 할 수 있습니다. 별도의 채널 (로그 정보, 치명적인 이메일 등)에. 그러나 더 직접적인 방법은 아래 답변에서 지적한 것처럼 이에 대한 정면을 갖는 것입니다.
tuxSlayer 2013 년

2
이 기능은의 일부 여야 slf4j 2.0합니다. jira.qos.ch/browse/SLF4J-124 자세한 내용과 가능한 해결 방법 은 내 대답을 참조하십시오 slf4j 1.x.
slartidan

답변:


47

으로이 작업을 수행 할 수있는 방법이 없습니다 slf4j.

이 기능이 누락 된 이유 는 파사드 뒤의 가능한 모든 로깅 구현에서 사용되는 (또는 동등한) 유형에 효율적으로 매핑 될 수 있는 Level유형 을 구성하는 것이 거의 불가능하기 때문이라고 생각합니다 . 또는 설계자들은 귀하의 사용 사례가 이를 지원하는 오버 헤드를 정당화 하기에는 너무 이례적 이라고 결정 했습니다.slf4jLevel

에 관한 @ ripper234사용 사례 (단위 테스트), 나는 실용적인 솔루션은 단위 테스트를 실행할 때 로깅 시스템 ...을 SLF4J 외관 뒤에 무엇의 하드 와이어 지식 단위 테스트 (들)을 수정할 생각합니다.


9
실제로 필요한 매핑이 없습니다. org.slf4j.Loggerdebug, error, info, trace, warn 의 메서드에 의해 이미 암시 적으로 정의 된 5 가지 수준이 있습니다 .
Edward Dale

1
그리고 문제는 무효로 마감되었습니다. 내가 이해하는 한, 그것은 의도적 인 디자인 선택입니다.
ripper234 2010

9
@ ripper234-귀하의 버그가 scompt.com의 원래 질문과 동일한 문제를 해결했다고 생각하지 않습니다. SLF4J API를 통해 기본 로깅 시스템 의 레벨 구성에 대해 질문했습니다 . scompt.com은 SLF4J API의 일반적인 'log'메소드로 메시지 의 로깅 수준 매개 변수로 사용합니다.
Richard Fearn

1
1 @RichardFearn은 하나는 60 초 후에 의견 upvote에 취소 할 수 없습니다 MEH . 그 동안 기능 요청이 존재합니다 : bugzilla.slf4j.org/show_bug.cgi?id=133
1

3
RFE 링크는 더 이상 해결되지 않습니다. 관련 링크는 이제 jira.qos.ch/browse/SLF4J-124jira.qos.ch/browse/SLF4J-197 ...이며 둘 다 닫혔습니다. 근거에 대한 의견을 읽으십시오.
Stephen C

27

Richard Fearn은 올바른 아이디어를 가지고 있으므로 그의 골격 코드를 기반으로 전체 클래스를 작성했습니다. 여기에 게시하기에 충분히 짧기를 바랍니다. 즐거움을 위해 복사 및 붙여 넣기. 마법 주문도 추가해야 할 것 같습니다. "이 코드는 공개 도메인에 공개되었습니다."

import org.slf4j.Logger;

public class LogLevel {

    /**
     * Allowed levels, as an enum. Import using "import [package].LogLevel.Level"
     * Every logging implementation has something like this except SLF4J.
     */

    public static enum Level {
        TRACE, DEBUG, INFO, WARN, ERROR
    }

    /**
     * This class cannot be instantiated, why would you want to?
     */

    private LogLevel() {
        // Unreachable
    }

    /**
     * Log at the specified level. If the "logger" is null, nothing is logged.
     * If the "level" is null, nothing is logged. If the "txt" is null,
     * behaviour depends on the SLF4J implementation.
     */

    public static void log(Logger logger, Level level, String txt) {
        if (logger != null && level != null) {
            switch (level) {
            case TRACE:
                logger.trace(txt);
                break;
            case DEBUG:
                logger.debug(txt);
                break;
            case INFO:
                logger.info(txt);
                break;
            case WARN:
                logger.warn(txt);
                break;
            case ERROR:
                logger.error(txt);
                break;
            }
        }
    }

    /**
     * Log at the specified level. If the "logger" is null, nothing is logged.
     * If the "level" is null, nothing is logged. If the "format" or the "argArray"
     * are null, behaviour depends on the SLF4J-backing implementation.
     */

    public static void log(Logger logger, Level level, String format, Object[] argArray) {
        if (logger != null && level != null) {
            switch (level) {
            case TRACE:
                logger.trace(format, argArray);
                break;
            case DEBUG:
                logger.debug(format, argArray);
                break;
            case INFO:
                logger.info(format, argArray);
                break;
            case WARN:
                logger.warn(format, argArray);
                break;
            case ERROR:
                logger.error(format, argArray);
                break;
            }
        }
    }

    /**
     * Log at the specified level, with a Throwable on top. If the "logger" is null,
     * nothing is logged. If the "level" is null, nothing is logged. If the "format" or
     * the "argArray" or the "throwable" are null, behaviour depends on the SLF4J-backing
     * implementation.
     */

    public static void log(Logger logger, Level level, String txt, Throwable throwable) {
        if (logger != null && level != null) {
            switch (level) {
            case TRACE:
                logger.trace(txt, throwable);
                break;
            case DEBUG:
                logger.debug(txt, throwable);
                break;
            case INFO:
                logger.info(txt, throwable);
                break;
            case WARN:
                logger.warn(txt, throwable);
                break;
            case ERROR:
                logger.error(txt, throwable);
                break;
            }
        }
    }

    /**
     * Check whether a SLF4J logger is enabled for a certain loglevel. 
     * If the "logger" or the "level" is null, false is returned.
     */

    public static boolean isEnabledFor(Logger logger, Level level) {
        boolean res = false;
        if (logger != null && level != null) {
            switch (level) {
            case TRACE:
                res = logger.isTraceEnabled();
                break;
            case DEBUG:
                res = logger.isDebugEnabled();
                break;
            case INFO:
                res = logger.isInfoEnabled();
                break;
            case WARN:
                res = logger.isWarnEnabled();
                break;
            case ERROR:
                res = logger.isErrorEnabled();
                break;
            }
        }
        return res;
    }
}

variadic (Object ...) args 매개 변수와 함께 사용하는 것이 더 쉽습니다.
Anonymoose 2012-06-27

"org.slf4j.Logger"에는 위의 클래스에서 처리되지 않는 로깅 메서드 서명이 상당히 많으므로 확장이 필요합니다. slf4j.org/api/org/slf4j/Logger.html
David Tonhofer

1
이 구현은 원하지 않는 변경 사항을 추가 할 것이라고 생각합니다. logger.info (...) 호출을 사용하면 로거가 호출자 클래스 및 메서드에 액세스 할 수 있으며 로그 항목에 자동으로 추가 될 수 있습니다. 이제이 구현에서 호출 로그 (logger, level, txt)는 항상 동일한 호출자 인 Loglevel.log를 갖는 로그 항목을 생성합니다. 내가 맞아?
Domin

@Domin 안녕하세요, 로거는 현재 호출 스택을 검사 한 다음 자동 로깅을위한 마지막 항목을 추출 할 수 있습니다. 여기에서는 그렇지 않습니까? 원칙적으로 예, 그러나 실제로 스택은 실제 메시지가 기록 될 때까지이 후에도 조금 더 그루브를 할 것입니다. 관심이없는 스택 라인을 버리는 것이 어 펜더의 역할이어야한다고 생각하므로이 Loglevel 클래스에 대한 호출을 포함하여 모든 것을 버리도록 조정할 수 있습니다.
David Tonhofer 2015-08-12

@David, 네, 맞아요 :-). 이 경우 appender와 logger 사이에 하드 종속성을 정의하고 있기 때문에 appender의 작업인지 확실하지 않습니다.하지만 ... 그것은 해결책입니다. 감사합니다 데이비드
Domin

14

Logback으로 전환하고 사용하십시오.

ch.qos.logback.classic.Logger rootLogger = (ch.qos.logback.classic.Logger)LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
rootLogger.setLevel(Level.toLevel("info"));

나는 이것이 Logback에 대한 유일한 호출이며 나머지 코드는 변경되지 않을 것이라고 믿습니다. Logback은 SLF4J를 사용하며 마이그레이션은 간단하며 xml 구성 파일 만 변경하면됩니다.

완료 한 후에는 로그 수준을 다시 설정해야합니다.


이미 Logback 지원 slf4j를 사용하고 있었는데, 이로 인해 즉시 단위 테스트를 정리할 수있었습니다. 감사!
Lambart

2
이것은 나의 첫 번째 -1이었습니다. 감사합니다. 나는 당신이 틀렸다고 믿습니다. Logback은 SLF4J를 사용하므로 대답은 관련이 있습니다.
Αλέκος

3
@AlexandrosGelbessis 질문을 다시 읽어야합니다. 어떤 수준에서든 하나의 로그 메시지를 프로그래밍 방식으로 기록 할 수있는 방법을 요청했습니다. 하나뿐 아니라 모든 메시지의 루트 로거 레벨을 변경합니다.
1월

12

Java 8 람다를 사용하여이를 구현할 수 있습니다.

import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.event.Level;

public class LevelLogger {
    private static final Logger LOGGER = LoggerFactory.getLogger(LevelLogger.class);
    private static final Map<Level, LoggingFunction> map;

    static {
        map = new HashMap<>();
        map.put(Level.TRACE, (o) -> LOGGER.trace(o));
        map.put(Level.DEBUG, (o) -> LOGGER.debug(o));
        map.put(Level.INFO, (o) -> LOGGER.info(o));
        map.put(Level.WARN, (o) -> LOGGER.warn(o));
        map.put(Level.ERROR, (o) -> LOGGER.error(o));
    }

    public static void log(Level level, String s) {
        map.get(level).log(s);
    }

    @FunctionalInterface
    private interface LoggingFunction {
        public void log(String arg);
    }
}

글쎄요 ...하지만 이제이 API를 사용하거나 slf4j 대신 사용하도록 코드베이스를 수정해야합니다. slf4j 대신 사용하는 경우 1) 아마도 더 풍부해야하고 2) 많은 (적어도) 가져 오기를 변경해야하며 3) slf4j 앞에있는이 새 레이어는 추가 로깅 오버 헤드를 추가합니다.
Stephen C

4
또한이 솔루션을 사용할 때 실제 로깅을 수행하는 클래스는 로깅되지 않습니다 (로거가로 초기화되기 때문에 LevelLogger). 일반적으로 매우 유용한 정보이므로 좋지 않습니다.
Dormouse

6

이 작업은 enum및 도우미 메서드를 사용하여 수행 할 수 있습니다 .

enum LogLevel {
    TRACE,
    DEBUG,
    INFO,
    WARN,
    ERROR,
}

public static void log(Logger logger, LogLevel level, String format, Object[] argArray) {
    switch (level) {
        case TRACE:
            logger.trace(format, argArray);
            break;
        case DEBUG:
            logger.debug(format, argArray);
            break;
        case INFO:
            logger.info(format, argArray);
            break;
        case WARN:
            logger.warn(format, argArray);
            break;
        case ERROR:
            logger.error(format, argArray);
            break;
    }
}

// example usage:
private static final Logger logger = ...
final LogLevel level = ...
log(logger, level, "Something bad happened", ...);

logSLF4J의 1- 파라미터 또는 2- 파라미터 warn/ error/ etc 의 일반적인 등가물을 원한다면 의 다른 변형을 추가 할 수 있습니다 . 행동 양식.


3
사실이지만 slf4j 목적은 로그 래퍼를 작성할 필요가 없습니다.
djjeck 2014-06-20

5
SLF4J의 목적은 다른 로깅 프레임 워크에 대한 추상화를 제공하는 것입니다. 추상화가 필요한 것을 정확히 제공하지 못하면 도우미 메서드를 작성할 수밖에 없습니다. 유일한 다른 대안은 SLF4J 프로젝트에 대한 내 대답과 같은 방법을 기여하는 것입니다.
Richard Fearn 2014-06-20

동의하지만이 경우에는 다른 해결 방법을 구현하지 않는 한 더 이상 파일 및 줄 번호를 제공 할 수 없다는 경고가 있습니다. 이 경우 프레임 워크가 기능을 지원할 때까지 log4j를 계속 사용했을 것입니다. 결국 확장을 통해 발생했습니다. Robert Elliot의 최근 답변을 참조하십시오.
djjeck 2014-06-20


3

나는 그저 그런 것이 필요했고 다음을 생각 해냈다.

@RequiredArgsConstructor //lombok annotation
public enum LogLevel{

    TRACE(l -> l::trace),
    INFO (l -> l::info),
    WARN (l -> l::warn),
    ERROR(l -> l::error);

    private final Function<Logger, Consumer<String>> function;

    public void log(Logger logger, String message) {
        function.apply(logger).accept(message);
    }
}

용법:

    LogLevel level = LogLevel.TRACE;
    level.log(logger, "message");

Logger는 호출 중에 전달되므로 클래스 정보는 정상이어야하며 @ Slf4j lombok 주석과 잘 작동합니다.


이 멋진 접근 방식에 대해 대단히 감사합니다. 귀하의 아이디어를 기반으로 비슷한 답변을 게시했습니다.
slartidan

DEBUG상수로 누락되었습니다.
slartidan

이 솔루션은 항상 LogLevel클래스 및 log메서드로 로그하므로 로그의 의미가 떨어집니다.
slartidan

2

것입니다 하지 sjf4j의 로그 레벨을 지정할 수 1.x상자 밖으로. 그러나 SLF4J에 대한 희망이 2.0해결하는 문제는 . 2.0에서는 다음과 같이 보일 수 있습니다.

// POTENTIAL 2.0 SOLUTION
import org.slf4j.helpers.Util;
import static org.slf4j.spi.LocationAwareLogger.*;

// does not work with slf4j 1.x
Util.log(logger, DEBUG_INT, "hello world!");

그 동안 slf4j 1.x의 경우 다음 해결 방법을 사용할 수 있습니다.

이 클래스를 클래스 경로에 복사하십시오.

import org.slf4j.Logger;
import java.util.function.Function;

public enum LogLevel {

    TRACE(l -> l::trace, Logger::isTraceEnabled),
    DEBUG(l -> l::debug, Logger::isDebugEnabled),
    INFO(l -> l::info, Logger::isInfoEnabled),
    WARN(l -> l::warn, Logger::isWarnEnabled),
    ERROR(l -> l::error, Logger::isErrorEnabled);

    interface LogMethod {
        void log(String format, Object... arguments);
    }

    private final Function<Logger, LogMethod> logMethod;
    private final Function<Logger, Boolean> isEnabledMethod;

    LogLevel(Function<Logger, LogMethod> logMethod, Function<Logger, Boolean> isEnabledMethod) {
        this.logMethod = logMethod;
        this.isEnabledMethod = isEnabledMethod;
    }

    public LogMethod prepare(Logger logger) {
        return logMethod.apply(logger);
    }

    public boolean isEnabled(Logger logger) {
        return isEnabledMethod.apply(logger);
    }
}

그런 다음 다음과 같이 사용할 수 있습니다.

Logger logger = LoggerFactory.getLogger(Application.class);

LogLevel level = LogLevel.ERROR;
level.prepare(logger).log("It works!"); // just message, without parameter
level.prepare(logger).log("Hello {}!", "world"); // with slf4j's parameter replacing

try {
    throw new RuntimeException("Oops");
} catch (Throwable t) {
    level.prepare(logger).log("Exception", t);
}

if (level.isEnabled(logger)) {
    level.prepare(logger).log("logging is enabled");
}

다음과 같은 로그가 출력됩니다.

[main] ERROR Application - It works!
[main] ERROR Application - Hello world!
[main] ERROR Application - Exception
java.lang.RuntimeException: Oops
    at Application.main(Application.java:14)
[main] ERROR Application - logging is enabled

그만한 가치가 있습니까?

  • Pro그것은 계속 소스 코드의 위치 (클래스 이름, 메소드 이름, 줄 번호를 가리 킵니다 당신의 코드)
  • Pro변수 , 매개 변수 및 반환 유형을 다음과 같이 쉽게 정의 할 수 있습니다.LogLevel
  • Pro비즈니스 코드는 짧고 읽기 쉬우 며 추가 종속성이 필요 하지 않습니다.

최소한의 예제 인 소스 코드는 GitHub에서 호스팅 됩니다 .


참고 : LogMethod인터페이스가 패키지 외부의 클래스와 작동하려면 공용이어야합니다. 그 외에는 의도 한대로 작동합니다. 감사!
andrebrait

1

slf4j API로는 로그 레벨을 동적으로 변경할 수 없지만 로그 백 (사용하는 경우)은 직접 구성 할 수 있습니다. 이 경우 로거에 대한 팩토리 클래스를 만들고 필요한 구성으로 루트 로거를 구현하십시오.

LoggerContext loggerContext = new LoggerContext();
ch.qos.logback.classic.Logger root = loggerContext.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);

// Configure appender
final TTLLLayout layout = new TTLLLayout();
layout.start(); // default layout of logging messages (the form that message displays 
// e.g. 10:26:49.113 [main] INFO com.yourpackage.YourClazz - log message

final LayoutWrappingEncoder<ILoggingEvent> encoder = new LayoutWrappingEncoder<>();
encoder.setCharset(StandardCharsets.UTF_8);
encoder.setLayout(layout);

final ConsoleAppender<ILoggingEvent> appender = new ConsoleAppender<>();
appender.setContext(loggerContext);
appender.setEncoder(encoder);
appender.setName("console");
appender.start();

root.addAppender(appender);

루트 로거를 구성한 후 (한 번이면 충분 함) 다음을 통해 새 로거 가져 오기를 위임 할 수 있습니다.

final ch.qos.logback.classic.Logger logger = loggerContext.getLogger(clazz);

동일한 loggerContext.

에서 제공 한 루트 로거를 사용하면 로그 수준을 쉽게 변경할 수 있습니다 loggerContext.

root.setLevel(Level.DEBUG);

1

답변 확인 Ondrej Skopek

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import org.slf4j.LoggerFactory;

var rootLogger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
rootLogger.setLevel(Level.TRACE);

결과를 얻을 수 있습니다.

2020-05-14 14 : 01 : 16,644 TRACE [] [oakcmMetrics] 테스트 작업자 MetricName이라는 등록 된 메트릭 [name = bufferpool-wait-time-total, group = producer-metrics, description = 어 펜더가 공간 할당을 기다리는 총 시간 ., tags = {client-id = producer-2}]


0

나는 방금 비슷한 요구에 직면했습니다. 제 경우에는 slf4j가 Java 로깅 어댑터 (jdk14 어댑터)로 구성되어 있습니다. 다음 코드 조각을 사용하여 런타임에 디버그 수준을 변경했습니다.

Logger logger = LoggerFactory.getLogger("testing");
java.util.logging.Logger julLogger = java.util.logging.Logger.getLogger("testing");
julLogger.setLevel(java.util.logging.Level.FINE);
logger.debug("hello world");

1
다른 답변과 마찬가지로 이것은 원래 질문을 해결하지 않고 다른 문제입니다.
E-Riz

0

massimo virgilio의 답변을 기반으로 introspection을 사용하여 slf4j-log4j로도 처리했습니다. HTH.

Logger LOG = LoggerFactory.getLogger(MyOwnClass.class);

org.apache.logging.slf4j.Log4jLogger LOGGER = (org.apache.logging.slf4j.Log4jLogger) LOG;

try {
    Class loggerIntrospected = LOGGER.getClass();
    Field fields[] = loggerIntrospected.getDeclaredFields();
    for (int i = 0; i < fields.length; i++) {
        String fieldName = fields[i].getName();
        if (fieldName.equals("logger")) {
            fields[i].setAccessible(true);
            org.apache.logging.log4j.core.Logger loggerImpl = (org.apache.logging.log4j.core.Logger) fields[i].get(LOGGER);
            loggerImpl.setLevel(Level.DEBUG);
        }
    }
} catch (Exception e) {
    System.out.println("ERROR :" + e.getMessage());
}

0

다음은 @Paul Croarkin만큼 사용자 친화적이지 않은 람다 솔루션입니다 (레벨이 효과적으로 두 번 전달됨). 그러나 나는 (a) 사용자가 Logger를 통과해야한다고 생각합니다. (b) AFAIU 원래 질문은 응용 프로그램의 모든 곳에서 편리한 방법을 요구하는 것이 아니라 라이브러리 내부에서 사용이 거의없는 상황 일뿐이었습니다.

package test.lambda;
import java.util.function.*;
import org.slf4j.*;

public class LoggerLambda {
    private static final Logger LOG = LoggerFactory.getLogger(LoggerLambda.class);

    private LoggerLambda() {}

    public static void log(BiConsumer<? super String, ? super Object[]> logFunc, Supplier<Boolean> logEnabledPredicate, 
            String format, Object... args) {
        if (logEnabledPredicate.get()) {
            logFunc.accept(format, args);
        }
    }

    public static void main(String[] args) {
        int a = 1, b = 2, c = 3;
        Throwable e = new Exception("something went wrong", new IllegalArgumentException());
        log(LOG::info, LOG::isInfoEnabled, "a = {}, b = {}, c = {}", a, b, c);

        // warn(String, Object...) instead of warn(String, Throwable), but prints stacktrace nevertheless
        log(LOG::warn, LOG::isWarnEnabled, "error doing something: {}", e, e);
    }
}

slf4j 는 varargs param 내부에 Throwable (스택 추적이 기록되어야하는)을 허용 하므로 log다른 소비자를 위해 헬퍼 메서드를 오버로딩 할 필요가 없다고 생각 (String, Object[])합니다.


0

먼저 SLF4J Logger 인스턴스를 요청한 다음 바인딩 수준 설정 하여 JDK14 바인딩에 대해이를 수행 할 수있었습니다 . Log4J 바인딩에 대해 시도해 볼 수 있습니다.

private void setLevel(Class loggerClass, java.util.logging.Level level) {
  org.slf4j.LoggerFactory.getLogger(loggerClass);
  java.util.logging.Logger.getLogger(loggerClass.getName()).setLevel(level);
}

0

내가 사용하는 방법은 ch.qos.logback 모듈을 가져온 다음 slf4j Logger 인스턴스를 ch.qos.logback.classic.Logger로 유형 캐스팅하는 것입니다. 이 인스턴스에는 setLevel () 메서드가 포함되어 있습니다.

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;

Logger levelSet = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);

// Now you can set the desired logging-level
levelSet.setLevel( Level.OFF );

가능한 로깅 수준을 확인하려면 ch.qos.logback 클래스를 확장하여 Level에 대해 가능한 모든 값을 볼 수 있습니다 .

prompt$ javap -cp logback-classic-1.2.3.jar ch.qos.logback.classic.Level

결과는 다음과 같습니다.

{
   // ...skipping
   public static final ch.qos.logback.classic.Level OFF;
   public static final ch.qos.logback.classic.Level ERROR;
   public static final ch.qos.logback.classic.Level WARN;
   public static final ch.qos.logback.classic.Level INFO;
   public static final ch.qos.logback.classic.Level DEBUG;
   public static final ch.qos.logback.classic.Level TRACE;
   public static final ch.qos.logback.classic.Level ALL;
}

-2

Java introspection을 사용하면 다음과 같이 할 수 있습니다.

private void changeRootLoggerLevel(int level) {

    if (logger instanceof org.slf4j.impl.Log4jLoggerAdapter) {
        try {
            Class loggerIntrospected = logger.getClass();
            Field fields[] = loggerIntrospected.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                String fieldName = fields[i].getName();
                if (fieldName.equals("logger")) {
                    fields[i].setAccessible(true);
                    org.apache.log4j.Logger loggerImpl = (org.apache.log4j.Logger) fields[i]
                            .get(logger);

                    if (level == DIAGNOSTIC_LEVEL) {
                        loggerImpl.setLevel(Level.DEBUG);
                    } else {
                        loggerImpl.setLevel(org.apache.log4j.Logger.getRootLogger().getLevel());
                    }

                    // fields[i].setAccessible(false);
                }
            }
        } catch (Exception e) {
            org.apache.log4j.Logger.getLogger(LoggerSLF4JImpl.class).error("An error was thrown while changing the Logger level", e);
        }
    }

}

5
이 명시 적으로 SLF4J 일반적으로 log4j를 참조하고 있지
Thorbjørn Ravn 안데르센

-6

아니요, 많은 메서드, info (), debug (), warn () 등이 있습니다 (우선 순위 필드를 대체 함).

전체 Logger API 는 http://www.slf4j.org/api/org/slf4j/Logger.html참조하십시오 .


죄송합니다. 지금 무엇을 요청 하시는지 알겠습니다. 아니요, 런타임에 로그 수준을 변경하는 일반적인 방법은 없지만 switch 문을 사용하여 도우미 메서드를 쉽게 구현할 수 있습니다.
크리스

예, 그러나 "log"메서드의 오버로드 된 버전마다 한 번씩 수행해야합니다.
Andrew Swan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.