package org.molgenis.ui.admin.log; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.util.ContextInitializer; import ch.qos.logback.core.joran.spi.JoranException; import org.molgenis.security.core.utils.SecurityUtils; import org.molgenis.ui.MolgenisPluginController; import org.slf4j.ILoggerFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseStatus; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import static org.molgenis.ui.admin.log.LogManagerController.URI; @Controller @RequestMapping(URI) public class LogManagerController extends MolgenisPluginController { private static final Logger LOG = LoggerFactory.getLogger(LogManagerController.class); public static final String ID = "logmanager"; public static final String URI = MolgenisPluginController.PLUGIN_URI_PREFIX + ID; private static final List<Level> LOG_LEVELS; static { LOG_LEVELS = Arrays.asList(Level.ALL, Level.TRACE, Level.DEBUG, Level.INFO, Level.WARN, Level.ERROR, Level.OFF); } public LogManagerController() { super(URI); } @RequestMapping(method = RequestMethod.GET) public String init(Model model) { ILoggerFactory iLoggerFactory = LoggerFactory.getILoggerFactory(); if (!(iLoggerFactory instanceof LoggerContext)) { throw new RuntimeException("Logger factory is not a Logback logger context"); } LoggerContext loggerContext = (LoggerContext) iLoggerFactory; List<Logger> loggers = new ArrayList<Logger>(); for (ch.qos.logback.classic.Logger logger : loggerContext.getLoggerList()) { if (logger.getLevel() != null || logger.iteratorForAppenders().hasNext()) { loggers.add(logger); } } model.addAttribute("loggers", loggers); model.addAttribute("levels", LOG_LEVELS); model.addAttribute("hasWritePermission", SecurityUtils.currentUserIsSu()); return "view-logmanager"; } @PreAuthorize("hasAnyRole('ROLE_SU')") @RequestMapping(value = "/logger/{loggerName}/{loggerLevel}", method = RequestMethod.POST) @ResponseStatus(HttpStatus.OK) public void updateLogLevel(@PathVariable(value = "loggerName") String loggerName, @PathVariable(value = "loggerLevel") String loggerLevelStr) { // SLF4j logging facade does not support runtime change of log level, cast to Logback logger org.slf4j.Logger logger = LoggerFactory.getLogger(loggerName); if (!(logger instanceof ch.qos.logback.classic.Logger)) { throw new RuntimeException("Root logger is not a Logback logger"); } ch.qos.logback.classic.Logger logbackLogger = (ch.qos.logback.classic.Logger) logger; // update log level Level loggerLevel; try { loggerLevel = Level.valueOf(loggerLevelStr); } catch (IllegalArgumentException e) { throw new RuntimeException("Invalid log level [" + loggerLevelStr + "]"); } logbackLogger.setLevel(loggerLevel); } @PreAuthorize("hasAnyRole('ROLE_SU')") @RequestMapping(value = "/loggers/reset", method = RequestMethod.POST) @ResponseStatus(HttpStatus.OK) public void resetLoggers() { ILoggerFactory iLoggerFactory = LoggerFactory.getILoggerFactory(); if (!(iLoggerFactory instanceof LoggerContext)) { throw new RuntimeException("Logger factory is not a Logback logger context"); } LoggerContext loggerContext = (LoggerContext) iLoggerFactory; ContextInitializer ci = new ContextInitializer(loggerContext); URL url = ci.findURLOfDefaultConfigurationFile(true); loggerContext.reset(); try { ci.configureByResource(url); } catch (JoranException e) { LOG.error("Error reloading log configuration", e); throw new RuntimeException(e); } } }