로그백을 위해 루트 로깅 수준을 프로그래밍 방식으로 변경하는 방법
다음 logback.xml 파일이 있습니다.
<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>
여기서 특정 이벤트가 발생하면 루트 로거의 레벨을 디버깅에서 에러로 프로그래밍 방식으로 변경합니다.변수 치환을 사용할 수 없습니다. 반드시 이 작업을 코드 내에서 수행해야 합니다.
어떻게 하면 좋을까요?고마워요.
이것을 시험해 보세요.
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
Logger root = (Logger)LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
root.setLevel(Level.INFO);
로그백에 다음과 같이 컨피규레이션파일을 정기적으로 스캔하도록 지시할 수도 있습니다.
<configuration scan="true" scanPeriod="30 seconds" >
...
</configuration>
(컨피규레이션파일에서) logback을 사용하고 있을 겁니다.
로그백 매뉴얼에서 알 수 있었습니다.
Logger rootLogger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
이것이 가치변경에 도움이 될 수 있을까요?
logback 1.1.3을 사용하여 다음 작업을 수행해야 했습니다(Scala 코드).
import ch.qos.logback.classic.Logger
import org.slf4j.LoggerFactory
...
val root: Logger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME).asInstanceOf[Logger]
다른 사람들이 지적한 바와 같이 단순히mockAppender
그 후, 작성한다.LoggingEvent
내부 등록/실행 로깅이벤트를 기본적으로 리슨하는 인스턴스mockAppender
.
테스트에서는 다음과 같이 표시됩니다.
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"));
}
}
MDC를 사용하여 로깅 수준을 프로그래밍 방식으로 변경할 수 있습니다.다음 코드는 현재 스레드의 로깅 수준을 변경하는 예입니다.이 방법에서는 로그백 구현에 대한 의존성이 발생하지 않습니다(SLF4J API에는 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");
나는 하는 데 성공하고 있는 것 같다.
org.jboss.logmanager.Logger logger = org.jboss.logmanager.Logger.getLogger("");
logger.setLevel(java.util.logging.Level.ALL);
그 후 netty에서 상세 로깅을 얻기 위해 다음 작업이 수행되었습니다.
org.slf4j.impl.SimpleLogger.setLevel(org.slf4j.impl.SimpleLogger.TRACE);
여기 컨트롤러가 있습니다.
@RestController
@RequestMapping("/loggers")
public class LoggerConfigController {
private final static org.slf4j.Logger LOGGER = LoggerFactory.getLogger(PetController.class);
@GetMapping()
public List<LoggerDto> getAllLoggers() throws CoreException {
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
List<Logger> loggers = loggerContext.getLoggerList();
List<LoggerDto> loggerDtos = new ArrayList<>();
for (Logger logger : loggers) {
if (Objects.isNull(logger.getLevel())) {
continue;
}
LoggerDto dto = new LoggerDto(logger.getName(), logger.getLevel().levelStr);
loggerDtos.add(dto);
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("All loggers retrieved. Total of {} loggers found", loggerDtos.size());
}
return loggerDtos;
}
@PutMapping
public boolean updateLoggerLevel(
@RequestParam String name,
@RequestParam String level
)throws CoreException {
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
Logger logger = loggerContext.getLogger(name);
if (Objects.nonNull(logger) && StringUtils.isNotBlank(level)) {
switch (level) {
case "INFO":
logger.setLevel(Level.INFO);
LOGGER.info("Logger [{}] updated to [{}]", name, level);
break;
case "DEBUG":
logger.setLevel(Level.DEBUG);
LOGGER.info("Logger [{}] updated to [{}]", name, level);
break;
case "ALL":
logger.setLevel(Level.ALL);
LOGGER.info("Logger [{}] updated to [{}]", name, level);
break;
case "OFF":
default:
logger.setLevel(Level.OFF);
LOGGER.info("Logger [{}] updated to [{}]", name, level);
}
}
return true;
}
}
언급URL : https://stackoverflow.com/questions/3837801/how-to-change-root-logging-level-programmatically-for-logback
'programing' 카테고리의 다른 글
문자열 상수에서 'char*'로의 변환이 C에서는 유효하지만 C++에서는 무효인 이유 (0) | 2022.07.28 |
---|---|
Vuex: 변환 시 평균 대괄호란 무엇입니까? (0) | 2022.07.28 |
확인란에서 ID를 가져와 vue3에서 선택되었는지 확인하는 방법 (0) | 2022.07.28 |
언제 C에서 malloc을 사용해야 하고 사용하지 말아야 하나요? (0) | 2022.07.28 |
python C 확장 프로파일링 (0) | 2022.07.28 |