Menyetel tingkat log pesan saat runtime di slf4j

100

Saat menggunakan log4j, Logger.log(Priority p, Object message)metode ini tersedia dan dapat digunakan untuk mencatat pesan pada tingkat log yang ditentukan saat runtime. Kami menggunakan fakta ini dan tip ini untuk mengarahkan stderr ke logger pada tingkat log tertentu.

slf4j tidak memiliki log()metode umum yang dapat saya temukan. Apakah itu berarti tidak ada cara untuk menerapkan hal di atas?

Edward Dale
sumber
4
Sepertinya ada beberapa diskusi untuk menambahkan ini ke slf4j 2.0 di milis dev: qos.ch/pipermail/slf4j-dev/2010-March/002865.html
Edward Dale
1
lihat Marker, ini adalah data khusus yang dapat Anda berikan ke rantai log.
tuxSlayer
1
@tuxSlayer dapatkah Anda menjelaskan cara menggunakan Marker dalam kasus ini?
Variabel Miserable
Mungkin ini bukan ide terbaik untuk "logging" tetapi Anda dapat menggunakan beberapa penanda untuk entri log "prioritas" (tinggi | rendah | normal, info | memperingatkan | fatal) dan menggunakan pemfilteran di logback atau appender kustom untuk menggunakan penanda dan mendorong entri log ke saluran terpisah (info log, email fatal, dll). Namun, cara yang lebih lurus adalah memiliki fasad untuk ini seperti yang ditunjukkan dalam jawaban di bawah ini.
tuxSlayer
2
Fitur ini seharusnya menjadi bagian dari slf4j 2.0. jira.qos.ch/browse/SLF4J-124 Lihat jawaban saya untuk detailnya dan untuk kemungkinan slf4j 1.xsolusi.
slartidan

Jawaban:

47

Tidak ada cara untuk melakukan ini dengan slf4j.

Saya membayangkan bahwa alasan mengapa fungsi ini hilang adalah karena hampir tidak mungkin untuk membangun Leveltipe slf4jyang dapat secara efisien dipetakan ke tipe Level(atau setara) yang digunakan di semua kemungkinan implementasi logging di belakang fasad. Alternatifnya, perancang memutuskan bahwa kasus penggunaan Anda terlalu tidak biasa untuk membenarkan biaya tambahan untuk mendukungnya.

Mengenai @ ripper234 's penggunaan-kasus (unit testing), saya pikir solusi pragmatis adalah memodifikasi tes unit (s) ke hard-kawat pengetahuan tentang apa sistem logging yang ada di balik fasad slf4j ... ketika menjalankan unit test.

Stephen C
sumber
9
Sebenarnya tidak perlu pemetaan. Ada lima level yang sudah ditentukan secara implisit oleh metode di org.slf4j.Logger: debug, error, info, trace, warn.
Edward Dale
1
Dan masalah ditutup sebagai tidak valid. Sejauh yang saya pahami, ini adalah pilihan desain yang disengaja.
ripper234
9
@ ripper234 - Saya rasa bug Anda tidak membahas masalah yang sama seperti pertanyaan asli scompt.com. Anda bertanya tentang mengonfigurasi tingkat sistem logging yang mendasari melalui SLF4J API. Apa yang dicari scompt.com adalah metode 'log' umum di SLF4J API, yang mengambil tingkat pencatatan pesan sebagai parameter.
Richard Fearn
1
+1 @RichardFearn Dan seseorang tidak dapat membatalkan upvote komentar setelah 60 detik, meh . Sementara itu, permintaan fitur sudah ada: bugzilla.slf4j.org/show_bug.cgi?id=133
jan
3
Tautan RFE tidak menyelesaikan lagi. Tautan yang relevan sekarang adalah: jira.qos.ch/browse/SLF4J-124 dan jira.qos.ch/browse/SLF4J-197 ... dan keduanya telah ditutup. Baca komentar untuk alasannya.
Stephen C
27

Richard Fearn memiliki ide yang tepat, jadi saya menulis kelas lengkapnya berdasarkan kode kerangkanya. Semoga cukup singkat untuk memposting di sini. Salin & tempel untuk kesenangan. Saya mungkin harus menambahkan beberapa mantra ajaib juga: "Kode ini dilepaskan ke domain publik"

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;
    }
}
David Tonhofer
sumber
Ini akan lebih mudah digunakan dengan parameter args variadic (Object ...).
Anonymoose
"org.slf4j.Logger" memiliki cukup banyak tanda tangan metode pencatatan yang tidak ditangani di kelas di atas, jadi ekstensi mungkin dijamin: slf4j.org/api/org/slf4j/Logger.html
David Tonhofer
1
Saya pikir penerapan ini akan menambah perubahan yang tidak diinginkan. Ketika Anda menggunakan panggilan logger.info (...) logger memiliki akses ke kelas dan metode pemanggil dan dapat ditambahkan ke entri log secara otomatis. Sekarang, dengan implementasi ini, log panggilan (logger, level, txt) akan menghasilkan entri log yang akan selalu menjadi pemanggil yang sama: Loglevel.log. Apakah saya benar?
Domin
@Domin Hai, maksud Anda, logger dapat memeriksa tumpukan panggilan saat ini, kemudian mengekstrak entri terakhir untuk pencatatan otomatis, yang tidak terjadi di sini? Pada prinsipnya ya, tetapi pada kenyataannya, tumpukan akan sedikit lebih banyak bahkan setelah ini sampai pesan yang sebenarnya ditulis (khususnya, logback harus dipanggil di beberapa titik, kemudian appender sebenarnya). Saya pikir itu harus menjadi peran appender untuk membuang baris tumpukan yang tidak menarik, sehingga Anda dapat menyesuaikannya untuk membuang semuanya dan termasuk panggilan ke kelas Loglevel ini.
David Tonhofer
@David, Ya, Anda benar :-). Saya tidak yakin bahwa ini adalah tugas untuk appender karena dalam hal ini Anda mendefinisikan ketergantungan yang kuat antara appender dan logger ... tapi ... ini adalah solusi. Terima kasih David
Domin
14

