diff options
author | Duarte Meneses <duarte.meneses@sonarsource.com> | 2015-06-16 17:37:13 +0200 |
---|---|---|
committer | Duarte Meneses <duarte.meneses@sonarsource.com> | 2015-06-23 15:15:25 +0200 |
commit | 792d7eb799efc25d92adcf059acc4c7c9f67d2c7 (patch) | |
tree | ecf24200abe9a1586a35893297743004ebc9193d /sonar-batch/src/main/java/org/sonar | |
parent | eba86f1a7feca56d8b39ec7baa6f105eef0fef91 (diff) | |
download | sonarqube-792d7eb799efc25d92adcf059acc4c7c9f67d2c7.tar.gz sonarqube-792d7eb799efc25d92adcf059acc4c7c9f67d2c7.zip |
SONAR-6648 Allow to redirect logs to a custom stream
Diffstat (limited to 'sonar-batch/src/main/java/org/sonar')
4 files changed, 191 insertions, 42 deletions
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/Batch.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/Batch.java index 70da9601bd1..c82124d64ab 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/Batch.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/Batch.java @@ -19,6 +19,9 @@ */ package org.sonar.batch.bootstrapper; +import org.sonar.home.log.LogListener; + +import org.picocontainer.annotations.Nullable; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import org.sonar.batch.bootstrap.GlobalContainer; @@ -35,7 +38,7 @@ import java.util.Map; public final class Batch { private boolean started = false; - private LoggingConfiguration logging; + private LoggingConfiguration loggingConfig; private List<Object> components; private Map<String, String> bootstrapProperties = Maps.newHashMap(); private GlobalContainer bootstrapContainer; @@ -50,12 +53,16 @@ public final class Batch { bootstrapProperties.putAll(builder.bootstrapProperties); } if (builder.isEnableLoggingConfiguration()) { - logging = LoggingConfiguration.create(builder.environment).setProperties(bootstrapProperties); + loggingConfig = new LoggingConfiguration(builder.environment).setProperties(bootstrapProperties); + + if (builder.listener != null) { + loggingConfig.setListener(builder.listener); + } } } public LoggingConfiguration getLoggingConfiguration() { - return logging; + return loggingConfig; } /** @@ -110,8 +117,8 @@ public final class Batch { } private void configureLogging() { - if (logging != null) { - logging.configure(); + if (loggingConfig != null) { + LoggingConfigurator.apply(loggingConfig); } } @@ -124,6 +131,7 @@ public final class Batch { private EnvironmentInformation environment; private List<Object> components = Lists.newArrayList(); private boolean enableLoggingConfiguration = true; + private LogListener listener; private Builder() { } @@ -138,6 +146,11 @@ public final class Batch { return this; } + public Builder setLogListener(@Nullable LogListener listener) { + this.listener = listener; + return this; + } + /** * @deprecated since 3.7 use {@link #setBootstrapProperties(Map)} */ diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/LogCallbackAppender.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/LogCallbackAppender.java new file mode 100644 index 00000000000..6c216410d13 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/LogCallbackAppender.java @@ -0,0 +1,60 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.bootstrapper; + +import org.sonar.home.log.LogListener; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.core.UnsynchronizedAppenderBase; +import ch.qos.logback.classic.spi.ILoggingEvent; + +public class LogCallbackAppender extends UnsynchronizedAppenderBase<ILoggingEvent> { + protected LogListener target; + + public LogCallbackAppender(LogListener target) { + setTarget(target); + } + + public void setTarget(LogListener target) { + this.target = target; + } + + @Override + protected void append(ILoggingEvent event) { + target.log(event.getFormattedMessage(), translate(event.getLevel())); + } + + private LogListener.Level translate(Level level) { + switch(level.toInt()) { + case Level.ERROR_INT: + return LogListener.Level.ERROR; + case Level.WARN_INT: + return LogListener.Level.WARN; + case Level.INFO_INT: + return LogListener.Level.INFO; + case Level.DEBUG_INT: + return LogListener.Level.DEBUG; + case Level.TRACE_INT: + return LogListener.Level.TRACE; + default: + return LogListener.Level.DEBUG; + } + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/LoggingConfiguration.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/LoggingConfiguration.java index da83b54becb..e2ee829310d 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/LoggingConfiguration.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/LoggingConfiguration.java @@ -19,15 +19,14 @@ */ package org.sonar.batch.bootstrapper; +import org.sonar.home.log.LogListener; + import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Maps; import org.apache.commons.lang.StringUtils; -import org.sonar.core.config.Logback; import javax.annotation.Nullable; -import java.io.File; -import java.io.PrintStream; import java.util.Map; /** @@ -37,18 +36,25 @@ public final class LoggingConfiguration { public static final String PROPERTY_ROOT_LOGGER_LEVEL = "ROOT_LOGGER_LEVEL"; public static final String PROPERTY_SQL_LOGGER_LEVEL = "SQL_LOGGER_LEVEL"; + public static final String PROPERTY_FORMAT = "FORMAT"; - public static final String LEVEL_ROOT_VERBOSE = "DEBUG"; + public static final String LEVEL_ROOT_VERBOSE = "DEBUG"; public static final String LEVEL_ROOT_DEFAULT = "INFO"; + @VisibleForTesting static final String FORMAT_DEFAULT = "%d{HH:mm:ss.SSS} %-5level - %msg%n"; @VisibleForTesting static final String FORMAT_MAVEN = "[%level] [%d{HH:mm:ss.SSS}] %msg%n"; - private Map<String, String> substitutionVariables = Maps.newHashMap(); + Map<String, String> substitutionVariables = Maps.newHashMap(); + LogListener listener = null; - private LoggingConfiguration(@Nullable EnvironmentInformation environment) { + public LoggingConfiguration() { + this(null); + } + + public LoggingConfiguration(@Nullable EnvironmentInformation environment) { setVerbose(false); if (environment != null && "maven".equalsIgnoreCase(environment.getKey())) { setFormat(FORMAT_MAVEN); @@ -57,25 +63,14 @@ public final class LoggingConfiguration { } } - static LoggingConfiguration create(@Nullable EnvironmentInformation environment) { - return new LoggingConfiguration(environment); - } - public LoggingConfiguration setProperties(Map<String, String> properties) { - String logLevel = properties.get("sonar.log.level"); - String deprecatedProfilingLevel = properties.get("sonar.log.profilingLevel"); - boolean verbose = "true".equals(properties.get("sonar.verbose")) || - "DEBUG".equals(logLevel) || "TRACE".equals(logLevel) || - "BASIC".equals(deprecatedProfilingLevel) || "FULL".equals(deprecatedProfilingLevel); - boolean sql = "TRACE".equals(logLevel) || "FULL".equals(deprecatedProfilingLevel); - - setShowSql(sql); - setVerbose(verbose); + setShowSql(properties); + setVerbose(properties); return this; } - - public LoggingConfiguration setStreams(PrintStream out, PrintStream err) { - + + public LoggingConfiguration setListener(@Nullable LogListener listener) { + this.listener = listener; return this; } @@ -83,6 +78,16 @@ public final class LoggingConfiguration { return setRootLevel(verbose ? LEVEL_ROOT_VERBOSE : LEVEL_ROOT_DEFAULT); } + public LoggingConfiguration setVerbose(Map<String, String> properties) { + String logLevel = properties.get("sonar.log.level"); + String deprecatedProfilingLevel = properties.get("sonar.log.profilingLevel"); + boolean verbose = "true".equals(properties.get("sonar.verbose")) || + "DEBUG".equals(logLevel) || "TRACE".equals(logLevel) || + "BASIC".equals(deprecatedProfilingLevel) || "FULL".equals(deprecatedProfilingLevel); + + return setVerbose(verbose); + } + public LoggingConfiguration setRootLevel(String level) { return addSubstitutionVariable(PROPERTY_ROOT_LOGGER_LEVEL, level); } @@ -91,6 +96,14 @@ public final class LoggingConfiguration { return addSubstitutionVariable(PROPERTY_SQL_LOGGER_LEVEL, showSql ? "TRACE" : "WARN"); } + public LoggingConfiguration setShowSql(Map<String, String> properties) { + String logLevel = properties.get("sonar.log.level"); + String deprecatedProfilingLevel = properties.get("sonar.log.profilingLevel"); + boolean sql = "TRACE".equals(logLevel) || "FULL".equals(deprecatedProfilingLevel); + + return setShowSql(sql); + } + @VisibleForTesting LoggingConfiguration setFormat(String format) { return addSubstitutionVariable(PROPERTY_FORMAT, StringUtils.defaultIfBlank(format, FORMAT_DEFAULT)); @@ -101,22 +114,8 @@ public final class LoggingConfiguration { return this; } + @VisibleForTesting String getSubstitutionVariable(String key) { return substitutionVariables.get(key); } - - LoggingConfiguration configure(String classloaderPath) { - Logback.configure(classloaderPath, substitutionVariables); - return this; - } - - LoggingConfiguration configure(File logbackFile) { - Logback.configure(logbackFile, substitutionVariables); - return this; - } - - LoggingConfiguration configure() { - Logback.configure("/org/sonar/batch/bootstrapper/logback.xml", substitutionVariables); - return this; - } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/LoggingConfigurator.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/LoggingConfigurator.java new file mode 100644 index 00000000000..9a74eda6da5 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/LoggingConfigurator.java @@ -0,0 +1,77 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.bootstrapper; + +import org.sonar.home.log.LogListener; + +import ch.qos.logback.core.Appender; +import ch.qos.logback.classic.Level; +import org.apache.commons.lang.StringUtils; + +import java.io.File; + +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import org.slf4j.LoggerFactory; +import org.sonar.core.config.Logback; + +public class LoggingConfigurator { + private LoggingConfigurator() { + } + + public static void apply(LoggingConfiguration conf, File logbackFile) { + Logback.configure(logbackFile, conf.substitutionVariables); + + if (conf.listener != null) { + setCustomRootAppender(conf); + } + } + + public static void apply(LoggingConfiguration conf) { + apply(conf, "/org/sonar/batch/bootstrapper/logback.xml"); + } + + public static void apply(LoggingConfiguration conf, String classloaderPath) { + Logback.configure(classloaderPath, conf.substitutionVariables); + + // if not set, keep default behavior (configured to stdout through the file in classpath) + if (conf.listener != null) { + setCustomRootAppender(conf); + } + } + + private static void setCustomRootAppender(LoggingConfiguration conf) { + Logger logger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); + String pattern = StringUtils.defaultIfBlank(conf.substitutionVariables.get(LoggingConfiguration.PROPERTY_FORMAT), LoggingConfiguration.FORMAT_DEFAULT); + String level = StringUtils.defaultIfBlank(conf.substitutionVariables.get(LoggingConfiguration.PROPERTY_ROOT_LOGGER_LEVEL), LoggingConfiguration.LEVEL_ROOT_DEFAULT); + + logger.detachAndStopAllAppenders(); + logger.addAppender(createAppender(pattern, conf.listener)); + logger.setLevel(Level.toLevel(level)); + } + + private static Appender<ILoggingEvent> createAppender(String pattern, LogListener target) { + LogCallbackAppender appender = new LogCallbackAppender(target); + appender.setName("custom_stream"); + appender.start(); + + return appender; + } +} |