Làm cách nào để thay đổi cấp ghi nhật ký gốc theo chương trình để đăng nhập lại


144

Tôi có tệp logback.xml sau:

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

Bây giờ, khi xảy ra một sự kiện cụ thể, tôi muốn lập trình thay đổi cấp độ của trình ghi nhật ký gốc từ gỡ lỗi thành lỗi . Tôi không thể sử dụng thay thế biến, điều bắt buộc là tôi phải làm điều này trong mã.

Nó được hoàn thiện bằng cách nào ? Cảm ơn.

Câu trả lời:


235

Thử cái này:

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

Lưu ý rằng bạn cũng có thể yêu cầu logback quét định kỳ tệp cấu hình của bạn như thế này:

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

64
Cần lưu ý rằng mục đích của slf4j là để trừu tượng hóa khung ghi nhật ký, nhưng phương pháp đầu tiên không làm được điều đó bằng cách tham chiếu trực tiếp khung ghi nhật ký.
Tim Gautier

3
Nếu bạn làm điều này và nhận ClassCastException, rất có thể là do có nhiều ràng buộc SLF4J trên đường dẫn lớp. Đầu ra nhật ký sẽ chỉ ra điều này và các ràng buộc nào có mặt để cho phép bạn xác định (các) bạn cần loại trừ.
icfantv

4
Slf4j cung cấp API để các thư viện có thể ghi nhật ký ứng dụng bằng bất kỳ khung nhật ký nào mà nhà phát triển ứng dụng muốn. Vấn đề là nhà phát triển ứng dụng vẫn phải chọn khung đăng nhập, phụ thuộc vào nó và cấu hình nó. Cấu hình logger như dogbane đã làm không vi phạm nguyên tắc này.
Tối đa

4
@JohnWiseman Nếu bạn muốn nó được cấu hình, thì bạn phải cấu hình nó ở đâu đó . Vì slf4j không cung cấp gì về mặt này, sẽ luôn có một cái gì đó phụ thuộc vào bộ ghi chép cơ bản. Có thể là một đoạn mã hoặc tập tin cấu hình. +++ Nếu nó được thực hiện theo chương trình như OP yêu cầu, thì bạn không có lựa chọn nào khác. Tuy nhiên, các ưu điểm vẫn còn: 1. Chỉ một phần nhỏ của mã phụ thuộc vào công cụ logger cụ thể (và nó có thể được viết để nó có thể xử lý các triển khai khác nhau). 2. Bạn cũng có thể định cấu hình các thư viện được viết bằng các logger khác.
maaartinus

4
Tại sao nó phải quá phức tạp đối với một cái gì đó như Ghi nhật ký, không nên có một cách trực tiếp để thay đổi mức ghi nhật ký trong chính mã. Làm thế nào để tuân theo nguyên tắc của thư viện cụ thể được ưu tiên hơn sự đơn giản của nó? Đến từ một thế giới Python, tôi không hiểu tại sao một thứ đơn giản như Logging lại phức tạp như vậy trong Java / Scala.
Abhinandan Dubey

11

Tôi giả sử bạn đang sử dụng logback (từ tệp cấu hình).

Từ hướng dẫn đăng nhập , tôi thấy

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

Có lẽ điều này có thể giúp bạn thay đổi giá trị?


10

sử dụng logback 1.1.3 Tôi phải làm như sau (mã Scala):

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

4

Tôi nghĩ bạn có thể sử dụng MDC để thay đổi cấp ghi nhật ký theo chương trình. Mã dưới đây là một ví dụ để thay đổi mức ghi nhật ký trên luồng hiện tại. Cách tiếp cận này không tạo ra sự phụ thuộc vào việc thực hiện đăng nhập lại (API SLF4J chứa MDC).

<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

Như những người khác đã chỉ ra, bạn chỉ cần tạo mockAppendervà sau đó tạo một LoggingEventthể hiện chủ yếu lắng nghe sự kiện đăng nhập đã đăng ký / xảy ra bên trong mockAppender.

Đây là cách nó trông giống như trong thử nghiệm:

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

Tôi dường như đang thành công

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

Sau đó, để có được đăng nhập chi tiết từ netty, sau đây đã làm điều đó

org.slf4j.impl.SimpleLogger.setLevel(org.slf4j.impl.SimpleLogger.TRACE);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.