aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-batch/src/main/java/org/sonar
diff options
context:
space:
mode:
authorDuarte Meneses <duarte.meneses@sonarsource.com>2015-06-16 17:37:13 +0200
committerDuarte Meneses <duarte.meneses@sonarsource.com>2015-06-23 15:15:25 +0200
commit792d7eb799efc25d92adcf059acc4c7c9f67d2c7 (patch)
treeecf24200abe9a1586a35893297743004ebc9193d /sonar-batch/src/main/java/org/sonar
parenteba86f1a7feca56d8b39ec7baa6f105eef0fef91 (diff)
downloadsonarqube-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')
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrapper/Batch.java23
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrapper/LogCallbackAppender.java60
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrapper/LoggingConfiguration.java73
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrapper/LoggingConfigurator.java77
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;
+ }
+}