How to change root logging level programmatically for logback

前端 未结 7 1221
猫巷女王i
猫巷女王i 2020-11-29 16:58

I have the following logback.xml file:

 

          


        
相关标签:
7条回答
  • 2020-11-29 17:10

    using logback 1.1.3 I had to do the following (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]
    
    0 讨论(0)
  • 2020-11-29 17:14

    As pointed out by others, you simply create mockAppender and then create a LoggingEvent instance which essentially listens to the logging event registered/happens inside mockAppender.

    Here is how it looks like in test:

    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 讨论(0)
  • 2020-11-29 17:19

    Try this:

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

    Note that you can also tell logback to periodically scan your config file like this:

    <configuration scan="true" scanPeriod="30 seconds" > 
      ...
    </configuration> 
    
    0 讨论(0)
  • 2020-11-29 17:19

    Here's a controller

    @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;
    }
    

    }

    0 讨论(0)
  • 2020-11-29 17:29

    I seem to be having success doing

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

    Then to get detailed logging from netty, the following has done it

    org.slf4j.impl.SimpleLogger.setLevel(org.slf4j.impl.SimpleLogger.TRACE);
    
    0 讨论(0)
  • 2020-11-29 17:30

    I think you can use MDC to change logging level programmatically. The code below is an example to change logging level on current thread. This approach does not create dependency to logback implementation (SLF4J API contains 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");
    
    0 讨论(0)
提交回复
热议问题