Jetzt möchte ich beim Auftreten eines bestimmten Ereignisses die Ebene des Root-Loggers programmgesteuert ändern debuggen zu Error. Ich kann keine Variablensubstitution verwenden, es ist zwingend erforderlich, dass ich dies innerhalb des Codes mache.
Es sollte beachtet werden, dass der Zweck von slf4j darin besteht, das Protokollierungs-Framework zu abstrahieren, aber diese erste Methode beseitigt dies, indem sie direkt auf das Protokollierungs-Framework verweist.
– Tim Gautier
11. April 2013 um 21:14 Uhr
Wenn Sie dies tun und eine ClassCastException erhalten, liegt dies höchstwahrscheinlich daran, dass mehrere SLF4J-Bindungen im Klassenpfad vorhanden sind. Die Protokollausgabe zeigt dies an und welche Bindungen vorhanden sind, damit Sie bestimmen können, welche Sie ausschließen müssen.
– icfantv
15. August 2013 um 17:54 Uhr
Slf4j stellt eine API bereit, damit Bibliotheken Anwendungsprotokolle mit einem beliebigen Protokoll-Framework protokollieren können, das der Anwendungsentwickler wünscht. Der Punkt ist, dass der Anwendungsentwickler immer noch ein Protokoll-Framework auswählen, sich darauf verlassen und es konfigurieren muss. Die Konfiguration des Loggers, wie es Dogbane getan hat, verstößt nicht gegen dieses Prinzip.
– max
6. Februar 2016 um 13:35 Uhr
@JohnWiseman Wenn Sie möchten, dass es konfiguriert wird, müssen Sie es konfigurieren irgendwo. Da slf4j in dieser Hinsicht nichts bietet, wird es immer etwas abhängig vom zugrunde liegenden Logger geben. Sei es ein Stück Code oder eine Konfigurationsdatei. +++ Wenn es wie vom OP angefordert programmgesteuert erfolgen soll, haben Sie keine Wahl. Dennoch bleiben Vorteile: 1. Nur ein winziger Teil des Codes hängt von der konkreten Logger-Engine ab (und er könnte so geschrieben werden, dass er mit verschiedenen Implementierungen umgehen kann). 2. Sie können auch Bibliotheken konfigurieren, die mit anderen Loggern geschrieben wurden.
– maaartinus
15. Mai 2016 um 15:34 Uhr
Warum muss es für so etwas wie Logging so kompliziert sein, sollte es nicht eine direkte Möglichkeit geben, das Logging-Level im Code selbst zu ändern? Inwiefern hat das Befolgen des Prinzips der bestimmten Bibliothek Vorrang vor seiner Einfachheit? Da ich aus einer Python-Welt komme, verstehe ich nicht, warum etwas so Einfaches wie Logging in Java/Scala so kompliziert ist.
– Abhinandan Dubey
15. Januar 2019 um 16:04 Uhr
Ich nehme an, Sie verwenden Logback (aus der Konfigurationsdatei).
Mit Logback 1.1.3 musste ich Folgendes tun (Scala-Code):
import ch.qos.logback.classic.Logger
import org.slf4j.LoggerFactory
...
val root: Logger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME).asInstanceOf[Logger]
Einfach-Lösung
Wie von anderen betont, erstellen Sie einfach mockAppender und erstellen Sie dann eine LoggingEvent Instanz, die im Wesentlichen auf das darin registrierte/geschiehte Protokollierungsereignis lauscht mockAppender.
So sieht es im Test aus:
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.core.Appender;
@RunWith(MockitoJUnitRunner.class)
public class TestLogEvent {
// your Logger
private Logger log = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
// here we mock the appender
@Mock
private Appender<ILoggingEvent> mockAppender;
// Captor is generic-ised with ch.qos.logback.classic.spi.LoggingEvent
@Captor
private ArgumentCaptor<LoggingEvent> captorLoggingEvent;
/**
* set up the test, runs before each test
*/
@Before
public void setUp() {
log.addAppender(mockAppender);
}
/**
* Always have this teardown otherwise we can stuff up our expectations.
* Besides, it's good coding practise
*/
@After
public void teardown() {
log.detachAppender(mockAppender);
}
// Assuming this is your method
public void yourMethod() {
log.info("hello world");
}
@Test
public void testYourLoggingEvent() {
//invoke your method
yourMethod();
// now verify our logging interaction
// essentially appending the event to mockAppender
verify(mockAppender, times(1)).doAppend(captorLoggingEvent.capture());
// Having a generic captor means we don't need to cast
final LoggingEvent loggingEvent = captorLoggingEvent.getValue();
// verify that info log level is called
assertThat(loggingEvent.getLevel(), is(Level.INFO));
// Check the message being logged is correct
assertThat(loggingEvent.getFormattedMessage(), containsString("hello world"));
}
}
Ich denke, Sie können MDC verwenden, um die Protokollierungsebene programmgesteuert zu ändern. Der folgende Code ist ein Beispiel zum Ändern der Protokollierungsebene im aktuellen Thread. Dieser Ansatz erzeugt keine Abhängigkeit von der Logback-Implementierung (SLF4J-API enthält MDC).