Geri kayıt için kök günlük düzeyi programlı olarak nasıl değiştirilir


144

Aşağıdaki logback.xml dosyası var:

<configuration debug="true"> 

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
<encoder>
  <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>

<root level="debug">
  <appender-ref ref="STDOUT" />
</root>
</configuration>

Şimdi, belirli bir olayın meydana gelmesi üzerine, ben programlı gelen kök kaydedicisi düzeyini değiştirmek istediğiniz hata ayıklama için hata . Değişken değiştirme kullanamıyorum, bunu kod içinde yapmak zorunludur.

Nasıl yapılabilir? Teşekkürler.

Yanıtlar:


235

Bunu dene:

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

Logger root = (Logger)LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
root.setLevel(Level.INFO);

Geri dönüş kaydına, yapılandırma dosyanızı periyodik olarak şu şekilde taramasını söyleyebilirsiniz:

<configuration scan="true" scanPeriod="30 seconds" > 
  ...
</configuration> 

64
Slf4j'nin amacının günlükleme çerçevesini soyutlamak olduğunu belirtmek gerekir, ancak bu ilk yöntem, günlükleme çerçevesine doğrudan başvurarak bunu ortadan kaldırır.
Tim Gautier

3
Bunu yapar ve bir ClassCastException alırsanız, bunun nedeni büyük olasılıkla sınıf yolunda birden çok SLF4J bağının bulunmasıdır. Günlük çıktısı bunu ve hariç tutmanız gerekenleri belirlemenize izin vermek için hangi bağların bulunduğunu gösterir.
icfantv

4
Slf4j, kütüphanelerin uygulama geliştiricisinin istediği günlük çerçevesini kullanarak uygulama günlüklerini günlüğe kaydedebilmesi için bir API sağlar. Mesele şu ki, uygulama geliştiricisi hala bir günlük çerçevesi seçmeli, buna bağlı olmalı ve yapılandırmalıdır. Kaydediciyi dogbane'in yaptığı gibi yapılandırmak bu ilkeyi ihlal etmez.
Max

4
@JohnWiseman Yapılandırılmasını istiyorsanız, bir yerde yapılandırmanız gerekir . Slf4j bu konuda hiçbir şey sunmadığından, her zaman temel kaydediciye bağlı bir şey olacaktır. Bir kod parçası veya bir yapılandırma dosyası olsun. +++ OP'nin istediği gibi programlı olarak yapılması gerekiyorsa, başka seçeneğiniz yoktur. Yine de avantajlar kalır: 1. Kodun sadece küçük bir kısmı beton logger motoruna bağlıdır (ve farklı uygulamaları işleyebilmesi için yazılabilir). 2. Diğer günlükçüler kullanılarak yazılan kütüphaneleri de yapılandırabilirsiniz.
maaartinus

4
Kodun kendisinde günlük kaydı düzeyini değiştirmenin doğrudan bir yolu olmasa da, Günlük Kaydı gibi bir şey için neden bu kadar karmaşık olması gerekir. Belirli bir kütüphane ilkesini takip etmek, sadeliğinden nasıl öncelik kazanır? Bir Python dünyasından geliyorum, Java / Scala'da Logging kadar basit bir şeyin neden bu kadar karmaşık olduğunu anlayamıyorum.
Abhinandan Dubey

11

Logback kullandığınızı varsayıyorum (yapılandırma dosyasından).

Gönderen logback kılavuzda , görüyorum

Logger rootLogger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);

Belki bu değeri değiştirmenize yardımcı olabilir?


10

logback 1.1.3 kullanarak aşağıdakileri yapmak zorundaydım (Scala kodu):

import ch.qos.logback.classic.Logger
import org.slf4j.LoggerFactory    
...
val root: Logger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME).asInstanceOf[Logger]

4

Kayıt düzeyini programlı olarak değiştirmek için MDC'yi kullanabileceğinizi düşünüyorum. Aşağıdaki kod, geçerli iş parçacığındaki günlük kaydı düzeyini değiştirmeye bir örnektir. Bu yaklaşım, geri oturum uygulamasına bağımlılık yaratmaz (SLF4J API'sı MDC içerir).

<configuration>
  <turboFilter class="ch.qos.logback.classic.turbo.DynamicThresholdFilter">
    <Key>LOG_LEVEL</Key>
    <DefaultThreshold>DEBUG</DefaultThreshold>
    <MDCValueLevelPair>
      <value>TRACE</value>
      <level>TRACE</level>
    </MDCValueLevelPair>
    <MDCValueLevelPair>
      <value>DEBUG</value>
      <level>DEBUG</level>
    </MDCValueLevelPair>
    <MDCValueLevelPair>
      <value>INFO</value>
      <level>INFO</level>
    </MDCValueLevelPair>
    <MDCValueLevelPair>
      <value>WARN</value>
      <level>WARN</level>
    </MDCValueLevelPair>
    <MDCValueLevelPair>
      <value>ERROR</value>
      <level>ERROR</level>
    </MDCValueLevelPair>
  </turboFilter>
  ......
</configuration>
MDC.put("LOG_LEVEL", "INFO");

3

Başkaları tarafından işaret edildiği gibi, basitçe içeride kaydedilen / gerçekleşen günlük olayını dinleyen mockAppenderbir LoggingEventörnek oluşturur ve oluşturursınız mockAppender.

İşte testte nasıl göründüğü:

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

0

Başarmak gibi görünüyorum

org.jboss.logmanager.Logger logger = org.jboss.logmanager.Logger.getLogger("");
logger.setLevel(java.util.logging.Level.ALL);

Netty'den ayrıntılı günlük kaydı almak için aşağıdakiler yapmıştır:

org.slf4j.impl.SimpleLogger.setLevel(org.slf4j.impl.SimpleLogger.TRACE);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.