diff --git a/gradle/changelog/conosole-appender.yml b/gradle/changelog/conosole-appender.yml new file mode 100644 index 0000000000..94380ad8ee --- /dev/null +++ b/gradle/changelog/conosole-appender.yml @@ -0,0 +1,6 @@ +- type: changed + description: Disabled the console appending of log statements for RPM and Windows per default +- type: changed + description: The console appending of the Unix release is only enabled, if the SCM-Manager is run in the foreground +- type: fixed + description: The console and file appender settings from the `config.yml` are now applied diff --git a/scm-packaging/rpm/src/main/fs/etc/scm/config.yml b/scm-packaging/rpm/src/main/fs/etc/scm/config.yml index d37f0f2d8d..e97fc658c2 100644 --- a/scm-packaging/rpm/src/main/fs/etc/scm/config.yml +++ b/scm-packaging/rpm/src/main/fs/etc/scm/config.yml @@ -31,7 +31,7 @@ log: logDir: /var/log/scm rootLevel: WARN enableFileAppender: true - enableConsoleAppender: true + enableConsoleAppender: false logger: sonia.scm: INFO com.cloudogu.scm: INFO diff --git a/scm-packaging/unix/src/main/bin/scm-server b/scm-packaging/unix/src/main/bin/scm-server index bede449265..6169902831 100755 --- a/scm-packaging/unix/src/main/bin/scm-server +++ b/scm-packaging/unix/src/main/bin/scm-server @@ -168,7 +168,7 @@ if $jsvc; then # TODO JVM Arguments - $JSVCCMD -cp "$CLASSPATH" $JAVA_OPTS \ + SCM_LOG_CONSOLE_APPENDER_ENABLED=false $JSVCCMD -cp "$CLASSPATH" $JAVA_OPTS \ $EXTRA_JVM_ARGUMENTS $USER_ARGUMENT \ -outfile "$LOGDIR/scm-server.out" \ -errfile "$LOGDIR/scm-server.err" \ diff --git a/scm-packaging/windows/src/main/fs/conf/config.yml b/scm-packaging/windows/src/main/fs/conf/config.yml index 175adaebe9..b4518f1e76 100644 --- a/scm-packaging/windows/src/main/fs/conf/config.yml +++ b/scm-packaging/windows/src/main/fs/conf/config.yml @@ -31,7 +31,7 @@ log: logDir: logs rootLevel: WARN enableFileAppender: true - enableConsoleAppender: true + enableConsoleAppender: false logger: sonia.scm: INFO com.cloudogu.scm: INFO diff --git a/scm-webapp/build.gradle b/scm-webapp/build.gradle index 886c3442fe..f594059f33 100644 --- a/scm-webapp/build.gradle +++ b/scm-webapp/build.gradle @@ -228,3 +228,9 @@ repositories { tasks.getByName("resolve").configure { dependsOn 'prepareOpenAPI' } + +test { + //Requiered by set environment variable annotation + //Explanation: https://junit-pioneer.org/docs/environment-variables/#warnings-for-reflective-access + jvmArgs("--add-opens=java.base/java.util=ALL-UNNAMED", "--add-opens=java.base/java.lang=ALL-UNNAMED") +} diff --git a/scm-webapp/src/main/java/sonia/scm/config/LoggingConfiguration.java b/scm-webapp/src/main/java/sonia/scm/config/LoggingConfiguration.java index 596c900f2e..92c8d70aaf 100644 --- a/scm-webapp/src/main/java/sonia/scm/config/LoggingConfiguration.java +++ b/scm-webapp/src/main/java/sonia/scm/config/LoggingConfiguration.java @@ -36,11 +36,11 @@ import com.google.common.base.Strings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.nio.file.Path; + @SuppressWarnings("java:S3740") // Accept usage of not-parameterized classes public class LoggingConfiguration { - private static final Logger LOG = LoggerFactory.getLogger(LoggingConfiguration.class); - private final ServerConfigYaml.LogConfig config; private final LoggerContext loggerContext; @@ -51,7 +51,7 @@ public class LoggingConfiguration { public void configureLogging() { if (!Strings.isNullOrEmpty(System.getProperty("logback.configurationFile"))) { - LOG.info("Found logback configuration file. Ignoring logging configuration from config.yml."); + System.out.println("Found logback configuration file. Ignoring logging configuration from config.yml."); return; } @@ -97,6 +97,11 @@ public class LoggingConfiguration { logDirectory = new ScmLogFilePropertyDefiner().getPropertyValue(); } + if (System.getProperty("basedir") != null) { + logDirectory = Path.of(System.getProperty("basedir")).resolve(logDirectory).normalize().toString(); + } + System.out.println("Writing logs to: " + logDirectory); + RollingFileAppender logFileAppender = new RollingFileAppender(); logFileAppender.setFile(logDirectory + "/scm-manager.log"); logFileAppender.setContext(loggerContext); diff --git a/scm-webapp/src/main/java/sonia/scm/config/ServerConfigYaml.java b/scm-webapp/src/main/java/sonia/scm/config/ServerConfigYaml.java index 852d98c478..3e9a5dfcb2 100644 --- a/scm-webapp/src/main/java/sonia/scm/config/ServerConfigYaml.java +++ b/scm-webapp/src/main/java/sonia/scm/config/ServerConfigYaml.java @@ -24,6 +24,8 @@ package sonia.scm.config; +import lombok.Setter; + import java.util.HashMap; import java.util.Map; @@ -39,8 +41,10 @@ public class ServerConfigYaml { private String logDir = ""; private String rootLevel = "INFO"; private Map logger = new HashMap<>(); - private boolean fileAppenderEnabled = true; - private boolean consoleAppenderEnabled = true; + @Setter + private boolean enableFileAppender = true; + @Setter + private boolean enableConsoleAppender = true; private LogConfig() {} @@ -83,19 +87,29 @@ public class ServerConfigYaml { } public boolean isFileAppenderEnabled() { - return getEnvWithDefault("LOG_FILE_APPENDER_ENABLED", fileAppenderEnabled); + return getEnvWithDefault("LOG_FILE_APPENDER_ENABLED", enableFileAppender); } + /** + * @deprecated As of 3.4.0, because the member variables names have been changed. Therefore, the new setter methods should be used. + * @param fileAppenderEnabled Whether the file appender should be enabled + */ + @Deprecated(since = "3.4.0") public void setFileAppenderEnabled(boolean fileAppenderEnabled) { - this.fileAppenderEnabled = fileAppenderEnabled; + this.enableFileAppender = fileAppenderEnabled; } public boolean isConsoleAppenderEnabled() { - return getEnvWithDefault("LOG_CONSOLE_APPENDER_ENABLED", consoleAppenderEnabled); + return getEnvWithDefault("LOG_CONSOLE_APPENDER_ENABLED", enableConsoleAppender); } + /** + * @deprecated As of 3.4.0, because the member variables names have been changed. Therefore, the new setter methods should be used. + * @param consoleAppenderEnabled Whether the console appender should be enabled + */ + @Deprecated(since = "3.4.0") public void setConsoleAppenderEnabled(boolean consoleAppenderEnabled) { - this.consoleAppenderEnabled = consoleAppenderEnabled; + this.enableConsoleAppender = consoleAppenderEnabled; } } diff --git a/scm-webapp/src/main/java/sonia/scm/lifecycle/BootstrapContextListener.java b/scm-webapp/src/main/java/sonia/scm/lifecycle/BootstrapContextListener.java index 71c16d0613..be973d7aa2 100644 --- a/scm-webapp/src/main/java/sonia/scm/lifecycle/BootstrapContextListener.java +++ b/scm-webapp/src/main/java/sonia/scm/lifecycle/BootstrapContextListener.java @@ -74,6 +74,8 @@ public class BootstrapContextListener extends GuiceServletContextListener { classLoaderLifeCycle.initialize(); super.contextInitialized(sce); + configureLoggers(); + Injector injector = (Injector) context.getAttribute(Injector.class.getName()); injectionLifeCycle = new InjectionLifeCycle(injector); injectionLifeCycle.initialize(); @@ -82,7 +84,6 @@ public class BootstrapContextListener extends GuiceServletContextListener { @Override protected Injector getInjector() { ConfigurationResolver configurationResolver = new ConfigurationResolver(); - configureLoggers(); LOG.info("start scm-manager version {}", SCMContext.getContext().getVersion()); Throwable startupError = SCMContext.getContext().getStartupError(); if (startupError != null) { diff --git a/scm-webapp/src/test/java/sonia/scm/config/ServerConfigParserTests.java b/scm-webapp/src/test/java/sonia/scm/config/ServerConfigParserTests.java new file mode 100644 index 0000000000..8ec4dd9e80 --- /dev/null +++ b/scm-webapp/src/test/java/sonia/scm/config/ServerConfigParserTests.java @@ -0,0 +1,77 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package sonia.scm.config; + +import com.google.common.io.Resources; +import org.junit.jupiter.api.Test; +import org.junitpioneer.jupiter.SetEnvironmentVariable; + +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class ServerConfigParserTests { + + @Test + void shouldApplyConfigurationFromResourceFile() { + ServerConfigParser parser = new ServerConfigParser(); + ServerConfigYaml config = parser.parse(Resources.getResource("sonia/scm/config/config.yml")); + + assertThat(config.getLog().getLogDir()).isEqualTo("/etc/scm/logs"); + assertThat(config.getLog().getRootLevel()).isEqualTo("WARN"); + assertThat(config.getLog().isConsoleAppenderEnabled()).isFalse(); + assertThat(config.getLog().isFileAppenderEnabled()).isFalse(); + assertThat(config.getLog().getLogger()).isEqualTo(Map.of("sonia.scm", "ERROR")); + + assertThat(config.getWebapp()).isEqualTo(Map.of( + "workDir", "/tmp/work/dir", + "homeDir", "/home/dir", + "cache", Map.of("dataFile", Map.of("enabled", true), "store", Map.of("enabled", true)), + "endlessJwt", true, + "asyncThreads", 8, + "maxAsyncAbortSeconds", 120, + "centralWorkQueue", Map.of("workers", 8), + "workingCopyPoolStrategy", "copyPoolStrategy", + "workingCopyPoolSize", 12 + )); + } + + @Test + @SetEnvironmentVariable(key = "SCM_LOG_DIR", value = "/ENV/LOG/DIR") + @SetEnvironmentVariable(key = "SCM_LOG_ROOT_LEVEL", value = "ENV_WARN") + @SetEnvironmentVariable(key = "SCM_LOG_FILE_APPENDER_ENABLED", value = "true") + @SetEnvironmentVariable(key = "SCM_LOG_CONSOLE_APPENDER_ENABLED", value = "true") + @SetEnvironmentVariable(key = "SCM_LOG_LOGGER", value = "sonia.env:ENV_INFO") + void shouldOverrideConfigFileWithEnvironmentVariables() { + ServerConfigParser parser = new ServerConfigParser(); + ServerConfigYaml config = parser.parse(Resources.getResource("sonia/scm/config/config.yml")); + + assertThat(config.getLog().getLogDir()).isEqualTo("/ENV/LOG/DIR"); + assertThat(config.getLog().getRootLevel()).isEqualTo("ENV_WARN"); + assertThat(config.getLog().isConsoleAppenderEnabled()).isTrue(); + assertThat(config.getLog().isFileAppenderEnabled()).isTrue(); + assertThat(config.getLog().getLogger()).isEqualTo(Map.of("sonia.env", "ENV_INFO")); + } +} diff --git a/scm-webapp/src/test/resources/sonia/scm/config/config.yml b/scm-webapp/src/test/resources/sonia/scm/config/config.yml new file mode 100644 index 0000000000..5bbadf158a --- /dev/null +++ b/scm-webapp/src/test/resources/sonia/scm/config/config.yml @@ -0,0 +1,46 @@ +# +# MIT License +# +# Copyright (c) 2020-present Cloudogu GmbH and Contributors +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +log: + logDir: /etc/scm/logs + rootLevel: WARN + enableFileAppender: false + enableConsoleAppender: false + logger: + sonia.scm: ERROR +webapp: + workDir: /tmp/work/dir + homeDir: /home/dir + cache: + dataFile: + enabled: true + store: + enabled: true + endlessJwt: true + asyncThreads: 8 + maxAsyncAbortSeconds: 120 + centralWorkQueue: + workers: 8 + workingCopyPoolStrategy: copyPoolStrategy + workingCopyPoolSize: 12