Browse Source

SONAR-6648 Allow to redirect logs to a custom stream

tags/5.2-RC1
Duarte Meneses 9 years ago
parent
commit
792d7eb799

+ 18
- 5
sonar-batch/src/main/java/org/sonar/batch/bootstrapper/Batch.java View File

@@ -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)}
*/

+ 60
- 0
sonar-batch/src/main/java/org/sonar/batch/bootstrapper/LogCallbackAppender.java View File

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

+ 36
- 37
sonar-batch/src/main/java/org/sonar/batch/bootstrapper/LoggingConfiguration.java View File

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

+ 77
- 0
sonar-batch/src/main/java/org/sonar/batch/bootstrapper/LoggingConfigurator.java View File

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

+ 12
- 1
sonar-batch/src/test/java/org/sonar/batch/bootstrapper/BatchTest.java View File

@@ -19,8 +19,12 @@
*/
package org.sonar.batch.bootstrapper;

import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;

import org.sonar.home.log.LogListener;

import org.junit.Test;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;

@@ -61,4 +65,11 @@ public class BatchTest {
public void loggingConfigurationShouldBeEnabledByDefault() {
assertNotNull(newBatch().getLoggingConfiguration());
}

@Test
public void shoudSetLogListener() {
LogListener listener = mock(LogListener.class);
Batch batch = Batch.builder().setLogListener(listener).build();
assertThat(batch.getLoggingConfiguration().listener).isEqualTo(listener);
}
}

+ 28
- 19
sonar-batch/src/test/java/org/sonar/batch/bootstrapper/LoggingConfigurationTest.java View File

@@ -19,58 +19,67 @@
*/
package org.sonar.batch.bootstrapper;

import org.sonar.home.log.LogListener;

import com.google.common.collect.Maps;
import org.junit.Test;

import java.util.Map;

import static org.mockito.Mockito.mock;
import static org.assertj.core.api.Assertions.assertThat;

