Java 如何以编程方式更改根日志记录级别以进行回写
我有以下logback.xml文件:Java 如何以编程方式更改根日志记录级别以进行回写,java,logging,logback,Java,Logging,Logback,我有以下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
<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>
%d{HH:mm:ss.SSS}[%thread]-5级别%logger{36}-%msg%n
现在,在发生特定事件时,我希望通过编程将根记录器的级别从debug更改为error。我不能使用变量替换,我必须在代码中这样做
怎样才能做到呢?谢谢。我假设您正在使用logback(来自配置文件) 我明白了
Logger rootLogger=LoggerFactory.getLogger(org.slf4j.Logger.ROOT\u Logger\u NAME)代码>
也许这可以帮助您更改值?尝试以下方法:
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);
请注意,您还可以告诉logback定期扫描配置文件,如下所示:
<configuration scan="true" scanPeriod="30 seconds" >
...
</configuration>
...
正如其他人所指出的,您只需创建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"));
}
}
import org.slf4j.LoggerFactory;
导入ch.qos.logback.classic.Level;
导入ch.qos.logback.classic.Logger;
导入ch.qos.logback.classic.spi.ILoggingEvent;
导入ch.qos.logback.classic.spi.LoggingEvent;
导入ch.qos.logback.core.Appender;
@RunWith(MockitoJUnitRunner.class)
公共类TestLogEvent{
//你的记录器
私有记录器log=(Logger)LoggerFactory.getLogger(Logger.ROOT\u Logger\u NAME);
//在这里,我们模拟了appender
@嘲弄
私人追加器模拟追加器;
//捕获者与ch.qos.logback.classic.spi.LoggingEvent通用
@俘虏
私人辩论CaptorCaptorLoggingEvent;
/**
*设置测试,在每次测试之前运行
*/
@以前
公共作废设置(){
log.addAppender(mockAppender);
}
/**
*一定要有这种拆卸,否则我们会把我们的期望压得喘不过气来。
*此外,这是很好的编码实践
*/
@之后
公共无效拆卸(){
log.detachAppender(mockAppender);
}
//假设这是你的方法
公共方法(){
log.info(“你好世界”);
}
@试验
公共无效测试YourLoggingEvent(){
//调用您的方法
你的方法();
//现在验证我们的日志交互
//本质上是将事件附加到mockAppender
验证(mockAppender,times(1)).doAppend(captorLoggingEvent.capture());
//拥有一个普通的俘虏意味着我们不需要施放
final LoggingEvent LoggingEvent=captorLoggingEvent.getValue();
//验证是否调用了信息日志级别
断言(loggingEvent.getLevel(),是(Level.INFO));
//检查正在记录的消息是否正确
资产(loggingEvent.getFormattedMessage(),包含字符串(“hello world”);
}
}
使用logback 1.1.3,我必须执行以下操作(Scala代码):
我认为您可以使用MDC以编程方式更改日志记录级别。下面的代码是更改当前线程日志记录级别的示例。这种方法不会创建对logback实现的依赖关系(SLF4J API包含MDC)
对数级
调试
痕迹
痕迹
调试
调试
信息
信息
警告
警告
错误
错误
......
MDC.put(“日志级别”、“信息”);
我的工作似乎很成功
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;
}
@RestController
@请求映射(“/loggers”)
公共类LoggerConfigController{
私有最终静态org.slf4j.Logger Logger=LoggerFactory.getLogger(PetController.class);
@GetMapping()
公共列表getAllLoggers()引发CoreException{
LoggerContext LoggerContext=(LoggerContext)LoggerFactory.getILoggerFactory();
List loggers=loggerContext.getLoggerList();
List loggerDtos=new ArrayList();
用于(记录器:记录器){
if(Objects.isNull(logger.getLevel())){
继续;
}
LoggerDto dto=新的LoggerDto(logger.getName(),logger.getLevel().levelStr);
loggerDtos.add(dto);
}
if(LOGGER.isDebugEnabled()){
debug(“检索到的所有记录器。找到的{}个记录器的总数”,loggerDtos.size());
}
返回loggerDtos;
}
@PutMapping
公共布尔值UpdateLogger级别(
@RequestParam字符串名称,
@RequestParam字符串级别
)抛出CoreException{
LoggerContext LoggerContext=(LoggerContext)LoggerFactory.getILoggerFactory();
Logger Logger=loggerContext.getLogger(名称);
if(Objects.nonNull(记录器)和&StringUtils.isNotBlank(级别)){
开关(电平){
案例“信息”:
logger.setLevel(Level.INFO);
info(“记录器[{}]更新为[{}]”,名称,级别);
打破
案例“调试”:
logger.setLevel(Level.DEBUG);
info(“记录器[{}]更新为[{}]”,名称,级别);
打破
案例“全部”:
logger.setLevel(Level.ALL);
info(“记录器[{}]更新为[{}]”,名称,级别);
打破
案例“关闭”:
违约:
记录器设置电平(电平关闭);
info(“记录器[{}]更新为[{}]”,名称,级别);
}
}
返回true;
}
}应该注意的是,slf4j的目的是抽象出日志框架,但第一种方法通过直接引用日志框架来实现。如果这样做并得到ClassCastException,很可能是因为类路径上有多个slf4j绑定。日志输出将指出这一点以及存在哪些绑定,以便您确定需要排除哪些绑定。Slf4j提供了一个API,以便库可以使用应用程序开发人员想要的任何日志框架记录应用程序日志。关键是
@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;
}