]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8335 support properties to configure log level per JVM
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Tue, 15 Nov 2016 10:17:33 +0000 (11:17 +0100)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Wed, 16 Nov 2016 17:27:52 +0000 (18:27 +0100)
server/sonar-process/src/main/java/org/sonar/process/LogbackHelper.java
server/sonar-search/src/main/java/org/sonar/search/SearchLogging.java
server/sonar-server/src/main/java/org/sonar/ce/log/CeProcessLogging.java
server/sonar-server/src/main/java/org/sonar/server/app/ServerProcessLogging.java
server/sonar-server/src/main/java/org/sonar/server/app/WebServerProcessLogging.java
sonar-application/src/main/java/org/sonar/application/AppLogging.java
sonar-application/src/test/java/org/sonar/application/AppLoggingTest.java

index a669c91a9cee8c2bf330664b646f7f920ed2b0b6..7a86fe5dd4ae2e0e006ef0d2a74959f5da129d39 100644 (file)
@@ -53,11 +53,12 @@ import static org.slf4j.Logger.ROOT_LOGGER_NAME;
 public class LogbackHelper {
 
   private static final String ALL_LOGS_TO_CONSOLE_PROPERTY = "sonar.log.console";
+  private static final String PROCESS_NAME_PLACEHOLDER = "XXXX";
+  private static final String THREAD_ID_PLACEHOLDER = "ZZZZ";
   private static final String SONAR_LOG_LEVEL_PROPERTY = "sonar.log.level";
+  private static final String SONAR_PROCESS_LOG_LEVEL_PROPERTY = "sonar.log.level." + PROCESS_NAME_PLACEHOLDER;
   private static final String ROLLING_POLICY_PROPERTY = "sonar.log.rollingPolicy";
   private static final String MAX_FILES_PROPERTY = "sonar.log.maxFiles";
-  private static final String PROCESS_NAME_PLACEHOLDER = "XXXX";
-  private static final String THREAD_ID_PLACEHOLDER = "ZZZZ";
   private static final String LOG_FORMAT = "%d{yyyy.MM.dd HH:mm:ss} %-5level " + PROCESS_NAME_PLACEHOLDER + "[" + THREAD_ID_PLACEHOLDER + "][%logger{20}] %msg%n";
   public static final Set<Level> ALLOWED_ROOT_LOG_LEVELS = unmodifiableSet(setOf(Level.TRACE, Level.DEBUG, Level.INFO));
 
@@ -164,8 +165,8 @@ public class LogbackHelper {
 
   public String buildLogPattern(LogbackHelper.RootLoggerConfig config) {
     return LOG_FORMAT
-      .replace(PROCESS_NAME_PLACEHOLDER, config.getProcessName())
-      .replace(THREAD_ID_PLACEHOLDER, config.getThreadIdFieldPattern());
+        .replace(PROCESS_NAME_PLACEHOLDER, config.getProcessName())
+        .replace(THREAD_ID_PLACEHOLDER, config.getThreadIdFieldPattern());
   }
 
   /**
@@ -190,12 +191,12 @@ public class LogbackHelper {
   /**
    * Make logback configuration for a process to push all its logs to a log file.
    * <p>
-   *   <ul>
-   *     <li>the file's name will use the prefix defined in {@link RootLoggerConfig#getFileNamePrefix()}.</li>
-   *     <li>the file will follow the rotation policy defined in property {@link #ROLLING_POLICY_PROPERTY} and
-   *     the max number of files defined in property {@link #MAX_FILES_PROPERTY}</li>
-   *     <li>the logs will follow the specified log pattern</li>
-   *   </ul>
+   * <ul>
+   * <li>the file's name will use the prefix defined in {@link RootLoggerConfig#getFileNamePrefix()}.</li>
+   * <li>the file will follow the rotation policy defined in property {@link #ROLLING_POLICY_PROPERTY} and
+   * the max number of files defined in property {@link #MAX_FILES_PROPERTY}</li>
+   * <li>the logs will follow the specified log pattern</li>
+   * </ul>
    * </p>
    *
    * @see #buildLogPattern(RootLoggerConfig)
@@ -254,17 +255,26 @@ public class LogbackHelper {
    *
    * @throws IllegalArgumentException if the value of {@link #SONAR_LOG_LEVEL_PROPERTY} is not one of {@link #ALLOWED_ROOT_LOG_LEVELS}
    */
-  public Level configureRootLogLevel(Props props) {
-    return configureRootLogLevel(props, SONAR_LOG_LEVEL_PROPERTY);
+  public Level configureRootLogLevel(Props props, ProcessId processId) {
+    return configureRootLogLevel(props,
+        SONAR_LOG_LEVEL_PROPERTY,
+        SONAR_PROCESS_LOG_LEVEL_PROPERTY.replace(PROCESS_NAME_PLACEHOLDER, processId.getKey()));
   }
 
   /**
-   * Configure the log level of the root logger reading the value of specified property.
+   * Configure the log level of the root logger reading the value of specified properties. The lowest level will be
+   * applied.
    *
    * @throws IllegalArgumentException if the value of the specified property is not one of {@link #ALLOWED_ROOT_LOG_LEVELS}
    */
-  public Level configureRootLogLevel(Props props, String propertyKey) {
-    Level newLevel = Level.toLevel(props.value(propertyKey, Level.INFO.toString()), Level.INFO);
+  public Level configureRootLogLevel(Props props, String... propertyKeys) {
+    Level newLevel = Level.INFO;
+    for (String propertyKey : propertyKeys) {
+      Level level = Level.toLevel(props.value(propertyKey, Level.INFO.toString()), Level.INFO);
+      if (!level.isGreaterOrEqual(newLevel)) {
+        newLevel = level;
+      }
+    }
     return configureRootLogLevel(newLevel);
   }
 
index 62c710e929aa4086180548c0a282b8e48d3e153c..5a35bd69c65e799d1a2d07c60d6d871a68846146 100644 (file)
@@ -38,7 +38,8 @@ public class SearchLogging {
     String logPattern = helper.buildLogPattern(config);
     helper.configureGlobalFileLog(props, config, logPattern);
     helper.configureForSubprocessGobbler(props, logPattern);
-    helper.configureRootLogLevel(props);
+    // SQ's global log level must not change ES's log level
+    helper.configureRootLogLevel(props, "sonar.log.es.level");
 
     return ctx;
   }
index 201878865dfd078e29c55f38a1b3a4e8149be4bb..e756cd1c251abd6e4db1978d8a04a0633a28ee29 100644 (file)
  */
 package org.sonar.ce.log;
 
+import org.sonar.process.ProcessId;
 import org.sonar.process.Props;
 import org.sonar.server.app.ServerProcessLogging;
 
+import static org.sonar.ce.log.CeLogging.MDC_CE_TASK_UUID;
+
 /**
  * Configure logback for the Compute Engine process. Logs are written to file "ce.log" in SQ's log directory.
  */
 public class CeProcessLogging extends ServerProcessLogging {
 
   public CeProcessLogging() {
-    super("ce", "%X{ceTaskUuid}");
+    super(ProcessId.COMPUTE_ENGINE, "%X{" + MDC_CE_TASK_UUID + "}");
   }
 
   @Override
index ec9f4e565d45b3301e9445d191adc0f326688856..933f6800314cafb36e90f5d68ebd47edb3e6b8e1 100644 (file)
@@ -21,18 +21,19 @@ package org.sonar.server.app;
 
 import ch.qos.logback.classic.LoggerContext;
 import org.sonar.process.LogbackHelper;
+import org.sonar.process.ProcessId;
 import org.sonar.process.Props;
 import org.sonar.server.platform.ServerLogging;
 
 import static org.sonar.process.LogbackHelper.RootLoggerConfig.newRootLoggerConfigBuilder;
 
 public abstract class ServerProcessLogging {
-  private final String processName;
+  private final ProcessId processId;
   private final String threadIdFieldPattern;
   private final LogbackHelper helper = new LogbackHelper();
 
-  protected ServerProcessLogging(String processName, String threadIdFieldPattern) {
-    this.processName = processName;
+  protected ServerProcessLogging(ProcessId processId, String threadIdFieldPattern) {
+    this.processId = processId;
     this.threadIdFieldPattern = threadIdFieldPattern;
   }
 
@@ -52,16 +53,16 @@ public abstract class ServerProcessLogging {
 
   private void configureRootLogger(Props props) {
     LogbackHelper.RootLoggerConfig config = newRootLoggerConfigBuilder()
-      .setProcessName(processName)
+      .setProcessName(processId.getKey())
       .setThreadIdFieldPattern(threadIdFieldPattern)
-      .setFileNamePrefix(processName)
+      .setFileNamePrefix(processId.getKey())
       .build();
     String logPattern = helper.buildLogPattern(config);
 
     helper.configureGlobalFileLog(props, config, logPattern);
     helper.configureForSubprocessGobbler(props, logPattern);
 
-    helper.configureRootLogLevel(props);
+    helper.configureRootLogLevel(props, processId);
     ServerLogging.configureHardcodedLevels(helper);
   }
 
index f10f249db8d96466a44ef097dd2bfa0b9cfd910e..f4f0753f214ceb1c806edfe8cb4cef8b6dfcdc03 100644 (file)
@@ -21,6 +21,7 @@ package org.sonar.server.app;
 
 import java.util.logging.LogManager;
 import org.slf4j.bridge.SLF4JBridgeHandler;
+import org.sonar.process.ProcessId;
 import org.sonar.process.Props;
 
 /**
@@ -29,7 +30,7 @@ import org.sonar.process.Props;
 public class WebServerProcessLogging extends ServerProcessLogging {
 
   public WebServerProcessLogging() {
-    super("web", "%X{UID}");
+    super(ProcessId.WEB_SERVER, "%X{UID}");
   }
 
   @Override
index 7ec122f95ce636c059c4c667d83bbedb432b4c9f..6a5586b93817f649e623bdba6af55db590126cb2 100644 (file)
@@ -25,6 +25,7 @@ import ch.qos.logback.classic.spi.ILoggingEvent;
 import ch.qos.logback.core.ConsoleAppender;
 import ch.qos.logback.core.FileAppender;
 import org.sonar.process.LogbackHelper;
+import org.sonar.process.ProcessId;
 import org.sonar.process.Props;
 
 import static org.slf4j.Logger.ROOT_LOGGER_NAME;
@@ -126,7 +127,7 @@ class AppLogging {
     } else {
       configureWithWrapperWritingToFile(ctx);
     }
-    helper.configureRootLogLevel(props, "sonar.app.log.level");
+    helper.configureRootLogLevel(props, ProcessId.APP);
 
     return ctx;
   }
index 0fccc6e11c787c18abc73809acc020f52042ecd1..d53a868482bb6ccbfa7402a4a8a06536bedcdb2f 100644 (file)
@@ -178,7 +178,7 @@ public class AppLoggingTest {
 
   @Test
   public void root_logger_level_can_be_changed_with_a_property() {
-    props.set("sonar.app.log.level", "TRACE");
+    props.set("sonar.log.level.app", "TRACE");
 
     LoggerContext ctx = underTest.configure(props);
     Logger rootLogger = ctx.getLogger(ROOT_LOGGER_NAME);
@@ -187,7 +187,7 @@ public class AppLoggingTest {
 
   @Test
   public void property_changing_root_logger_level_is_case_insensitive() {
-    props.set("sonar.app.log.level", "trace");
+    props.set("sonar.log.level.app", "trace");
 
     LoggerContext ctx = underTest.configure(props);
     Logger rootLogger = ctx.getLogger(ROOT_LOGGER_NAME);
@@ -196,7 +196,7 @@ public class AppLoggingTest {
 
   @Test
   public void default_to_INFO_if_property_changing_root_logger_level_has_invalid_value() {
-    props.set("sonar.app.log.level", "DodoDouh!");
+    props.set("sonar.log.level.app", "DodoDouh!");
 
     LoggerContext ctx = underTest.configure(props);
     Logger rootLogger = ctx.getLogger(ROOT_LOGGER_NAME);