/** * Copyright (c) 2013-2016, The SeedStack authors <http://seedstack.org> * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.seedstack.seed.core.internal.init; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.encoder.PatternLayoutEncoder; import ch.qos.logback.classic.jul.LevelChangePropagator; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.util.ContextInitializer; import ch.qos.logback.core.ConsoleAppender; import ch.qos.logback.core.joran.spi.JoranException; import ch.qos.logback.core.joran.util.ConfigurationWatchListUtil; import org.seedstack.seed.LoggingConfig; import org.seedstack.shed.reflect.Classes; import org.slf4j.LoggerFactory; import java.util.Map; import static com.google.common.base.Strings.isNullOrEmpty; class LogbackLogManager implements LogManager { private final boolean underTomcat = Classes.optional("org.apache.catalina.startup.Catalina").isPresent(); private final LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); LogbackLogManager() { context.getLogger(Logger.ROOT_LOGGER_NAME).setLevel(Level.OFF); } @Override public synchronized void configure(LoggingConfig loggingConfig) { context.reset(); if (!context.isStarted()) { context.start(); } boolean autoConfigurationFailed = false; try { new ContextInitializer(context).autoConfig(); } catch (JoranException e) { autoConfigurationFailed = true; } if (autoConfigurationFailed || !isExplicitlyConfigured()) { context.reset(); PatternLayoutEncoder encoder = new PatternLayoutEncoder(); encoder.setPattern(isNullOrEmpty(loggingConfig.getPattern()) ? "%highlight(%-5level) %d{ISO8601} %magenta(%-15thread) %cyan(%-40logger{40}) %msg%n%red(%throwable)" : loggingConfig.getPattern()); encoder.setContext(context); encoder.start(); ConsoleAppender<ILoggingEvent> logConsoleAppender = new ConsoleAppender<>(); logConsoleAppender.setContext(context); logConsoleAppender.setTarget("System.out"); logConsoleAppender.setEncoder(encoder); logConsoleAppender.start(); Logger nuunLogger = context.getLogger("io.nuun"); nuunLogger.setLevel(Level.WARN); if (underTomcat && (loggingConfig.getLevel() == LoggingConfig.Level.DEBUG || loggingConfig.getLevel() == LoggingConfig.Level.TRACE)) { // When running under Tomcat with a LevelChangePropagator, DEBUG level and below lead to an exception so we force INFO level context.getLogger("org.apache.catalina").setLevel(Level.INFO); context.getLogger("org.apache.juli").setLevel(Level.INFO); } for (Map.Entry<String, LoggingConfig.LoggerConfig> loggerLevelEntry : loggingConfig.getLoggerConfigs().entrySet()) { Logger logger = context.getLogger(loggerLevelEntry.getKey()); LoggingConfig.LoggerConfig config = loggerLevelEntry.getValue(); logger.setLevel(convertLevel(config.getLevel())); logger.setAdditive(config.isAdditive()); } Logger rootLogger = context.getLogger(Logger.ROOT_LOGGER_NAME); rootLogger.setLevel(convertLevel(loggingConfig.getLevel())); rootLogger.addAppender(logConsoleAppender); LevelChangePropagator levelChangePropagator = new LevelChangePropagator(); levelChangePropagator.setContext(context); levelChangePropagator.setResetJUL(true); context.addListener(levelChangePropagator); levelChangePropagator.start(); } } private Level convertLevel(LoggingConfig.Level level) { return Level.valueOf(level.name()); } @Override public synchronized void close() { context.stop(); } private boolean isExplicitlyConfigured() { return ConfigurationWatchListUtil.getMainWatchURL(context) != null; } }