]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8422 add visible error in sonar.log when DB is not ok
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Wed, 30 Nov 2016 16:31:23 +0000 (17:31 +0100)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Thu, 1 Dec 2016 15:17:51 +0000 (16:17 +0100)
server/sonar-ce/src/main/java/org/sonar/ce/app/WebServerBarrier.java
server/sonar-server/src/main/java/org/sonar/server/app/ServerProcessLogging.java
server/sonar-server/src/main/java/org/sonar/server/platform/DatabaseServerCompatibility.java
server/sonar-server/src/test/java/org/sonar/ce/log/CeProcessLoggingTest.java
server/sonar-server/src/test/java/org/sonar/server/app/WebServerProcessLoggingTest.java
server/sonar-server/src/test/java/org/sonar/server/platform/DatabaseServerCompatibilityTest.java

index 86d4419c7b70eddb5b4e0c27efa113efc737a1ee..2053d9325f39fa05c3723b724c35ca657f22887f 100644 (file)
@@ -25,6 +25,8 @@ import org.sonar.api.utils.log.Loggers;
 import org.sonar.process.DefaultProcessCommands;
 import org.sonar.process.ProcessId;
 
+import static org.sonar.server.app.ServerProcessLogging.STARTUP_LOGGER_NAME;
+
 /**
  * Waits for the web server to be operational (started and datastores up-to-date)
  */
@@ -47,6 +49,7 @@ class WebServerBarrier implements StartupBarrier {
         return true;
       }
 