Coba beralih ke Logback dan gunakan

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

Saya yakin ini akan menjadi satu-satunya panggilan ke Logback dan kode Anda lainnya tidak akan berubah. Logback menggunakan SLF4J dan migrasi tidak akan menimbulkan rasa sakit, hanya file konfigurasi xml yang harus diubah.

Ingatlah untuk menyetel kembali level log setelah Anda selesai.

Αλέκος
sumber
Saya sudah menggunakan slf4j yang didukung Logback, dan ini langsung memungkinkan saya untuk membersihkan pengujian unit saya. Terima kasih!
Lambart
2
Ini pertama saya -1, terima kasih. Saya yakin Anda salah. Logback menggunakan SLF4J, jadi jawabannya relevan.
Αλέκος
3
@AlexandrosGelbessis Anda harus membaca ulang pertanyaannya. Itu ditanyakan tentang metode yang bisa mencatat secara terprogram satu pesan log di tingkat mana pun. Anda mengubah level logger root untuk semua pesan, tidak hanya untuk satu.
Januari
12

Anda bisa mengimplementasikan ini menggunakan Java 8 lambda.

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);
    }
}
Paul Croarkin
sumber
Ya ... tapi sekarang Anda perlu memodifikasi basis kode Anda untuk menggunakan API ini serta atau sebagai pengganti slf4j. Jika Anda menggunakannya sebagai ganti slf4j 1) mungkin perlu lebih kaya, 2) banyak (setidaknya) impor perlu diubah, dan 3) lapisan baru di depan slf4j ini menambahkan overhead logging ekstra.
Stephen C
4
Ketahuilah juga bahwa saat Anda menggunakan solusi ini, kelas yang melakukan pencatatan sebenarnya tidak akan dicatat (karena pencatat diinisialisasi dengan LevelLogger), yang bukan merupakan hal yang baik karena umumnya informasi sangat berguna.
Dormouse
6

Ini bisa dilakukan dengan metode an enumand helper:

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", ...);

Anda dapat menambahkan varian lain dari log, katakanlah jika Anda menginginkan persamaan generik dari 1-parameter SLF4J atau 2-parameter warn/ error/ etc. metode.

Richard Fearn
sumber
3
Benar, tetapi tujuan slf4j bukanlah untuk menulis pembungkus log.
djjeck
5
Tujuan SLF4J adalah menyediakan abstraksi untuk kerangka kerja logging yang berbeda. Jika abstraksi itu tidak memberikan apa yang Anda butuhkan, Anda tidak punya pilihan selain menulis metode pembantu. Satu-satunya alternatif lain adalah menyumbangkan metode seperti yang ada dalam jawaban saya untuk proyek SLF4J.
Richard Fearn
Saya setuju, tetapi dalam kasus ini ada peringatan, seperti Anda tidak akan dapat memberikan file dan nomor baris lagi, kecuali Anda menerapkan solusi lain untuk itu. Dalam hal ini saya akan terjebak dengan log4j, sampai kerangka mendukung fitur - yang akhirnya terjadi melalui ekstensi, lihat jawaban Robert Elliot yang lebih baru.
djjeck
5

Siapa pun yang menginginkan solusi drop-in yang sepenuhnya kompatibel dengan SLF4J untuk masalah ini mungkin ingin melihat Ekstensi Lidalia SLF4J - ada di Maven Central.

Robert Elliot
sumber
3

Saya baru saja membutuhkan sesuatu seperti itu dan muncul dengan:

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

pemakaian:

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

Pencatat diteruskan selama pemanggilan, jadi info kelas akan baik-baik saja, dan bekerja dengan baik dengan anotasi @ Slf4j lombok.

Kamil Nowak
sumber
Terima kasih banyak atas pendekatan yang luar biasa ini - Saya memposting jawaban yang serupa, berdasarkan ide Anda.
slartidan
DEBUGhilang sebagai konstanta.
slartidan
Solusi ini akan selalu mencatat sebagai metode LogLevelkelas dan logsebagai, yang membuat log kurang bermakna.
slartidan
2

