Установка уровня журнала сообщений во время выполнения в slf4j - PullRequest
85 голосов
/ 12 апреля 2010

При использовании log4j доступен метод Logger.log(Priority p, Object message), который можно использовать для регистрации сообщения на уровне журнала, определенном во время выполнения. Мы используем этот факт и этот совет для перенаправления stderr в регистратор на определенном уровне журнала.

slf4j не имеет общего метода log(), который я могу найти. Означает ли это, что нет способа реализовать вышесказанное?

Ответы [ 15 ]

0 голосов
/ 29 июля 2016

Вот лямбда-решение, не столь удобное для пользователя, как у @Paul Croarkin в одном смысле (уровень фактически пройден дважды). Но я думаю, что (а) пользователь должен пройти регистратор; и (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 допускает Throwable (чья трассировка стека должна регистрироваться) внутри параметра varargs , я думаю, что нет необходимости перегружать вспомогательный метод log для других потребителей, кроме (String, Object[]).

0 голосов
/ 24 февраля 2016

Основываясь на ответе Массимо Вирджилио, мне также удалось сделать это с помощью slf4j-log4j, используя интроспекцию. НТН.

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 голосов
/ 11 июня 2014

Я только что столкнулся с аналогичной потребностью. В моем случае 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");
0 голосов
/ 27 апреля 2012

используя Java-самоанализ, вы можете сделать это, например:

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

}
0 голосов
/ 12 апреля 2010

нет, есть несколько методов, info (), debug (), warn () и т. Д. (Это заменяет поле приоритета)

посмотрите на http://www.slf4j.org/api/org/slf4j/Logger.html для полного API Logger.

...