+      Loggers.get(STARTUP_LOGGER_NAME).info("Compute Engine startup is on hold. Waiting for Web Server to be operational.");
       LOG.info("Waiting for Web Server to be operational...");
       Logger logarithmicLogger = LogarithmicLogger.from(LOG).applyingCallRatio(CALL_RATIO).build();
       while (!processCommands.isOperational()) {
index baeaa88d31878cc1cf52955b058a8304c27e3cd5..f3814406a3a65841034e5738e5c501dfb6f56316 100644 (file)
 package org.sonar.server.app;
 
 import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
 import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.ConsoleAppender;
 import com.google.common.collect.ImmutableSet;
 import java.util.Set;
-import org.sonar.process.logging.LogLevelConfig;
-import org.sonar.process.logging.LogbackHelper;
 import org.sonar.process.ProcessId;
 import org.sonar.process.Props;
+import org.sonar.process.logging.LogLevelConfig;
+import org.sonar.process.logging.LogbackHelper;
 import org.sonar.process.logging.RootLoggerConfig;
 
 import static org.sonar.process.logging.RootLoggerConfig.newRootLoggerConfigBuilder;
 
 public abstract class ServerProcessLogging {
+
+  public static final String STARTUP_LOGGER_NAME = "startup";
   protected static final Set<String> JMX_RMI_LOGGER_NAMES = ImmutableSet.of(
     "javax.management.remote.timeout",
     "javax.management.remote.misc",
@@ -80,8 +85,10 @@ public abstract class ServerProcessLogging {
     ctx.reset();
 
     helper.enableJulChangePropagation(ctx);
+
     configureRootLogger(props);
     helper.apply(logLevelConfig, props);
+    configureDirectToConsoleLoggers(ctx, STARTUP_LOGGER_NAME);
 
     extendConfigure();
 
@@ -107,4 +114,23 @@ public abstract class ServerProcessLogging {
     helper.configureForSubprocessGobbler(props, logPattern);
   }
 
+  /**
+   * Setup one or more specified loggers to be non additive and to print to System.out which will be caught by the Main
+   * Process and written to sonar.log.
+   */
+  private void configureDirectToConsoleLoggers(LoggerContext context, String... loggerNames) {
+    RootLoggerConfig config = newRootLoggerConfigBuilder()
+      .setProcessId(ProcessId.APP)
+      .setThreadIdFieldPattern("")
+      .build();
+    String logPattern = helper.buildLogPattern(config);
+    ConsoleAppender<ILoggingEvent> consoleAppender = helper.newConsoleAppender(context, "CONSOLE", logPattern);
+
+    for (String loggerName : loggerNames) {
+      Logger consoleLogger = context.getLogger(loggerName);
+      consoleLogger.setAdditive(false);
+      consoleLogger.addAppender(consoleAppender);
+    }
+  }
+
 }
index 89da490e50efb0a77db8c00453222f404e2cdaef..db5548a95fe85fc3300483fbfaa37aadf1ad387f 100644 (file)
@@ -24,8 +24,11 @@ import org.sonar.api.utils.MessageException;
 import org.sonar.api.utils.log.Loggers;
 import org.sonar.db.version.DatabaseVersion;
 
+import static org.sonar.server.app.ServerProcessLogging.STARTUP_LOGGER_NAME;
+
 public class DatabaseServerCompatibility implements Startable {
 
+  private static final String HIGHLIGHTER = "################################################################################";
   private DatabaseVersion version;
 
   public DatabaseServerCompatibility(DatabaseVersion version) {
@@ -43,7 +46,12 @@ public class DatabaseServerCompatibility implements Startable {
       if (currentVersion != null && currentVersion < DatabaseVersion.MIN_UPGRADE_VERSION) {
         throw MessageException.of("Current version is too old. Please upgrade to Long Term Support version firstly.");
       }
-      Loggers.get(DatabaseServerCompatibility.class).warn("Database must be upgraded. Please backup database and browse /setup");
+      String msg = "Database must be upgraded. Please backup database and browse /setup";
+      Loggers.get(DatabaseServerCompatibility.class).warn(msg);
+      Loggers.get(STARTUP_LOGGER_NAME).warn('\n'
+        + HIGHLIGHTER + '\n'
+        + "      " + msg
+        + '\n' + HIGHLIGHTER);
     }
   }
 
index 0058688f0560a8ed3182436c2118e5e85976f6bb..451aac9e379e8a20b3a44f00b37ce3a2f39590bc 100644 (file)
@@ -25,6 +25,7 @@ import ch.qos.logback.classic.LoggerContext;
 import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
 import ch.qos.logback.classic.spi.ILoggingEvent;
 import ch.qos.logback.core.Appender;
+import ch.qos.logback.core.ConsoleAppender;
 import ch.qos.logback.core.FileAppender;
 import ch.qos.logback.core.joran.spi.JoranException;
 import java.io.File;
@@ -74,6 +75,21 @@ public class CeProcessLoggingTest {
     assertThat(appender).isNull();
   }
 
+  @Test
+  public void startup_logger_prints_to_only_to_system_out() {
+    LoggerContext ctx = underTest.configure(props);
+
+    Logger startup = ctx.getLogger("startup");
+    assertThat(startup.isAdditive()).isFalse();
+    Appender appender = startup.getAppender("CONSOLE");
+    assertThat(appender).isInstanceOf(ConsoleAppender.class);
+    ConsoleAppender<ILoggingEvent> consoleAppender = (ConsoleAppender<ILoggingEvent>) appender;
+    assertThat(consoleAppender.getTarget()).isEqualTo("System.out");
+    assertThat(consoleAppender.getEncoder()).isInstanceOf(PatternLayoutEncoder.class);
+    PatternLayoutEncoder patternEncoder = (PatternLayoutEncoder) consoleAppender.getEncoder();
+    assertThat(patternEncoder.getPattern()).isEqualTo("%d{yyyy.MM.dd HH:mm:ss} %-5level app[][%logger{20}] %msg%n");
+  }
+
   @Test
   public void log_to_ce_file() {
     LoggerContext ctx = underTest.configure(props);
index 02dba16937ae284de072f7982580c90823703723..24d661249e7df7bd77cbde9bae116bd8bf2ea8e5 100644 (file)
@@ -25,6 +25,7 @@ import ch.qos.logback.classic.LoggerContext;
 import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
 import ch.qos.logback.classic.spi.ILoggingEvent;
 import ch.qos.logback.core.Appender;
+import ch.qos.logback.core.ConsoleAppender;
 import ch.qos.logback.core.FileAppender;
 import ch.qos.logback.core.joran.spi.JoranException;
 import java.io.File;
@@ -74,6 +75,21 @@ public class WebServerProcessLoggingTest {
     assertThat(appender).isNull();
   }
 
+  @Test
+  public void startup_logger_prints_to_only_to_system_out() {
+    LoggerContext ctx = underTest.configure(props);
+
+    Logger startup = ctx.getLogger("startup");
+    assertThat(startup.isAdditive()).isFalse();
+    Appender appender = startup.getAppender("CONSOLE");
+    assertThat(appender).isInstanceOf(ConsoleAppender.class);
+    ConsoleAppender<ILoggingEvent> consoleAppender = (ConsoleAppender<ILoggingEvent>) appender;
+    assertThat(consoleAppender.getTarget()).isEqualTo("System.out");
+    assertThat(consoleAppender.getEncoder()).isInstanceOf(PatternLayoutEncoder.class);
+    PatternLayoutEncoder patternEncoder = (PatternLayoutEncoder) consoleAppender.getEncoder();
+    assertThat(patternEncoder.getPattern()).isEqualTo("%d{yyyy.MM.dd HH:mm:ss} %-5level app[][%logger{20}] %msg%n");
+  }
+
   @Test
   public void log_to_web_file() {
     LoggerContext ctx = underTest.configure(props);
index 5bda5ae0eb518eaebda69ec46cedd2a22b679da5..2749a9b570a03298833ea8a8d85ad075b458a164 100644 (file)
@@ -23,8 +23,11 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.utils.MessageException;
+import org.sonar.api.utils.log.LogTester;
+import org.sonar.api.utils.log.LoggerLevel;
 import org.sonar.db.version.DatabaseVersion;
 
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -32,6 +35,8 @@ public class DatabaseServerCompatibilityTest {
 
   @Rule
   public ExpectedException thrown = ExpectedException.none();
+  @Rule
+  public LogTester logTester = new LogTester();
 
   @Test
   public void fail_if_requires_downgrade() {
@@ -60,8 +65,13 @@ public class DatabaseServerCompatibilityTest {
     when(version.getStatus()).thenReturn(DatabaseVersion.Status.REQUIRES_UPGRADE);
     when(version.getVersion()).thenReturn(DatabaseVersion.MIN_UPGRADE_VERSION);
     new DatabaseServerCompatibility(version).start();
-    // oh well... how to simply test logging ?
-    // Let's assume that this test verifies that no error is raised.
+
+    assertThat(logTester.logs()).hasSize(2);
+    assertThat(logTester.logs(LoggerLevel.WARN)).contains(
+      "Database must be upgraded. Please backup database and browse /setup",
+      "\n################################################################################\n" +
+        "      Database must be upgraded. Please backup database and browse /setup\n" +
+        "################################################################################");
   }
 
   @Test