Hal ini tidak mungkin untuk menentukan tingkat log di sjf4j 1.xkeluar dari kotak. Tetapi ada harapan bagi slf4j 2.0untuk memperbaiki masalah tersebut . Dalam 2.0 mungkin terlihat seperti ini:

// 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!");

Sementara itu, untuk slf4j 1.x, Anda dapat menggunakan solusi ini:

Salin kelas ini ke classpath Anda:

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

Kemudian Anda bisa menggunakannya seperti ini:

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

Ini akan mengeluarkan log seperti ini:

[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

Apakah itu layak?

  • ProItu membuat lokasi kode sumber (nama kelas, nama metode, nomor baris akan mengarah ke Anda kode )
  • ProAnda dapat dengan mudah mendefinisikan variabel , parameter, dan tipe kembalian sebagaiLogLevel
  • ProKode bisnis Anda tetap pendek dan mudah dibaca, dan tidak diperlukan ketergantungan tambahan .

Kode sumber sebagai contoh minimal dihosting di GitHub .

slartidan
sumber
Catatan: LogMethodantarmuka harus bersifat publik agar dapat bekerja dengan kelas di luar paketnya. Selain itu, ini berfungsi sebagaimana mestinya. Terima kasih!
andrebrait
1

Slf4j API tidak mungkin mengubah level log secara dinamis, tetapi Anda dapat mengonfigurasi logback (jika Anda menggunakannya) sendiri. Dalam hal ini, buat kelas pabrik untuk logger Anda dan implementasikan root logger dengan konfigurasi yang Anda perlukan.

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

Setelah Anda mengkonfigurasi root logger (hanya sekali saja sudah cukup), Anda dapat mendelegasikan mendapatkan logger baru dengan

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

Ingatlah untuk menggunakan yang sama loggerContext .

Mengubah level log mudah dilakukan dengan root logger yang diberikan dari loggerContext.

root.setLevel(Level.DEBUG);
pablo127
sumber
1

Konfirmasikan jawaban 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);

Anda akan mendapatkan hasil:

2020-05-14 14: 01: 16,644 TRACE [] [oakcmMetrics] Pekerja pengujian Metrik terdaftar bernama MetricName [name = bufferpool-wait-time-total, group = producer-metrics, description = Total waktu appender menunggu alokasi ruang ., tag = {client-id = producer-2}]

Torino
sumber
0

Saya baru saja menemukan kebutuhan yang serupa. Dalam kasus saya, slf4j dikonfigurasi dengan adaptor pencatatan java (yang jdk14). Dengan menggunakan cuplikan kode berikut, saya berhasil mengubah level debug saat runtime:

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");
Yair Zaslavsky
sumber
1
Seperti jawaban lain, ini tidak menjawab pertanyaan asli, ini masalah yang berbeda.
E-Riz
0

Berdasarkan jawaban massimo virgilio, saya juga berhasil melakukannya dengan slf4j-log4j menggunakan introspeksi. 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());
}
Guido
sumber
0

Berikut adalah solusi lambda yang tidak semudah @Paul Croarkin dalam satu hal (levelnya dilewati secara efektif dua kali). Tapi saya pikir (a) pengguna harus melewati Logger; dan (b) AFAIU pertanyaan awal tidak menanyakan cara yang nyaman untuk semua tempat dalam aplikasi, hanya situasi dengan sedikit penggunaan di dalam perpustakaan.

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

Karena slf4j memungkinkan Throwable (yang jejak tumpukannya harus dicatat) di dalam parameter varargs , menurut saya tidak perlu membebani logmetode pembantu untuk konsumen lain selain (String, Object[]).

EndlosSchleife
sumber
0

Saya dapat melakukan ini untuk pengikatan JDK14 dengan terlebih dahulu meminta instans SLF4J Logger dan kemudian menyetel level pada pengikatan - Anda dapat mencoba ini untuk pengikatan 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);
}
youurayy
sumber
0

Metode yang saya gunakan adalah mengimpor modul ch.qos.logback dan kemudian mengetikkan instance Logger slf4j ke ch.qos.logback.classic.Logger. Instance ini menyertakan metode 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 );

Untuk mengetahui kemungkinan level Logging, Anda dapat meledakkan kelas ch.qos.logback untuk melihat semua kemungkinan nilai untuk Level :

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

Hasilnya adalah sebagai berikut:

{
   // ...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;
}
Glenn Inn
sumber
-2

menggunakan introspeksi java Anda dapat melakukannya, misalnya:

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

}
massimo virgilio
sumber
5
Ini secara eksplisit mengacu pada log4j dan bukan slf4j secara umum
Thorbjørn Ravn Andersen
-6

tidak, ini memiliki sejumlah metode, info (), debug (), warn (), dll (ini menggantikan bidang prioritas)

lihat di http://www.slf4j.org/api/org/slf4j/Logger.html untuk logger api lengkap.

chris
sumber
maaf, saya mengerti apa yang Anda tanyakan sekarang. tidak, tidak ada cara umum untuk mengubah level log saat runtime, tetapi Anda dapat dengan mudah menerapkan metode helper dengan statment switch.
chris
Ya, tetapi Anda harus melakukannya sekali untuk setiap versi metode "log" yang kelebihan beban.
Andrew Swan