public class LoggingConfigurationTest {

@Test
public void testSetVerbose() {
assertThat(LoggingConfiguration.create(null).setVerbose(true)
assertThat(new LoggingConfiguration(null).setVerbose(true)
.getSubstitutionVariable(LoggingConfiguration.PROPERTY_ROOT_LOGGER_LEVEL)).isEqualTo(LoggingConfiguration.LEVEL_ROOT_VERBOSE);

assertThat(LoggingConfiguration.create(null).setVerbose(false)
assertThat(new LoggingConfiguration(null).setVerbose(false)
.getSubstitutionVariable(LoggingConfiguration.PROPERTY_ROOT_LOGGER_LEVEL)).isEqualTo(LoggingConfiguration.LEVEL_ROOT_DEFAULT);

assertThat(LoggingConfiguration.create(null).setRootLevel("ERROR")
assertThat(new LoggingConfiguration(null).setRootLevel("ERROR")
.getSubstitutionVariable(LoggingConfiguration.PROPERTY_ROOT_LOGGER_LEVEL)).isEqualTo("ERROR");
}

@Test
public void shouldNotBeVerboseByDefault() {
assertThat(LoggingConfiguration.create(null)
assertThat(new LoggingConfiguration(null)
.getSubstitutionVariable(LoggingConfiguration.PROPERTY_ROOT_LOGGER_LEVEL)).isEqualTo(LoggingConfiguration.LEVEL_ROOT_DEFAULT);
}

@Test
public void test_log_listener_setter() {
LogListener listener = mock(LogListener.class);
assertThat(new LoggingConfiguration(null).setListener(listener).listener).isEqualTo(listener);
}

@Test
public void test_deprecated_log_properties() {
Map<String, String> properties = Maps.newHashMap();
assertThat(LoggingConfiguration.create(null).setProperties(properties)
assertThat(new LoggingConfiguration(null).setProperties(properties)
.getSubstitutionVariable(LoggingConfiguration.PROPERTY_ROOT_LOGGER_LEVEL)).isEqualTo(LoggingConfiguration.LEVEL_ROOT_DEFAULT);

properties.put("sonar.verbose", "true");
LoggingConfiguration conf = LoggingConfiguration.create(null).setProperties(properties);
LoggingConfiguration conf = new LoggingConfiguration(null).setProperties(properties);
assertThat(conf.getSubstitutionVariable(LoggingConfiguration.PROPERTY_ROOT_LOGGER_LEVEL)).isEqualTo(LoggingConfiguration.LEVEL_ROOT_VERBOSE);
assertThat(conf.getSubstitutionVariable(LoggingConfiguration.PROPERTY_SQL_LOGGER_LEVEL)).isEqualTo("WARN");

properties.put("sonar.verbose", "false");
conf = LoggingConfiguration.create(null).setProperties(properties);
conf = new LoggingConfiguration(null).setProperties(properties);
assertThat(conf.getSubstitutionVariable(LoggingConfiguration.PROPERTY_ROOT_LOGGER_LEVEL)).isEqualTo(LoggingConfiguration.LEVEL_ROOT_DEFAULT);
assertThat(conf.getSubstitutionVariable(LoggingConfiguration.PROPERTY_SQL_LOGGER_LEVEL)).isEqualTo("WARN");

properties.put("sonar.verbose", "false");
properties.put("sonar.log.profilingLevel", "FULL");
conf = LoggingConfiguration.create(null).setProperties(properties);
conf = new LoggingConfiguration(null).setProperties(properties);
assertThat(conf.getSubstitutionVariable(LoggingConfiguration.PROPERTY_ROOT_LOGGER_LEVEL)).isEqualTo("DEBUG");
assertThat(conf.getSubstitutionVariable(LoggingConfiguration.PROPERTY_SQL_LOGGER_LEVEL)).isEqualTo("TRACE");

properties.put("sonar.verbose", "false");
properties.put("sonar.log.profilingLevel", "BASIC");
conf = LoggingConfiguration.create(null).setProperties(properties);
conf = new LoggingConfiguration(null).setProperties(properties);
assertThat(conf.getSubstitutionVariable(LoggingConfiguration.PROPERTY_ROOT_LOGGER_LEVEL)).isEqualTo("DEBUG");
assertThat(conf.getSubstitutionVariable(LoggingConfiguration.PROPERTY_SQL_LOGGER_LEVEL)).isEqualTo("WARN");
}
@@ -78,53 +87,53 @@ public class LoggingConfigurationTest {
@Test
public void test_log_level_property() {
Map<String, String> properties = Maps.newHashMap();
LoggingConfiguration conf = LoggingConfiguration.create(null).setProperties(properties);
LoggingConfiguration conf = new LoggingConfiguration(null).setProperties(properties);
assertThat(conf.getSubstitutionVariable(LoggingConfiguration.PROPERTY_ROOT_LOGGER_LEVEL)).isEqualTo("INFO");
assertThat(conf.getSubstitutionVariable(LoggingConfiguration.PROPERTY_SQL_LOGGER_LEVEL)).isEqualTo("WARN");

properties.put("sonar.log.level", "INFO");
conf = LoggingConfiguration.create(null).setProperties(properties);
conf = new LoggingConfiguration(null).setProperties(properties);
assertThat(conf.getSubstitutionVariable(LoggingConfiguration.PROPERTY_ROOT_LOGGER_LEVEL)).isEqualTo("INFO");
assertThat(conf.getSubstitutionVariable(LoggingConfiguration.PROPERTY_SQL_LOGGER_LEVEL)).isEqualTo("WARN");

properties.put("sonar.log.level", "DEBUG");
conf = LoggingConfiguration.create(null).setProperties(properties);
conf = new LoggingConfiguration(null).setProperties(properties);
assertThat(conf.getSubstitutionVariable(LoggingConfiguration.PROPERTY_ROOT_LOGGER_LEVEL)).isEqualTo("DEBUG");
assertThat(conf.getSubstitutionVariable(LoggingConfiguration.PROPERTY_SQL_LOGGER_LEVEL)).isEqualTo("WARN");

properties.put("sonar.log.level", "TRACE");
conf = LoggingConfiguration.create(null).setProperties(properties);
conf = new LoggingConfiguration(null).setProperties(properties);
assertThat(conf.getSubstitutionVariable(LoggingConfiguration.PROPERTY_ROOT_LOGGER_LEVEL)).isEqualTo("DEBUG");
assertThat(conf.getSubstitutionVariable(LoggingConfiguration.PROPERTY_SQL_LOGGER_LEVEL)).isEqualTo("TRACE");
}

@Test
public void testDefaultFormat() {
assertThat(LoggingConfiguration.create(null)
assertThat(new LoggingConfiguration(null)
.getSubstitutionVariable(LoggingConfiguration.PROPERTY_FORMAT)).isEqualTo(LoggingConfiguration.FORMAT_DEFAULT);
}

@Test
public void testMavenFormat() {
assertThat(LoggingConfiguration.create(new EnvironmentInformation("maven", "1.0"))
assertThat(new LoggingConfiguration(new EnvironmentInformation("maven", "1.0"))
.getSubstitutionVariable(LoggingConfiguration.PROPERTY_FORMAT)).isEqualTo(LoggingConfiguration.FORMAT_MAVEN);
}

@Test
public void testSetFormat() {
assertThat(LoggingConfiguration.create(null).setFormat("%d %level")
assertThat(new LoggingConfiguration(null).setFormat("%d %level")
.getSubstitutionVariable(LoggingConfiguration.PROPERTY_FORMAT)).isEqualTo("%d %level");
}

@Test
public void shouldNotSetBlankFormat() {
assertThat(LoggingConfiguration.create(null).setFormat(null)
assertThat(new LoggingConfiguration(null).setFormat(null)
.getSubstitutionVariable(LoggingConfiguration.PROPERTY_FORMAT)).isEqualTo(LoggingConfiguration.FORMAT_DEFAULT);

assertThat(LoggingConfiguration.create(null).setFormat("")
assertThat(new LoggingConfiguration(null).setFormat("")
.getSubstitutionVariable(LoggingConfiguration.PROPERTY_FORMAT)).isEqualTo(LoggingConfiguration.FORMAT_DEFAULT);

assertThat(LoggingConfiguration.create(null).setFormat(" ")
assertThat(new LoggingConfiguration(null).setFormat(" ")
.getSubstitutionVariable(LoggingConfiguration.PROPERTY_FORMAT)).isEqualTo(LoggingConfiguration.FORMAT_DEFAULT);
}
}

+ 139
- 0
sonar-batch/src/test/java/org/sonar/batch/bootstrapper/LoggingConfiguratorTest.java View File

@@ -0,0 +1,139 @@
/*
* 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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;

import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
import org.junit.Before;

public class LoggingConfiguratorTest {
private static final String TEST_STR = "foo";
private LoggingConfiguration conf = new LoggingConfiguration();
private ByteArrayOutputStream out;
private SimpleLogListener listener;

@Before
public void setUp() {
out = new ByteArrayOutputStream();
conf = new LoggingConfiguration();
listener = new SimpleLogListener();
}

private class SimpleLogListener implements LogListener {
String msg;
Level level;

@Override
public void log(String msg, Level level) {
this.msg = msg;
this.level = level;
}
}

@Test
public void testCustomAppender() throws UnsupportedEncodingException {
conf.setListener(listener);
LoggingConfigurator.apply(conf);

Logger logger = LoggerFactory.getLogger(this.getClass());
logger.info(TEST_STR);

assertThat(listener.msg).endsWith(TEST_STR);
assertThat(listener.level).isEqualTo(LogListener.Level.INFO);
}

@Test
public void testNoStdout() throws UnsupportedEncodingException {
System.setOut(new PrintStream(out, false, StandardCharsets.UTF_8.name()));
conf.setListener(listener);
LoggingConfigurator.apply(conf);

Logger logger = LoggerFactory.getLogger(this.getClass());

logger.error(TEST_STR);
logger.info(TEST_STR);
logger.debug(TEST_STR);
assertThat(out.size()).isEqualTo(0);
}

@Test
public void testFormatNoEffect() throws UnsupportedEncodingException {
conf.setListener(listener);
conf.setFormat("%t");

LoggingConfigurator.apply(conf);
Logger logger = LoggerFactory.getLogger(this.getClass());

logger.info("info");

assertThat(listener.msg).isEqualTo("info");
}

@Test
public void testSqlClasspath() throws UnsupportedEncodingException {
String classpath = "/org/sonar/batch/bootstrapper/logback.xml";

conf.setListener(listener);
conf.setShowSql(true);

LoggingConfigurator.apply(conf, classpath);

Logger logger = LoggerFactory.getLogger("java.sql");
logger.info("foo");

assertThat(listener.msg).endsWith(TEST_STR);
}

@Test
public void testNoListener() throws UnsupportedEncodingException {
System.setOut(new PrintStream(out, false, StandardCharsets.UTF_8.name()));
LoggingConfigurator.apply(conf);

Logger logger = LoggerFactory.getLogger(this.getClass());
logger.info("info");

assertThat(new String(out.toByteArray(), StandardCharsets.UTF_8)).contains("info");
}

@Test
public void testNoSqlClasspath() throws UnsupportedEncodingException {
String classpath = "/org/sonar/batch/bootstrapper/logback.xml";

conf.setListener(listener);
conf.setShowSql(false);

LoggingConfigurator.apply(conf, classpath);

Logger logger = LoggerFactory.getLogger("java.sql");
logger.info("foo");

assertThat(listener.msg).isNull();
}
}

+ 102
- 0
sonar-batch/src/test/java/org/sonar/batch/bootstrapper/PrintStreamTest.java View File

@@ -0,0 +1,102 @@
/*
* 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 ch.qos.logback.core.encoder.EchoEncoder;
import ch.qos.logback.classic.spi.ILoggingEvent;
import org.mockito.Matchers;
import ch.qos.logback.core.encoder.Encoder;
import ch.qos.logback.core.Context;
import org.junit.Test;
import org.junit.Before;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;

import static org.assertj.core.api.Assertions.assertThat;

import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.mock;

public class PrintStreamTest {
private static final String TEST_STR = "foo";

private ByteArrayOutputStream os;
private PrintStream stream;
private PrintStreamAppender<ILoggingEvent> appender;
private Context context = mock(Context.class);

private Encoder<ILoggingEvent> encoder = mock(Encoder.class);
private ILoggingEvent event = mock(ILoggingEvent.class);

@Before
public void setUp() {
os = new ByteArrayOutputStream();
stream = new PrintStream(os);

appender = new PrintStreamAppender<ILoggingEvent>(stream);
when(event.getMessage()).thenReturn(TEST_STR);
when(event.toString()).thenReturn(TEST_STR);
}

@Test
public void testNullStream() {
appender.setContext(mock(Context.class));
appender.setEncoder(encoder);
appender.setTarget(null);
appender.start();
appender.doAppend(event);

verifyNoMoreInteractions(encoder);
}

@Test
public void testEncoder() throws IOException {
appender.setContext(mock(Context.class));
appender.setEncoder(encoder);
appender.start();
appender.doAppend(event);

verify(encoder, times(1)).init(Matchers.notNull(OutputStream.class));
verify(encoder, times(1)).doEncode(event);

}

@Test
public void testWrite() {
encoder = new EchoEncoder<>();
encoder.setContext(context);
encoder.start();

appender.setContext(mock(Context.class));
appender.setEncoder(encoder);
appender.setTarget(stream);
appender.start();

appender.doAppend(event);

assertThat(os.toString()).isEqualTo(TEST_STR + System.lineSeparator());
}
}

sonar-plugin-api/src/main/java/org/sonar/api/utils/ProjectTempFolder.java → sonar-home/src/main/java/org/sonar/home/log/LogListener.java View File

@@ -17,38 +17,12 @@
* 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.api.utils;

import javax.annotation.Nullable;

import java.io.File;

import org.sonar.api.batch.BatchSide;


/**
* Use this component to deal with temp files/folders that have a scope linked to each
* project analysis.
* Root location will typically be the working directory (see sonar.working.directory)

* @since 5.2
*
*/
@BatchSide
public interface ProjectTempFolder {

/**
* Create a directory in temp folder with a random unique name.
*/
File newDir();

/**
* Create a directory in temp folder using provided name.
*/
File newDir(String name);

File newFile();

File newFile(@Nullable String prefix, @Nullable String suffix);

}
package org.sonar.home.log;

public interface LogListener {
public void log(String msg, Level level);
public static enum Level {
ERROR, WARN, INFO, DEBUG, TRACE;
}
}

Loading…
Cancel
Save