aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-process
diff options
context:
space:
mode:
authorJacek <jacek.poreda@sonarsource.com>2021-08-05 09:30:32 +0200
committersonartech <sonartech@sonarsource.com>2021-08-11 20:08:08 +0000
commitbb03cec435d188cc7fd5576eced84eaa2c634212 (patch)
treeb3f3af3322a77964aa06ef4e5e3e2d46208f1703 /server/sonar-process
parent8bda059b8117593fac19e34cafb41c5d0be76a54 (diff)
downloadsonarqube-bb03cec435d188cc7fd5576eced84eaa2c634212.tar.gz
sonarqube-bb03cec435d188cc7fd5576eced84eaa2c634212.zip
SONAR-15243 Enable JSON logging on Elasticsearch process
Diffstat (limited to 'server/sonar-process')
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/ProcessProperties.java14
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/logging/Log4JPropertiesBuilder.java181
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/logging/LogbackHelper.java3
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/logging/LogbackJsonLayout.java5
-rw-r--r--server/sonar-process/src/test/java/org/sonar/process/logging/Log4JPropertiesBuilderTest.java449
-rw-r--r--server/sonar-process/src/test/java/org/sonar/process/logging/LogbackHelperTest.java2
-rw-r--r--server/sonar-process/src/test/java/org/sonar/process/logging/LogbackJsonLayoutTest.java26
7 files changed, 452 insertions, 228 deletions
diff --git a/server/sonar-process/src/main/java/org/sonar/process/ProcessProperties.java b/server/sonar-process/src/main/java/org/sonar/process/ProcessProperties.java
index 72c99d1b2d0..fe9e97951e8 100644
--- a/server/sonar-process/src/main/java/org/sonar/process/ProcessProperties.java
+++ b/server/sonar-process/src/main/java/org/sonar/process/ProcessProperties.java
@@ -45,6 +45,7 @@ import static org.sonar.process.ProcessProperties.Property.SEARCH_PORT;
* They are almost all the properties defined in conf/sonar.properties.
*/
public class ProcessProperties {
+ private static final String DEFAULT_FALSE = Boolean.FALSE.toString();
private final ServiceLoaderWrapper serviceLoaderWrapper;
@@ -75,6 +76,7 @@ public class ProcessProperties {
LOG_ROLLING_POLICY("sonar.log.rollingPolicy"),
LOG_MAX_FILES("sonar.log.maxFiles"),
LOG_CONSOLE("sonar.log.console"),
+ LOG_JSON_OUTPUT("sonar.log.jsonOutput", DEFAULT_FALSE),
SEARCH_HOST("sonar.search.host"),
SEARCH_PORT("sonar.search.port"),
@@ -113,8 +115,8 @@ public class ProcessProperties {
SOCKS_PROXY_HOST("socksProxyHost"),
SOCKS_PROXY_PORT("socksProxyPort"),
- CLUSTER_ENABLED("sonar.cluster.enabled", "false"),
- CLUSTER_KUBERNETES("sonar.cluster.kubernetes", "false"),
+ CLUSTER_ENABLED("sonar.cluster.enabled", DEFAULT_FALSE),
+ CLUSTER_KUBERNETES("sonar.cluster.kubernetes", DEFAULT_FALSE),
CLUSTER_NODE_TYPE("sonar.cluster.node.type"),
CLUSTER_SEARCH_HOSTS("sonar.cluster.search.hosts"),
CLUSTER_HZ_HOSTS("sonar.cluster.hosts"),
@@ -140,14 +142,14 @@ public class ProcessProperties {
CLUSTER_NODE_ES_PORT("sonar.cluster.node.es.port"),
AUTH_JWT_SECRET("sonar.auth.jwtBase64Hs256Secret"),
- SONAR_WEB_SSO_ENABLE("sonar.web.sso.enable", "false"),
+ SONAR_WEB_SSO_ENABLE("sonar.web.sso.enable", DEFAULT_FALSE),
SONAR_WEB_SSO_LOGIN_HEADER("sonar.web.sso.loginHeader", "X-Forwarded-Login"),
SONAR_WEB_SSO_NAME_HEADER("sonar.web.sso.nameHeader", "X-Forwarded-Name"),
SONAR_WEB_SSO_EMAIL_HEADER("sonar.web.sso.emailHeader", "X-Forwarded-Email"),
SONAR_WEB_SSO_GROUPS_HEADER("sonar.web.sso.groupsHeader", "X-Forwarded-Groups"),
SONAR_WEB_SSO_REFRESH_INTERVAL_IN_MINUTES("sonar.web.sso.refreshIntervalInMinutes", "5"),
SONAR_SECURITY_REALM("sonar.security.realm"),
- SONAR_AUTHENTICATOR_IGNORE_STARTUP_FAILURE("sonar.authenticator.ignoreStartupFailure", "false"),
+ SONAR_AUTHENTICATOR_IGNORE_STARTUP_FAILURE("sonar.authenticator.ignoreStartupFailure", DEFAULT_FALSE),
LDAP_SERVERS("ldap.servers"),
LDAP_URL("ldap.url"),
@@ -172,7 +174,7 @@ public class ProcessProperties {
SONAR_UPDATECENTER_ACTIVATE("sonar.updatecenter.activate", "true"),
- SONARCLOUD_ENABLED("sonar.sonarcloud.enabled", "false"),
+ SONARCLOUD_ENABLED("sonar.sonarcloud.enabled", DEFAULT_FALSE),
SONARCLOUD_HOMEPAGE_URL("sonar.homepage.url", ""),
SONAR_PRISMIC_ACCESS_TOKEN("sonar.prismic.accessToken", ""),
SONAR_ANALYTICS_GTM_TRACKING_ID("sonar.analytics.gtm.trackingId", ""),
@@ -184,7 +186,7 @@ public class ProcessProperties {
ENABLE_STOP_COMMAND("sonar.enableStopCommand"),
// whether the blue/green deployment of server is enabled
- BLUE_GREEN_ENABLED("sonar.blueGreenEnabled", "false");
+ BLUE_GREEN_ENABLED("sonar.blueGreenEnabled", DEFAULT_FALSE);
/**
* Properties that are defined for each LDAP server from the `ldap.servers` property
diff --git a/server/sonar-process/src/main/java/org/sonar/process/logging/Log4JPropertiesBuilder.java b/server/sonar-process/src/main/java/org/sonar/process/logging/Log4JPropertiesBuilder.java
index 10ec6e88c02..c450d940d62 100644
--- a/server/sonar-process/src/main/java/org/sonar/process/logging/Log4JPropertiesBuilder.java
+++ b/server/sonar-process/src/main/java/org/sonar/process/logging/Log4JPropertiesBuilder.java
@@ -26,23 +26,34 @@ import java.util.Objects;
import java.util.Properties;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import javax.annotation.Nullable;
import org.apache.commons.lang.StringUtils;
import org.sonar.process.MessageException;
import org.sonar.process.ProcessProperties;
import org.sonar.process.Props;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
import static java.lang.String.format;
import static java.lang.String.valueOf;
+import static java.util.Optional.ofNullable;
import static org.sonar.process.ProcessProperties.Property.LOG_LEVEL;
import static org.sonar.process.ProcessProperties.Property.LOG_MAX_FILES;
import static org.sonar.process.ProcessProperties.Property.LOG_ROLLING_POLICY;
public class Log4JPropertiesBuilder extends AbstractLogHelper {
+ private static final String PATTERN_LAYOUT = "PatternLayout";
private static final String ROOT_LOGGER_NAME = "rootLogger";
private static final int UNLIMITED_MAX_FILES = 100_000;
private final Properties log4j2Properties = new Properties();
private final Props props;
+ private RootLoggerConfig config;
+ private String logPattern;
+ private boolean allLogsToConsole;
+ private File logDir;
+ private LogLevelConfig logLevelConfig;
+ private boolean jsonOutput;
public Log4JPropertiesBuilder(Props props) {
super("%logger{1.}");
@@ -55,20 +66,64 @@ public class Log4JPropertiesBuilder extends AbstractLogHelper {
return ROOT_LOGGER_NAME;
}
- public Properties get() {
+ public Log4JPropertiesBuilder rootLoggerConfig(RootLoggerConfig config) {
+ this.config = config;
+ return this;
+ }
+
+ public Log4JPropertiesBuilder logPattern(String logPattern) {
+ this.logPattern = logPattern;
+ return this;
+ }
+
+ public Log4JPropertiesBuilder enableAllLogsToConsole(boolean allLogsToConsoleEnabled) {
+ allLogsToConsole = allLogsToConsoleEnabled;
+ return this;
+ }
+
+ public Log4JPropertiesBuilder jsonOutput(boolean jsonOutput) {
+ this.jsonOutput = jsonOutput;
+ return this;
+ }
+
+ public Log4JPropertiesBuilder logDir(File logDir) {
+ this.logDir = logDir;
+ return this;
+ }
+
+ public Log4JPropertiesBuilder logLevelConfig(LogLevelConfig logLevelConfig) {
+ this.logLevelConfig = logLevelConfig;
+ return this;
+ }
+
+ public Properties build() {
+ checkNotNull(logDir, config);
+ checkState(jsonOutput || (logPattern != null), "log pattern must be specified if not using json output");
+ configureGlobalFileLog();
+ if (allLogsToConsole) {
+ configureGlobalStdoutLog();
+ }
+
+ ofNullable(logLevelConfig).ifPresent(this::applyLogLevelConfiguration);
+
Properties res = new Properties();
res.putAll(log4j2Properties);
return res;
}
- public void internalLogLevel(Level level) {
+ public Log4JPropertiesBuilder internalLogLevel(Level level) {
putProperty("status", level.toString());
+ return this;
}
private void putProperty(String key, String value) {
log4j2Properties.put(key, value);
}
+ private void putProperty(String prefix, String key, @Nullable String value) {
+ log4j2Properties.put(prefix + key, value);
+ }
+
/**
* Make log4j2 configuration for a process to push all its logs to a log file.
* <p>
@@ -82,31 +137,17 @@ public class Log4JPropertiesBuilder extends AbstractLogHelper {
*
* @see #buildLogPattern(RootLoggerConfig)
*/
- public void configureGlobalFileLog(RootLoggerConfig config, File logDir, String logPattern) {
- String appenderRef = writeFileAppender(config, logDir, logPattern);
-
- putProperty(ROOT_LOGGER_NAME + ".appenderRef." + appenderRef + ".ref", appenderRef);
- }
-
- private String writeFileAppender(RootLoggerConfig config, File logDir, String logPattern) {
+ private void configureGlobalFileLog() {
String appenderName = "file_" + config.getProcessId().getLogFilenamePrefix();
RollingPolicy rollingPolicy = createRollingPolicy(logDir, config.getProcessId().getLogFilenamePrefix());
- FileAppender appender = new FileAppender(appenderName, rollingPolicy, logPattern);
- appender.writeAppenderProperties();
- return appender.getAppenderRef();
+ writeFileAppender(appenderName, rollingPolicy, logPattern, jsonOutput);
+ putProperty(ROOT_LOGGER_NAME + ".appenderRef." + appenderName + ".ref", appenderName);
}
- public void configureGlobalStdoutLog(String logPattern) {
- String appenderRef = writeStdoutAppender(logPattern);
-
- putProperty(ROOT_LOGGER_NAME + ".appenderRef." + appenderRef + ".ref", appenderRef);
- }
-
- private String writeStdoutAppender(String logPattern) {
+ private void configureGlobalStdoutLog() {
String appenderName = "stdout";
- ConsoleAppender appender = new ConsoleAppender(appenderName, logPattern);
- appender.writeAppenderProperties();
- return appender.getAppenderRef();
+ writeConsoleAppender(appenderName, logPattern, jsonOutput);
+ putProperty(ROOT_LOGGER_NAME + ".appenderRef." + appenderName + ".ref", appenderName);
}
private RollingPolicy createRollingPolicy(File logDir, String filenamePrefix) {
@@ -127,7 +168,7 @@ public class Log4JPropertiesBuilder extends AbstractLogHelper {
}
}
- public void apply(LogLevelConfig logLevelConfig) {
+ private void applyLogLevelConfiguration(LogLevelConfig logLevelConfig) {
if (!ROOT_LOGGER_NAME.equals(logLevelConfig.getRootLoggerName())) {
throw new IllegalArgumentException("Value of LogLevelConfig#rootLoggerName must be \"" + ROOT_LOGGER_NAME + "\"");
}
@@ -170,61 +211,59 @@ public class Log4JPropertiesBuilder extends AbstractLogHelper {
}
}
- private class FileAppender {
- private final String prefix;
- private final String appenderName;
- private final RollingPolicy rollingPolicy;
- private final String logPattern;
-
- private FileAppender(String appenderName, RollingPolicy rollingPolicy, String logPattern) {
- this.prefix = "appender." + appenderName + ".";
- this.appenderName = appenderName;
- this.rollingPolicy = rollingPolicy;
- this.logPattern = logPattern;
- }
-
- void writeAppenderProperties() {
- put("name", appenderName);
- put("layout.type", "PatternLayout");
- put("layout.pattern", logPattern);
-
- rollingPolicy.writePolicy(this.prefix);
- }
-
- void put(String key, String value) {
- Log4JPropertiesBuilder.this.putProperty(this.prefix + key, value);
- }
-
- String getAppenderRef() {
- return appenderName;
- }
+ private void writeFileAppender(String appenderName, RollingPolicy rollingPolicy, @Nullable String logPattern, boolean jsonOutput) {
+ String prefix = "appender." + appenderName + ".";
+ putProperty(prefix, "name", appenderName);
+ writeAppenderLayout(logPattern, jsonOutput, prefix);
+ rollingPolicy.writePolicy(prefix);
}
- private class ConsoleAppender {
- private final String prefix;
- private final String appenderName;
- private final String logPattern;
+ private void writeConsoleAppender(String appenderName, @Nullable String logPattern, boolean jsonOutput) {
+ String prefix = "appender." + appenderName + ".";
+ putProperty(prefix, "type", "Console");
+ putProperty(prefix, "name", appenderName);
+ writeAppenderLayout(logPattern, jsonOutput, prefix);
+ }
- private ConsoleAppender(String appenderName, String logPattern) {
- this.prefix = "appender." + appenderName + ".";
- this.appenderName = appenderName;
- this.logPattern = logPattern;
+ private void writeAppenderLayout(@Nullable String logPattern, boolean jsonOutput, String prefix) {
+ putProperty(prefix, "layout.type", PATTERN_LAYOUT);
+ if (!jsonOutput) {
+ putProperty(prefix, "layout.pattern", logPattern);
+ } else {
+ putProperty(prefix, "layout.pattern", getJsonPattern());
}
+ }
- void writeAppenderProperties() {
- put("type", "Console");
- put("name", appenderName);
- put("layout.type", "PatternLayout");
- put("layout.pattern", logPattern);
- }
+ /**
+ * json pattern based on https://github.com/elastic/elasticsearch/blob/7.13/server/src/main/java/org/elasticsearch/common/logging/ESJsonLayout.java
+ */
+ private String getJsonPattern() {
+ return "{"
+ + jsonKey("process")
+ + inQuotes(config.getProcessId().getKey())
+ + ","
+ + jsonKey("timestamp")
+ + inQuotes("%d{yyyy-MM-dd'T'HH:mm:ss.SSSZZ}")
+ + ","
+ + jsonKey("severity")
+ + inQuotes("%p")
+ + ","
+ + jsonKey("logger")
+ + inQuotes("%c{1.}")
+ + ","
+ + jsonKey("message")
+ + inQuotes("%notEmpty{%enc{%marker}{JSON} }%enc{%.-10000m}{JSON}")
+ + "%exceptionAsJson "
+ + "}"
+ + System.lineSeparator();
+ }
- void put(String key, String value) {
- Log4JPropertiesBuilder.this.putProperty(this.prefix + key, value);
- }
+ private static CharSequence jsonKey(String s) {
+ return inQuotes(s) + ": ";
+ }
- String getAppenderRef() {
- return appenderName;
- }
+ private static String inQuotes(String s) {
+ return "\"" + s + "\"";
}
private abstract class RollingPolicy {
diff --git a/server/sonar-process/src/main/java/org/sonar/process/logging/LogbackHelper.java b/server/sonar-process/src/main/java/org/sonar/process/logging/LogbackHelper.java
index becaf3d7bfa..e95fb20eda0 100644
--- a/server/sonar-process/src/main/java/org/sonar/process/logging/LogbackHelper.java
+++ b/server/sonar-process/src/main/java/org/sonar/process/logging/LogbackHelper.java
@@ -55,6 +55,7 @@ import static org.sonar.process.ProcessProperties.Property.LOG_CONSOLE;
import static org.sonar.process.ProcessProperties.Property.LOG_LEVEL;
import static org.sonar.process.ProcessProperties.Property.LOG_MAX_FILES;
import static org.sonar.process.ProcessProperties.Property.LOG_ROLLING_POLICY;
+import static org.sonar.process.ProcessProperties.Property.LOG_JSON_OUTPUT;
import static org.sonar.process.ProcessProperties.Property.PATH_LOGS;
/**
@@ -229,7 +230,7 @@ public class LogbackHelper extends AbstractLogHelper {
}
public Encoder<ILoggingEvent> createEncoder(Props props, RootLoggerConfig config, LoggerContext context) {
- if (props.valueAsBoolean("sonar.log.useJsonOutput", false)) {
+ if (props.valueAsBoolean(LOG_JSON_OUTPUT.getKey(), Boolean.parseBoolean(LOG_JSON_OUTPUT.getDefaultValue()))) {
LayoutWrappingEncoder encoder = new LayoutWrappingEncoder<>();
encoder.setLayout(new LogbackJsonLayout(config.getProcessId().getKey()));
encoder.setContext(context);
diff --git a/server/sonar-process/src/main/java/org/sonar/process/logging/LogbackJsonLayout.java b/server/sonar-process/src/main/java/org/sonar/process/logging/LogbackJsonLayout.java
index ef4be5bb329..d0ed49a5f1d 100644
--- a/server/sonar-process/src/main/java/org/sonar/process/logging/LogbackJsonLayout.java
+++ b/server/sonar-process/src/main/java/org/sonar/process/logging/LogbackJsonLayout.java
@@ -45,7 +45,7 @@ import static java.util.Objects.requireNonNull;
*/
public class LogbackJsonLayout extends LayoutBase<ILoggingEvent> {
- private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ISO_OFFSET_DATE_TIME
+ static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ISO_OFFSET_DATE_TIME
.withLocale(Locale.US)
.withZone(ZoneId.systemDefault());
private static final Pattern NEWLINE_REGEXP = Pattern.compile("\n");
@@ -72,8 +72,7 @@ public class LogbackJsonLayout extends LayoutBase<ILoggingEvent> {
}
}
json
- .name("instant").value(event.getTimeStamp())
- .name("date").value(DATE_FORMATTER.format(Instant.ofEpochMilli(event.getTimeStamp())))
+ .name("timestamp").value(DATE_FORMATTER.format(Instant.ofEpochMilli(event.getTimeStamp())))
.name("severity").value(event.getLevel().toString())
.name("logger").value(event.getLoggerName())
.name("message").value(NEWLINE_REGEXP.matcher(event.getFormattedMessage()).replaceAll("\r"));
diff --git a/server/sonar-process/src/test/java/org/sonar/process/logging/Log4JPropertiesBuilderTest.java b/server/sonar-process/src/test/java/org/sonar/process/logging/Log4JPropertiesBuilderTest.java
index d6429fae4a2..975eba70c3f 100644
--- a/server/sonar-process/src/test/java/org/sonar/process/logging/Log4JPropertiesBuilderTest.java
+++ b/server/sonar-process/src/test/java/org/sonar/process/logging/Log4JPropertiesBuilderTest.java
@@ -24,6 +24,7 @@ import com.tngtech.java.junit.dataprovider.DataProvider;
import com.tngtech.java.junit.dataprovider.DataProviderRunner;
import com.tngtech.java.junit.dataprovider.UseDataProvider;
import java.io.File;
+import java.io.IOException;
import java.util.HashSet;
import java.util.Properties;
import java.util.Random;
@@ -31,7 +32,6 @@ import java.util.Set;
import org.apache.commons.lang.RandomStringUtils;
import org.junit.Rule;
import org.junit.Test;
-import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.sonar.process.MessageException;
@@ -41,6 +41,8 @@ import org.sonar.process.Props;
import static java.lang.String.valueOf;
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.Assert.assertThrows;
import static org.sonar.process.logging.RootLoggerConfig.newRootLoggerConfigBuilder;
@RunWith(DataProviderRunner.class)
@@ -49,38 +51,39 @@ public class Log4JPropertiesBuilderTest {
private static final String PROPERTY_MAX_FILES = "sonar.log.maxFiles";
@Rule
- public ExpectedException expectedException = ExpectedException.none();
- @Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
private final RootLoggerConfig esRootLoggerConfig = newRootLoggerConfigBuilder().setProcessId(ProcessId.ELASTICSEARCH).build();
- private final Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder();
@Test
public void constructor_fails_with_NPE_if_Props_is_null() {
- expectedException.expect(NullPointerException.class);
- expectedException.expectMessage("Props can't be null");
-
- new Log4JPropertiesBuilder(null);
+ assertThatThrownBy(() -> new Log4JPropertiesBuilder(null))
+ .isInstanceOf(NullPointerException.class)
+ .hasMessage("Props can't be null");
}
@Test
- public void constructor_sets_status_to_ERROR() {
- Properties properties = underTest.get();
+ public void constructor_sets_status_to_ERROR() throws IOException {
+ File logDir = temporaryFolder.newFolder();
+ String logPattern = randomAlphanumeric(15);
+ Properties properties = newLog4JPropertiesBuilder().rootLoggerConfig(esRootLoggerConfig).logDir(logDir).logPattern(logPattern).build();
assertThat(properties.getProperty("status")).isEqualTo("ERROR");
}
@Test
public void getRootLoggerName_returns_rootLogger() {
- assertThat(underTest.getRootLoggerName()).isEqualTo("rootLogger");
+ assertThat(newLog4JPropertiesBuilder().getRootLoggerName()).isEqualTo("rootLogger");
}
@Test
- public void get_always_returns_a_new_object() {
- Properties previous = underTest.get();
+ public void get_always_returns_a_new_object() throws IOException {
+ File logDir = temporaryFolder.newFolder();
+ String logPattern = randomAlphanumeric(15);
+
+ Properties previous = newLog4JPropertiesBuilder().rootLoggerConfig(esRootLoggerConfig).logDir(logDir).logPattern(logPattern).build();
for (int i = 0; i < 2 + new Random().nextInt(5); i++) {
- Properties properties = underTest.get();
+ Properties properties = newLog4JPropertiesBuilder().rootLoggerConfig(esRootLoggerConfig).logDir(logDir).logPattern(logPattern).build();
assertThat(properties).isNotSameAs(previous);
previous = properties;
}
@@ -88,7 +91,7 @@ public class Log4JPropertiesBuilderTest {
@Test
public void buildLogPattern_puts_process_key_as_process_id() {
- String pattern = underTest.buildLogPattern(newRootLoggerConfigBuilder()
+ String pattern = newLog4JPropertiesBuilder().buildLogPattern(newRootLoggerConfigBuilder()
.setProcessId(ProcessId.ELASTICSEARCH)
.build());
@@ -99,7 +102,7 @@ public class Log4JPropertiesBuilderTest {
public void buildLogPattern_puts_threadIdFieldPattern_from_RootLoggerConfig_non_null() {
String threadIdFieldPattern = RandomStringUtils.randomAlphabetic(5);
- String pattern = underTest.buildLogPattern(
+ String pattern = newLog4JPropertiesBuilder().buildLogPattern(
newRootLoggerConfigBuilder()
.setProcessId(ProcessId.APP)
.setThreadIdFieldPattern(threadIdFieldPattern)
@@ -110,7 +113,7 @@ public class Log4JPropertiesBuilderTest {
@Test
public void buildLogPattern_does_not_put_threadIdFieldPattern_from_RootLoggerConfig_is_null() {
- String pattern = underTest.buildLogPattern(
+ String pattern = newLog4JPropertiesBuilder().buildLogPattern(
newRootLoggerConfigBuilder()
.setProcessId(ProcessId.COMPUTE_ENGINE)
.build());
@@ -120,7 +123,7 @@ public class Log4JPropertiesBuilderTest {
@Test
public void buildLogPattern_does_not_put_threadIdFieldPattern_from_RootLoggerConfig_is_empty() {
- String pattern = underTest.buildLogPattern(
+ String pattern = newLog4JPropertiesBuilder().buildLogPattern(
newRootLoggerConfigBuilder()
.setProcessId(ProcessId.WEB_SERVER)
.setThreadIdFieldPattern("")
@@ -133,7 +136,10 @@ public class Log4JPropertiesBuilderTest {
public void configureGlobalFileLog_sets_properties_for_daily_time_rolling_policy_with_max_7_files_for_empty_props() throws Exception {
File logDir = temporaryFolder.newFolder();
String logPattern = randomAlphanumeric(15);
- underTest.configureGlobalFileLog(esRootLoggerConfig, logDir, logPattern);
+ var underTest = newLog4JPropertiesBuilder()
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern);
verifyTimeRollingPolicy(underTest, logDir, logPattern, "yyyy-MM-dd", 7);
}
@@ -142,10 +148,13 @@ public class Log4JPropertiesBuilderTest {
public void time_rolling_policy_has_large_max_files_if_property_is_zero() throws Exception {
File logDir = temporaryFolder.newFolder();
String logPattern = "foo";
- Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder(
+
+ var underTest = newLog4JPropertiesBuilder(
ROLLING_POLICY_PROPERTY, "time:yyyy-MM-dd",
- PROPERTY_MAX_FILES, "0");
- underTest.configureGlobalFileLog(esRootLoggerConfig, logDir, logPattern);
+ PROPERTY_MAX_FILES, "0")
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern);
verifyTimeRollingPolicy(underTest, logDir, logPattern, "yyyy-MM-dd", 100_000);
}
@@ -154,10 +163,13 @@ public class Log4JPropertiesBuilderTest {
public void time_rolling_policy_has_large_max_files_if_property_is_negative() throws Exception {
File logDir = temporaryFolder.newFolder();
String logPattern = "foo";
- Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder(
+
+ var underTest = newLog4JPropertiesBuilder(
ROLLING_POLICY_PROPERTY, "time:yyyy-MM-dd",
- PROPERTY_MAX_FILES, "-2");
- underTest.configureGlobalFileLog(esRootLoggerConfig, logDir, logPattern);
+ PROPERTY_MAX_FILES, "-2")
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern);
verifyTimeRollingPolicy(underTest, logDir, logPattern, "yyyy-MM-dd", 100_000);
}
@@ -167,10 +179,13 @@ public class Log4JPropertiesBuilderTest {
File logDir = temporaryFolder.newFolder();
String logPattern = "foo";
String sizePattern = "1KB";
- Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder(
+
+ var underTest = newLog4JPropertiesBuilder(
ROLLING_POLICY_PROPERTY, "size:" + sizePattern,
- PROPERTY_MAX_FILES, "0");
- underTest.configureGlobalFileLog(esRootLoggerConfig, logDir, logPattern);
+ PROPERTY_MAX_FILES, "0")
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern);
verifySizeRollingPolicy(underTest, logDir, logPattern, sizePattern, 100_000);
}
@@ -180,10 +195,13 @@ public class Log4JPropertiesBuilderTest {
File logDir = temporaryFolder.newFolder();
String logPattern = "foo";
String sizePattern = "1KB";
- Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder(
+
+ var underTest = newLog4JPropertiesBuilder(
ROLLING_POLICY_PROPERTY, "size:" + sizePattern,
- PROPERTY_MAX_FILES, "-2");
- underTest.configureGlobalFileLog(esRootLoggerConfig, logDir, logPattern);
+ PROPERTY_MAX_FILES, "-2")
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern);
verifySizeRollingPolicy(underTest, logDir, logPattern, sizePattern, 100_000);
}
@@ -194,12 +212,14 @@ public class Log4JPropertiesBuilderTest {
String logPattern = randomAlphanumeric(15);
String invalidPropertyValue = randomAlphanumeric(3);
Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder(
- ROLLING_POLICY_PROPERTY, invalidPropertyValue);
-
- expectedException.expect(MessageException.class);
- expectedException.expectMessage("Unsupported value for property " + ROLLING_POLICY_PROPERTY + ": " + invalidPropertyValue);
+ ROLLING_POLICY_PROPERTY, invalidPropertyValue)
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern);
- underTest.configureGlobalFileLog(esRootLoggerConfig, logDir, logPattern);
+ assertThatThrownBy(underTest::build)
+ .isInstanceOf(MessageException.class)
+ .hasMessage("Unsupported value for property " + ROLLING_POLICY_PROPERTY + ": " + invalidPropertyValue);
}
@Test
@@ -207,9 +227,12 @@ public class Log4JPropertiesBuilderTest {
File logDir = temporaryFolder.newFolder();
String logPattern = randomAlphanumeric(15);
String timePattern = randomAlphanumeric(6);
+
Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder(
- ROLLING_POLICY_PROPERTY, "time:" + timePattern);
- underTest.configureGlobalFileLog(esRootLoggerConfig, logDir, logPattern);
+ ROLLING_POLICY_PROPERTY, "time:" + timePattern)
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern);
verifyTimeRollingPolicy(underTest, logDir, logPattern, timePattern, 7);
}
@@ -220,10 +243,13 @@ public class Log4JPropertiesBuilderTest {
String logPattern = randomAlphanumeric(15);
String timePattern = randomAlphanumeric(6);
int maxFile = 1 + new Random().nextInt(10);
+
Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder(
ROLLING_POLICY_PROPERTY, "time:" + timePattern,
- PROPERTY_MAX_FILES, valueOf(maxFile));
- underTest.configureGlobalFileLog(esRootLoggerConfig, logDir, logPattern);
+ PROPERTY_MAX_FILES, valueOf(maxFile))
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern);
verifyTimeRollingPolicy(underTest, logDir, logPattern, timePattern, maxFile);
}
@@ -234,8 +260,10 @@ public class Log4JPropertiesBuilderTest {
String logPattern = randomAlphanumeric(15);
String sizePattern = randomAlphanumeric(6);
Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder(
- ROLLING_POLICY_PROPERTY, "size:" + sizePattern);
- underTest.configureGlobalFileLog(esRootLoggerConfig, logDir, logPattern);
+ ROLLING_POLICY_PROPERTY, "size:" + sizePattern)
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern);
verifySizeRollingPolicy(underTest, logDir, logPattern, sizePattern, 7);
}
@@ -248,8 +276,10 @@ public class Log4JPropertiesBuilderTest {
int maxFile = 1 + new Random().nextInt(10);
Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder(
ROLLING_POLICY_PROPERTY, "size:" + sizePattern,
- PROPERTY_MAX_FILES, valueOf(maxFile));
- underTest.configureGlobalFileLog(esRootLoggerConfig, logDir, logPattern);
+ PROPERTY_MAX_FILES, valueOf(maxFile))
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern);
verifySizeRollingPolicy(underTest, logDir, logPattern, sizePattern, maxFile);
}
@@ -259,10 +289,12 @@ public class Log4JPropertiesBuilderTest {
File logDir = temporaryFolder.newFolder();
String logPattern = randomAlphanumeric(15);
Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder(
- ROLLING_POLICY_PROPERTY, "none");
- underTest.configureGlobalFileLog(esRootLoggerConfig, logDir, logPattern);
+ ROLLING_POLICY_PROPERTY, "none")
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern);
- verifyProperties(underTest.get(),
+ verifyProperties(underTest.build(),
"appender.file_es.type", "File",
"appender.file_es.name", "file_es",
"appender.file_es.fileName", new File(logDir, "es.log").getAbsolutePath(),
@@ -272,183 +304,323 @@ public class Log4JPropertiesBuilderTest {
}
@Test
- public void name() {
+ public void enable_all_logs_to_stdout_write_additionally_Console_appender() throws IOException {
+ File logDir = temporaryFolder.newFolder();
String logPattern = randomAlphanumeric(15);
- Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder();
- underTest.configureGlobalStdoutLog(logPattern);
- verifyProperties(underTest.get(),
+ Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder(ROLLING_POLICY_PROPERTY, "none")
+ .enableAllLogsToConsole(true)
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logPattern(logPattern)
+ .logDir(logDir);
+ verifyProperties(underTest.build(),
"appender.stdout.type", "Console",
"appender.stdout.name", "stdout",
"appender.stdout.layout.type", "PatternLayout",
"appender.stdout.layout.pattern", logPattern,
- "rootLogger.appenderRef.stdout.ref", "stdout");
+ "rootLogger.appenderRef.stdout.ref", "stdout",
+ "appender.file_es.layout.pattern", logPattern,
+ "appender.file_es.layout.type", "PatternLayout",
+ "appender.file_es.fileName", new File(logDir, "es.log").getAbsolutePath(),
+ "appender.file_es.name", "file_es",
+ "rootLogger.appenderRef.file_es.ref", "file_es",
+ "appender.file_es.type", "File");
+ }
+
+ @Test
+ public void enable_json_output_should_change_pattern_for_console_and_file_appender() throws IOException {
+ File logDir = temporaryFolder.newFolder();
+
+ String expectedPattern = "{\"process\": \"es\",\"timestamp\": \"%d{yyyy-MM-dd'T'HH:mm:ss.SSSZZ}\","
+ + "\"severity\": \"%p\",\"logger\": \"%c{1.}\",\"message\": \"%notEmpty{%enc{%marker}{JSON} }%enc{%.-10000m}{JSON}\"%exceptionAsJson }" + System.lineSeparator();
+
+ Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder(ROLLING_POLICY_PROPERTY, "none")
+ .enableAllLogsToConsole(true)
+ .rootLoggerConfig(esRootLoggerConfig)
+ .jsonOutput(true)
+ .logDir(logDir);
+ verifyProperties(underTest.build(),
+ "appender.stdout.type", "Console",
+ "appender.stdout.name", "stdout",
+ "appender.stdout.layout.type", "PatternLayout",
+ "appender.stdout.layout.pattern", expectedPattern,
+ "rootLogger.appenderRef.stdout.ref", "stdout",
+ "appender.file_es.layout.type", "PatternLayout",
+ "appender.file_es.layout.pattern", expectedPattern,
+ "appender.file_es.fileName", new File(logDir, "es.log").getAbsolutePath(),
+ "appender.file_es.name", "file_es",
+ "rootLogger.appenderRef.file_es.ref", "file_es",
+ "appender.file_es.type", "File");
}
@Test
- public void apply_fails_with_IAE_if_LogLevelConfig_does_not_have_rootLoggerName_of_Log4J() {
- Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder();
+ public void apply_fails_with_IAE_if_LogLevelConfig_does_not_have_rootLoggerName_of_Log4J() throws IOException {
LogLevelConfig logLevelConfig = LogLevelConfig.newBuilder(randomAlphanumeric(2)).build();
+ File logDir = temporaryFolder.newFolder();
+ String logPattern = randomAlphanumeric(15);
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("Value of LogLevelConfig#rootLoggerName must be \"rootLogger\"");
+ Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder()
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern)
+ .logLevelConfig(logLevelConfig);
- underTest.apply(logLevelConfig);
+ assertThatThrownBy(underTest::build)
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("Value of LogLevelConfig#rootLoggerName must be \"rootLogger\"");
}
@Test
- public void apply_fails_with_IAE_if_global_property_has_unsupported_level() {
+ public void apply_fails_with_IAE_if_global_property_has_unsupported_level() throws IOException {
LogLevelConfig config = newLogLevelConfig().rootLevelFor(ProcessId.WEB_SERVER).build();
+ File logDir = temporaryFolder.newFolder();
+ String logPattern = randomAlphanumeric(15);
- Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder("sonar.log.level", "ERROR");
-
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("log level ERROR in property sonar.log.level is not a supported value (allowed levels are [TRACE, DEBUG, INFO])");
+ Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder("sonar.log.level", "ERROR")
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern)
+ .logLevelConfig(config);
- underTest.apply(config);
+ assertThatThrownBy(underTest::build)
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("log level ERROR in property sonar.log.level is not a supported value (allowed levels are [TRACE, DEBUG, INFO])");
}
@Test
- public void apply_fails_with_IAE_if_process_property_has_unsupported_level() {
+ public void apply_fails_with_IAE_if_process_property_has_unsupported_level() throws IOException {
LogLevelConfig config = newLogLevelConfig().rootLevelFor(ProcessId.WEB_SERVER).build();
+ File logDir = temporaryFolder.newFolder();
+ String logPattern = randomAlphanumeric(15);
- Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder("sonar.log.level.web", "ERROR");
-
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("log level ERROR in property sonar.log.level.web is not a supported value (allowed levels are [TRACE, DEBUG, INFO])");
+ Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder("sonar.log.level.web", "ERROR")
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern)
+ .logLevelConfig(config);
- underTest.apply(config);
+ assertThatThrownBy(underTest::build)
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("log level ERROR in property sonar.log.level.web is not a supported value (allowed levels are [TRACE, DEBUG, INFO])");
}
@Test
- public void apply_sets_root_logger_to_INFO_if_no_property_is_set() {
+ public void apply_sets_root_logger_to_INFO_if_no_property_is_set() throws IOException {
LogLevelConfig config = newLogLevelConfig().rootLevelFor(ProcessId.WEB_SERVER).build();
+ File logDir = temporaryFolder.newFolder();
+ String logPattern = randomAlphanumeric(15);
+
+ Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder()
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern)
+ .logLevelConfig(config);
- underTest.apply(config);
+ underTest.build();
verifyRootLoggerLevel(underTest, Level.INFO);
}
@Test
- public void apply_sets_root_logger_to_global_property_if_set() {
+ public void apply_sets_root_logger_to_global_property_if_set() throws IOException {
LogLevelConfig config = newLogLevelConfig().rootLevelFor(ProcessId.WEB_SERVER).build();
+ File logDir = temporaryFolder.newFolder();
+ String logPattern = randomAlphanumeric(15);
- Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder("sonar.log.level", "TRACE");
-
- underTest.apply(config);
+ Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder("sonar.log.level", "TRACE")
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern)
+ .logLevelConfig(config);
verifyRootLoggerLevel(underTest, Level.TRACE);
}
@Test
- public void apply_sets_root_logger_to_process_property_if_set() {
+ public void apply_sets_root_logger_to_process_property_if_set() throws IOException {
LogLevelConfig config = newLogLevelConfig().rootLevelFor(ProcessId.WEB_SERVER).build();
+ File logDir = temporaryFolder.newFolder();
+ String logPattern = randomAlphanumeric(15);
- Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder("sonar.log.level.web", "DEBUG");
-
- underTest.apply(config);
+ Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder("sonar.log.level.web", "DEBUG")
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern)
+ .logLevelConfig(config);
verifyRootLoggerLevel(underTest, Level.DEBUG);
}
@Test
- public void apply_sets_root_logger_to_process_property_over_global_property_if_both_set() {
+ public void apply_sets_root_logger_to_process_property_over_global_property_if_both_set() throws IOException {
LogLevelConfig config = newLogLevelConfig().rootLevelFor(ProcessId.WEB_SERVER).build();
- Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder("sonar.log.level", "DEBUG",
- "sonar.log.level.web", "TRACE");
+ File logDir = temporaryFolder.newFolder();
+ String logPattern = randomAlphanumeric(15);
- underTest.apply(config);
+ Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder("sonar.log.level", "DEBUG",
+ "sonar.log.level.web", "TRACE")
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern)
+ .logLevelConfig(config);
verifyRootLoggerLevel(underTest, Level.TRACE);
}
@Test
- public void apply_sets_domain_property_over_process_and_global_property_if_all_set() {
+ public void apply_sets_domain_property_over_process_and_global_property_if_all_set() throws IOException {
LogLevelConfig config = newLogLevelConfig().levelByDomain("foo", ProcessId.WEB_SERVER, LogDomain.ES).build();
+ File logDir = temporaryFolder.newFolder();
+ String logPattern = randomAlphanumeric(15);
+
Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder(
"sonar.log.level", "DEBUG",
"sonar.log.level.web", "DEBUG",
- "sonar.log.level.web.es", "TRACE");
-
- underTest.apply(config);
+ "sonar.log.level.web.es", "TRACE")
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern)
+ .logLevelConfig(config);
- verifyLoggerProperties(underTest.get(), "foo", Level.TRACE);
+ verifyLoggerProperties(underTest.build(), "foo", Level.TRACE);
}
@Test
- public void apply_sets_domain_property_over_process_property_if_both_set() {
+ public void apply_sets_domain_property_over_process_property_if_both_set() throws IOException {
LogLevelConfig config = newLogLevelConfig().levelByDomain("foo", ProcessId.WEB_SERVER, LogDomain.ES).build();
+ File logDir = temporaryFolder.newFolder();
+ String logPattern = randomAlphanumeric(15);
+
Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder(
"sonar.log.level.web", "DEBUG",
- "sonar.log.level.web.es", "TRACE");
+ "sonar.log.level.web.es", "TRACE")
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern)
+ .logLevelConfig(config);
- underTest.apply(config);
-
- verifyLoggerProperties(underTest.get(), "foo", Level.TRACE);
+ verifyLoggerProperties(underTest.build(), "foo", Level.TRACE);
}
@Test
- public void apply_sets_domain_property_over_global_property_if_both_set() {
+ public void apply_sets_domain_property_over_global_property_if_both_set() throws IOException {
LogLevelConfig config = newLogLevelConfig().levelByDomain("foo", ProcessId.WEB_SERVER, LogDomain.ES).build();
+ File logDir = temporaryFolder.newFolder();
+ String logPattern = randomAlphanumeric(15);
+
Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder(
"sonar.log.level", "DEBUG",
- "sonar.log.level.web.es", "TRACE");
-
- underTest.apply(config);
+ "sonar.log.level.web.es", "TRACE")
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern)
+ .logLevelConfig(config);
- verifyLoggerProperties(underTest.get(), "foo", Level.TRACE);
+ verifyLoggerProperties(underTest.build(), "foo", Level.TRACE);
}
@Test
- public void apply_fails_with_IAE_if_domain_property_has_unsupported_level() {
- LogLevelConfig config = newLogLevelConfig().levelByDomain("foo", ProcessId.WEB_SERVER, LogDomain.JMX).build();
+ public void apply_fails_with_IAE_if_domain_property_has_unsupported_level() throws IOException {
+ File logDir = temporaryFolder.newFolder();
+ String logPattern = randomAlphanumeric(15);
- Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder("sonar.log.level.web.jmx", "ERROR");
+ LogLevelConfig config = newLogLevelConfig().levelByDomain("foo", ProcessId.WEB_SERVER, LogDomain.JMX).build();
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectMessage("log level ERROR in property sonar.log.level.web.jmx is not a supported value (allowed levels are [TRACE, DEBUG, INFO])");
+ Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder("sonar.log.level.web.jmx", "ERROR")
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern)
+ .logLevelConfig(config);
- underTest.apply(config);
+ assertThatThrownBy(underTest::build)
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("log level ERROR in property sonar.log.level.web.jmx is not a supported value (allowed levels are [TRACE, DEBUG, INFO])");
}
@Test
@UseDataProvider("logbackLevels")
- public void apply_accepts_any_level_as_hardcoded_level(Level level) {
+ public void apply_accepts_any_level_as_hardcoded_level(Level level) throws IOException {
LogLevelConfig config = newLogLevelConfig().immutableLevel("bar", level).build();
+ File logDir = temporaryFolder.newFolder();
+ String logPattern = randomAlphanumeric(15);
+
+ Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder()
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern)
+ .logLevelConfig(config);
- underTest.apply(config);
+ verifyLoggerProperties(underTest.build(), "bar", level);
+ }
- verifyLoggerProperties(underTest.get(), "bar", level);
+ @Test
+ public void apply_set_level_to_OFF_if_sonar_global_level_is_not_set() throws IOException {
+ File logDir = temporaryFolder.newFolder();
+ String logPattern = randomAlphanumeric(15);
+
+ Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder()
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logLevelConfig(newLogLevelConfig().offUnlessTrace("fii").build())
+ .logDir(logDir)
+ .logPattern(logPattern);
+
+ verifyLoggerProperties(underTest.build(), "fii", Level.OFF);
}
@Test
- public void apply_set_level_to_OFF_if_sonar_global_level_is_not_set() {
- underTest.apply(newLogLevelConfig().offUnlessTrace("fii").build());
+ public void fail_if_pattern_not_provided() {
+ Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder()
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(new File("dir"));
- verifyLoggerProperties(underTest.get(), "fii", Level.OFF);
+ assertThrows(IllegalStateException.class, underTest::build);
}
@Test
- public void apply_set_level_to_OFF_if_sonar_global_level_is_INFO() {
+ public void fail_if_root_logger_config_not_provided() {
+ Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder()
+ .logPattern("pattern")
+ .logDir(new File("dir"));
+
+ assertThrows(NullPointerException.class, underTest::build);
+ }
+
+ @Test
+ public void fail_if_logDir_not_provided() {
+ Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder()
+ .logPattern("pattern")
+ .rootLoggerConfig(esRootLoggerConfig);
+
+ assertThrows(NullPointerException.class, underTest::build);
+ }
+
+ @Test
+ public void apply_set_level_to_OFF_if_sonar_global_level_is_INFO() throws Exception {
setLevelToOff(Level.INFO);
}
@Test
- public void apply_set_level_to_OFF_if_sonar_global_level_is_DEBUG() {
+ public void apply_set_level_to_OFF_if_sonar_global_level_is_DEBUG() throws Exception {
setLevelToOff(Level.DEBUG);
}
@Test
- public void apply_does_not_create_loggers_property_if_only_root_level_is_defined() {
+ public void apply_does_not_create_loggers_property_if_only_root_level_is_defined() throws IOException {
LogLevelConfig logLevelConfig = newLogLevelConfig().rootLevelFor(ProcessId.APP).build();
+ File logDir = temporaryFolder.newFolder();
+ String logPattern = randomAlphanumeric(15);
- underTest.apply(logLevelConfig);
+ Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder()
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern)
+ .logLevelConfig(logLevelConfig);
- assertThat(underTest.get().getProperty("loggers")).isNull();
+ assertThat(underTest.build().getProperty("loggers")).isNull();
}
@Test
- public void apply_creates_loggers_property_with_logger_names_ordered_but_root() {
+ public void apply_creates_loggers_property_with_logger_names_ordered_but_root() throws IOException {
LogLevelConfig config = newLogLevelConfig()
.rootLevelFor(ProcessId.WEB_SERVER)
.levelByDomain("foo", ProcessId.WEB_SERVER, LogDomain.JMX)
@@ -458,26 +630,43 @@ public class Log4JPropertiesBuilderTest {
.offUnlessTrace("fii")
.build();
- underTest.apply(config);
+ File logDir = temporaryFolder.newFolder();
+ String logPattern = randomAlphanumeric(15);
+
+ Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder()
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern)
+ .logLevelConfig(config);
- assertThat(underTest.get().getProperty("loggers")).isEqualTo("bar,doh,fii,foo,pif");
+ assertThat(underTest.build().getProperty("loggers")).isEqualTo("bar,doh,fii,foo,pif");
}
- private void setLevelToOff(Level globalLogLevel) {
- Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder("sonar.log.level", globalLogLevel.toString());
+ @Test
+ public void apply_does_not_set_level_if_sonar_global_level_is_TRACE() throws IOException {
+ File logDir = temporaryFolder.newFolder();
+ String logPattern = randomAlphanumeric(15);
- underTest.apply(newLogLevelConfig().offUnlessTrace("fii").build());
+ Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder("sonar.log.level", Level.TRACE.toString())
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern)
+ .logLevelConfig(newLogLevelConfig().offUnlessTrace("fii").build());
- verifyLoggerProperties(underTest.get(), "fii", Level.OFF);
+ verifyNoLoggerProperties(underTest.build(), "fii");
}
- @Test
- public void apply_does_not_set_level_if_sonar_global_level_is_TRACE() {
- Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder("sonar.log.level", Level.TRACE.toString());
+ private void setLevelToOff(Level globalLogLevel) throws IOException {
+ File logDir = temporaryFolder.newFolder();
+ String logPattern = randomAlphanumeric(15);
- underTest.apply(newLogLevelConfig().offUnlessTrace("fii").build());
+ Log4JPropertiesBuilder underTest = newLog4JPropertiesBuilder("sonar.log.level", globalLogLevel.toString())
+ .rootLoggerConfig(esRootLoggerConfig)
+ .logDir(logDir)
+ .logPattern(logPattern)
+ .logLevelConfig(newLogLevelConfig().offUnlessTrace("fii").build());
- verifyNoLoggerProperties(underTest.get(), "fii");
+ verifyLoggerProperties(underTest.build(), "fii", Level.OFF);
}
private static Log4JPropertiesBuilder newLog4JPropertiesBuilder(String... propertyKeysAndValues) {
@@ -490,7 +679,7 @@ public class Log4JPropertiesBuilderTest {
}
private void verifyTimeRollingPolicy(Log4JPropertiesBuilder builder, File logDir, String logPattern, String datePattern, int maxFiles) {
- verifyProperties(builder.get(),
+ verifyProperties(builder.build(),
"appender.file_es.type", "RollingFile",
"appender.file_es.name", "file_es",
"appender.file_es.filePattern", new File(logDir, "es.%d{" + datePattern + "}.log").getAbsolutePath(),
@@ -514,7 +703,7 @@ public class Log4JPropertiesBuilderTest {
}
private void verifySizeRollingPolicy(Log4JPropertiesBuilder builder, File logDir, String logPattern, String sizePattern, int maxFiles) {
- verifyProperties(builder.get(),
+ verifyProperties(builder.build(),
"appender.file_es.type", "RollingFile",
"appender.file_es.name", "file_es",
"appender.file_es.filePattern", new File(logDir, "es.%i.log").getAbsolutePath(),
@@ -562,7 +751,7 @@ public class Log4JPropertiesBuilderTest {
}
private void verifyRootLoggerLevel(Log4JPropertiesBuilder underTest, Level expectedLevel) {
- assertThat(underTest.get().get("rootLogger.level")).isEqualTo(expectedLevel.toString());
+ assertThat(underTest.build().get("rootLogger.level")).isEqualTo(expectedLevel.toString());
}
@DataProvider
diff --git a/server/sonar-process/src/test/java/org/sonar/process/logging/LogbackHelperTest.java b/server/sonar-process/src/test/java/org/sonar/process/logging/LogbackHelperTest.java
index bfa2ddd318e..7806aaa0a78 100644
--- a/server/sonar-process/src/test/java/org/sonar/process/logging/LogbackHelperTest.java
+++ b/server/sonar-process/src/test/java/org/sonar/process/logging/LogbackHelperTest.java
@@ -491,7 +491,7 @@ public class LogbackHelperTest {
@Test
public void createEncoder_uses_json_output() {
- props.set("sonar.log.useJsonOutput", "true");
+ props.set("sonar.log.jsonOutput", "true");
RootLoggerConfig config = newRootLoggerConfigBuilder()
.setProcessId(ProcessId.WEB_SERVER)
.build();
diff --git a/server/sonar-process/src/test/java/org/sonar/process/logging/LogbackJsonLayoutTest.java b/server/sonar-process/src/test/java/org/sonar/process/logging/LogbackJsonLayoutTest.java
index 3dcf0c48a83..6a207d6a746 100644
--- a/server/sonar-process/src/test/java/org/sonar/process/logging/LogbackJsonLayoutTest.java
+++ b/server/sonar-process/src/test/java/org/sonar/process/logging/LogbackJsonLayoutTest.java
@@ -24,17 +24,16 @@ import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.LoggingEvent;
import com.google.gson.Gson;
import java.time.Instant;
-import java.time.format.DateTimeFormatter;
-import org.assertj.core.data.Offset;
import org.junit.Test;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.process.logging.LogbackJsonLayout.DATE_FORMATTER;
public class LogbackJsonLayoutTest {
- private LogbackJsonLayout underTest = new LogbackJsonLayout("web");
+ private final LogbackJsonLayout underTest = new LogbackJsonLayout("web");
@Test
public void test_simple_log() {
@@ -44,12 +43,10 @@ public class LogbackJsonLayoutTest {
JsonLog json = new Gson().fromJson(log, JsonLog.class);
assertThat(json.process).isEqualTo("web");
- assertThat(json.instant).isCloseTo(System.currentTimeMillis(), Offset.offset(10_000L));
- assertThat(Instant.from(DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(json.date)).toEpochMilli()).isEqualTo(json.instant);
+ assertThat(json.timestamp).isEqualTo(DATE_FORMATTER.format(Instant.ofEpochMilli(event.getTimeStamp())));
assertThat(json.severity).isEqualTo("WARN");
assertThat(json.logger).isEqualTo("the.logger");
assertThat(json.message).isEqualTo("the message");
- assertThat(json.message).isEqualTo("the message");
assertThat(json.stacktrace).isNull();
assertThat(json.fromMdc).isNull();
}
@@ -63,12 +60,11 @@ public class LogbackJsonLayoutTest {
JsonLog json = new Gson().fromJson(log, JsonLog.class);
assertThat(json.process).isEqualTo("web");
- assertThat(json.instant).isCloseTo(System.currentTimeMillis(), Offset.offset(10_000L));
- assertThat(Instant.from(DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(json.date)).toEpochMilli()).isEqualTo(json.instant);
+ assertThat(json.timestamp).isEqualTo(DATE_FORMATTER.format(Instant.ofEpochMilli(event.getTimeStamp())));
assertThat(json.severity).isEqualTo("WARN");
assertThat(json.logger).isEqualTo("the.logger");
assertThat(json.message).isEqualTo("the message");
- assertThat(json.stacktrace.length).isGreaterThan(5);
+ assertThat(json.stacktrace).hasSizeGreaterThan(5);
assertThat(json.stacktrace[0]).isEqualTo("java.lang.IllegalStateException: BOOM");
assertThat(json.stacktrace[1]).startsWith("at ").contains("LogbackJsonLayoutTest.test_log_with_throwable");
assertThat(json.fromMdc).isNull();
@@ -83,7 +79,7 @@ public class LogbackJsonLayoutTest {
String log = underTest.doLayout(event);
JsonLog json = new Gson().fromJson(log, JsonLog.class);
- assertThat(json.stacktrace.length).isGreaterThan(5);
+ assertThat(json.stacktrace).hasSizeGreaterThan(5);
assertThat(json.stacktrace[0]).isEqualTo("java.lang.IllegalStateException: BOOM");
assertThat(json.stacktrace[1]).startsWith("at org.sonar.process.logging.LogbackJsonLayoutTest.test_log_with_throwable_and_cause(LogbackJsonLayoutTest.java:");
assertThat(json.stacktrace)
@@ -100,21 +96,20 @@ public class LogbackJsonLayoutTest {
String log = underTest.doLayout(event);
JsonLog json = new Gson().fromJson(log, JsonLog.class);
- assertThat(json.stacktrace.length).isGreaterThan(5);
+ assertThat(json.stacktrace).hasSizeGreaterThan(5);
assertThat(json.stacktrace[0]).isEqualTo("java.lang.Exception: BOOM");
assertThat(json.stacktrace).contains("Suppressed: java.lang.IllegalStateException: foo");
}
@Test
public void test_log_with_message_arguments() {
- LoggingEvent event = new LoggingEvent("org.foundation.Caller", (Logger) LoggerFactory.getLogger("the.logger"), Level.WARN, "the {}", null, new Object[]{"message"});
+ LoggingEvent event = new LoggingEvent("org.foundation.Caller", (Logger) LoggerFactory.getLogger("the.logger"), Level.WARN, "the {}", null, new Object[] {"message"});
String log = underTest.doLayout(event);
JsonLog json = new Gson().fromJson(log, JsonLog.class);
assertThat(json.process).isEqualTo("web");
- assertThat(json.instant).isCloseTo(System.currentTimeMillis(), Offset.offset(10_000L));
- assertThat(Instant.from(DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(json.date)).toEpochMilli()).isEqualTo(json.instant);
+ assertThat(json.timestamp).isEqualTo(DATE_FORMATTER.format(Instant.ofEpochMilli(event.getTimeStamp())));
assertThat(json.severity).isEqualTo("WARN");
assertThat(json.logger).isEqualTo("the.logger");
assertThat(json.message).isEqualTo("the message");
@@ -139,8 +134,7 @@ public class LogbackJsonLayoutTest {
private static class JsonLog {
private String process;
- private long instant;
- private String date;
+ private String timestamp;
private String severity;
private String logger;
private String message;