use new ServiceLoader based log configurator

This commit is contained in:
Sebastian Stenzel 2022-08-11 18:14:54 +02:00
parent 5267a04491
commit ec7ad0f479
No known key found for this signature in database
GPG Key ID: 667B866EA8240A09
9 changed files with 181 additions and 231 deletions

View File

@ -1,4 +1,6 @@
import ch.qos.logback.classic.spi.Configurator;
import org.cryptomator.integrations.tray.TrayMenuController;
import org.cryptomator.logging.LogbackConfiguratorFactory;
import org.cryptomator.ui.traymenu.AwtTrayMenuController;
open module org.cryptomator.desktop {
@ -38,6 +40,7 @@ open module org.cryptomator.desktop {
exports org.cryptomator.ui.traymenu to org.cryptomator.integrations.api;
provides TrayMenuController with AwtTrayMenuController;
provides Configurator with LogbackConfiguratorFactory;
exports org.cryptomator.ui.keyloading.hub to com.fasterxml.jackson.databind;
}

View File

@ -33,12 +33,14 @@ public class Environment {
private static final String PLUGIN_DIR_PROP_NAME = "cryptomator.pluginDir";
private static final String TRAY_ICON_PROP_NAME = "cryptomator.showTrayIcon";
public Environment() {
LOG.debug("user.home: {}", System.getProperty("user.home"));
LOG.debug("java.library.path: {}", System.getProperty("java.library.path"));
LOG.debug("user.language: {}", System.getProperty("user.language"));
LOG.debug("user.region: {}", System.getProperty("user.region"));
LOG.debug("logback.configurationFile: {}", System.getProperty("logback.configurationFile"));
private Environment() {}
public void log() {
LOG.info("user.home: {}", System.getProperty("user.home"));
LOG.info("java.library.path: {}", System.getProperty("java.library.path"));
LOG.info("user.language: {}", System.getProperty("user.language"));
LOG.info("user.region: {}", System.getProperty("user.region"));
LOG.info("logback.configurationFile: {}", System.getProperty("logback.configurationFile"));
logCryptomatorSystemProperty(SETTINGS_PATH_PROP_NAME);
logCryptomatorSystemProperty(IPC_SOCKET_PATH_PROP_NAME);
logCryptomatorSystemProperty(KEYCHAIN_PATHS_PROP_NAME);
@ -54,13 +56,14 @@ public class Environment {
public static Environment getInstance() {
final class Holder {
private static final Environment INSTANCE = new Environment();
}
return Holder.INSTANCE;
}
private void logCryptomatorSystemProperty(String propertyName) {
LOG.debug("{}: {}", propertyName, System.getProperty(propertyName));
LOG.info("{}: {}", propertyName, System.getProperty(propertyName));
}
public boolean useCustomLogbackConfig() {
@ -97,6 +100,7 @@ public class Environment {
/**
* Returns the app version defined in the {@value APP_VERSION_PROP_NAME} property or returns "SNAPSHOT".
*
* @return App version or "SNAPSHOT", if undefined
*/
public String getAppVersion() {

View File

@ -12,7 +12,6 @@ import org.cryptomator.common.Environment;
import org.cryptomator.common.ShutdownHook;
import org.cryptomator.ipc.IpcCommunicator;
import org.cryptomator.logging.DebugMode;
import org.cryptomator.logging.LoggerConfiguration;
import org.cryptomator.ui.fxapp.FxApplicationComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -35,7 +34,6 @@ public class Cryptomator {
private static final CryptomatorComponent CRYPTOMATOR_COMPONENT = DaggerCryptomatorComponent.factory().create(STARTUP_TIME);
private static final Logger LOG = LoggerFactory.getLogger(Cryptomator.class);
private final LoggerConfiguration logConfig;
private final DebugMode debugMode;
private final SupportedLanguages supportedLanguages;
private final Environment env;
@ -43,8 +41,7 @@ public class Cryptomator {
private final ShutdownHook shutdownHook;
@Inject
Cryptomator(LoggerConfiguration logConfig, DebugMode debugMode, SupportedLanguages supportedLanguages, Environment env, Lazy<IpcMessageHandler> ipcMessageHandler, ShutdownHook shutdownHook) {
this.logConfig = logConfig;
Cryptomator(DebugMode debugMode, SupportedLanguages supportedLanguages, Environment env, Lazy<IpcMessageHandler> ipcMessageHandler, ShutdownHook shutdownHook) {
this.debugMode = debugMode;
this.supportedLanguages = supportedLanguages;
this.env = env;
@ -79,7 +76,7 @@ public class Cryptomator {
* @return Nonzero exit code in case of an error.
*/
private int run(String[] args) {
logConfig.init();
env.log();
LOG.debug("Dagger graph initialized after {}ms", System.currentTimeMillis() - STARTUP_TIME);
LOG.info("Starting Cryptomator {} on {} {} ({})", env.getAppVersion(), SystemUtils.OS_NAME, SystemUtils.OS_VERSION, SystemUtils.OS_ARCH);
debugMode.initialize();

View File

@ -3,14 +3,13 @@ package org.cryptomator.launcher;
import dagger.BindsInstance;
import dagger.Component;
import org.cryptomator.common.CommonsModule;
import org.cryptomator.logging.LoggerModule;
import org.cryptomator.ui.fxapp.FxApplicationComponent;
import javax.inject.Named;
import javax.inject.Singleton;
@Singleton
@Component(modules = {CryptomatorModule.class, CommonsModule.class, LoggerModule.class})
@Component(modules = {CryptomatorModule.class, CommonsModule.class})
public interface CryptomatorComponent {
Cryptomator application();

View File

@ -5,29 +5,24 @@
*******************************************************************************/
package org.cryptomator.logging;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import org.cryptomator.common.settings.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Singleton;
import javafx.beans.value.ObservableValue;
import java.util.Map;
@Singleton
public class DebugMode {
private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(DebugMode.class);
private static final Logger LOG = LoggerFactory.getLogger(DebugMode.class);
private final Settings settings;
private final LoggerContext context;
@Inject
public DebugMode(Settings settings, LoggerContext context) {
public DebugMode(Settings settings) {
this.settings = settings;
this.context = context;
}
public void initialize() {
@ -40,19 +35,13 @@ public class DebugMode {
}
private void setLogLevels(boolean debugMode) {
var configurator = LogbackConfiguratorFactory.provider();
if (debugMode) {
setLogLevels(LoggerModule.DEBUG_LOG_LEVELS);
configurator.setLogLevels(LogbackConfigurator.DEBUG_LOG_LEVELS);
LOG.debug("Debug mode enabled");
} else {
LOG.debug("Debug mode disabled");
setLogLevels(LoggerModule.DEFAULT_LOG_LEVELS);
}
}
private void setLogLevels(Map<String, Level> logLevels) {
for (Map.Entry<String, Level> loglevel : logLevels.entrySet()) {
Logger logger = context.getLogger(loglevel.getKey());
logger.setLevel(loglevel.getValue());
configurator.setLogLevels(LogbackConfigurator.DEFAULT_LOG_LEVELS);
}
}

View File

@ -0,0 +1,146 @@
package org.cryptomator.logging;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.spi.Configurator;
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.helpers.NOPAppender;
import ch.qos.logback.core.rolling.FixedWindowRollingPolicy;
import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.spi.ContextAwareBase;
import ch.qos.logback.core.util.FileSize;
import org.cryptomator.common.Environment;
import java.nio.file.Path;
import java.util.Map;
public class LogbackConfigurator extends ContextAwareBase implements Configurator {
private static final String LOG_PATTERN = "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n";
private static final String UPGRADE_FILENAME = "upgrade.log";
private static final String LOGFILE_NAME = "cryptomator0.log";
private static final String LOGFILE_ROLLING_PATTERN = "cryptomator%i.log";
private static final int LOGFILE_ROLLING_MIN = 1;
private static final int LOGFILE_ROLLING_MAX = 9;
private static final String LOG_MAX_SIZE = "100mb";
static final Map<String, Level> DEFAULT_LOG_LEVELS = Map.of( //
Logger.ROOT_LOGGER_NAME, Level.INFO, //
"org.cryptomator", Level.INFO //
);
static final Map<String, Level> DEBUG_LOG_LEVELS = Map.of( //
Logger.ROOT_LOGGER_NAME, Level.INFO, //
"org.cryptomator", Level.TRACE //
);
LogbackConfigurator() {}
/**
* Adjust the log levels
*
* @param logLevels new log levels to use
*/
void setLogLevels(Map<String, Level> logLevels) {
if (context instanceof LoggerContext lc) {
for (var loglevel : logLevels.entrySet()) {
Logger logger = lc.getLogger(loglevel.getKey());
logger.setLevel(loglevel.getValue());
}
}
}
@Override
public void configure(LoggerContext context) {
var useCustomCfg = Environment.getInstance().useCustomLogbackConfig();
var logDir = Environment.getInstance().getLogDir().orElse(null);
if (useCustomCfg) {
addInfo("Using external logback configuration file.");
} else {
context.reset();
// configure appenders:
var stdout = stdOutAppender(context);
var noop = noopAppender(context);
var file = logDir == null ? noop : fileAppender(context, logDir);
var upgrade = logDir == null ? noop : upgradeAppender(context, logDir);
// configure loggers:
for (var loglevel : DEFAULT_LOG_LEVELS.entrySet()) {
Logger logger = context.getLogger(loglevel.getKey());
logger.setLevel(loglevel.getValue());
logger.setAdditive(false);
logger.addAppender(stdout);
logger.addAppender(file);
}
// configure upgrade logger:
Logger upgrades = context.getLogger("org.cryptomator.cryptofs.migration");
upgrades.setLevel(Level.DEBUG);
upgrades.addAppender(stdout);
upgrades.addAppender(upgrade);
upgrades.addAppender(file);
upgrades.setAdditive(false);
}
}
private Appender<ILoggingEvent> noopAppender(LoggerContext context) {
var appender = new NOPAppender<ILoggingEvent>();
appender.setContext(context);
return appender;
}
private Appender<ILoggingEvent> stdOutAppender(LoggerContext context) {
var appender = new ConsoleAppender<ILoggingEvent>();
appender.setContext(context);
appender.setName("STDOUT");
appender.setEncoder(encoder(context));
appender.start();
return appender;
}
private Appender<ILoggingEvent> upgradeAppender(LoggerContext context, Path logDir) {
var appender = new FileAppender<ILoggingEvent>();
appender.setContext(context);
appender.setName("UPGRADE");
appender.setFile(logDir.resolve(UPGRADE_FILENAME).toString());
appender.setEncoder(encoder(context));
appender.start();
return appender;
}
private Appender<ILoggingEvent> fileAppender(LoggerContext context, Path logDir) {
var appender = new RollingFileAppender<ILoggingEvent>();
appender.setContext(context);
appender.setName("FILE");
appender.setFile(logDir.resolve(LOGFILE_NAME).toString());
appender.setEncoder(encoder(context));
var triggeringPolicy = new LaunchAndSizeBasedTriggeringPolicy<ILoggingEvent>(FileSize.valueOf(LOG_MAX_SIZE));
triggeringPolicy.setContext(context);
triggeringPolicy.start();
appender.setTriggeringPolicy(triggeringPolicy);
var rollingPolicy = new FixedWindowRollingPolicy();
rollingPolicy.setContext(context);
rollingPolicy.setFileNamePattern(logDir.resolve(LOGFILE_ROLLING_PATTERN).toString());
rollingPolicy.setMinIndex(LOGFILE_ROLLING_MIN);
rollingPolicy.setMaxIndex(LOGFILE_ROLLING_MAX);
rollingPolicy.setParent(appender);
rollingPolicy.start();
appender.setRollingPolicy(rollingPolicy);
appender.start();
return appender;
}
private PatternLayoutEncoder encoder(LoggerContext context) {
var encoder = new PatternLayoutEncoder();
encoder.setContext(context);
encoder.setPattern(LOG_PATTERN);
encoder.start();
return encoder;
}
}

View File

@ -0,0 +1,12 @@
package org.cryptomator.logging;
public class LogbackConfiguratorFactory {
public static LogbackConfigurator provider() {
final class Holder {
private static final LogbackConfigurator INSTANCE = new LogbackConfigurator();
}
return Holder.INSTANCE;
}
}

View File

@ -1,70 +0,0 @@
package org.cryptomator.logging;
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.Appender;
import org.cryptomator.common.Environment;
import org.cryptomator.common.ShutdownHook;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.util.Map;
@Singleton
public class LoggerConfiguration {
private final LoggerContext context;
private final Environment environment;
private final Appender<ILoggingEvent> stdout;
private final Appender<ILoggingEvent> upgrade;
private final Appender<ILoggingEvent> file;
private final ShutdownHook shutdownHook;
@Inject
LoggerConfiguration(LoggerContext context, //
Environment environment, //
@Named("stdoutAppender") Appender<ILoggingEvent> stdout, //
@Named("upgradeAppender") Appender<ILoggingEvent> upgrade, //
@Named("fileAppender") Appender<ILoggingEvent> file, //
ShutdownHook shutdownHook) {
this.context = context;
this.environment = environment;
this.stdout = stdout;
this.upgrade = upgrade;
this.file = file;
this.shutdownHook = shutdownHook;
}
public void init() {
if (environment.useCustomLogbackConfig()) {
Logger root = context.getLogger(Logger.ROOT_LOGGER_NAME);
root.info("Using external logback configuration file.");
} else {
context.reset();
// configure loggers:
for (Map.Entry<String, Level> loglevel : LoggerModule.DEFAULT_LOG_LEVELS.entrySet()) {
Logger logger = context.getLogger(loglevel.getKey());
logger.setLevel(loglevel.getValue());
logger.setAdditive(false);
logger.addAppender(stdout);
logger.addAppender(file);
}
// configure upgrade logger:
Logger upgrades = context.getLogger("org.cryptomator.cryptofs.migration");
upgrades.setLevel(Level.DEBUG);
upgrades.addAppender(stdout);
upgrades.addAppender(upgrade);
upgrades.addAppender(file);
upgrades.setAdditive(false);
// add shutdown hook
shutdownHook.runOnShutdown(ShutdownHook.PRIO_LAST, context::stop);
}
}
}

View File

@ -1,130 +0,0 @@
package org.cryptomator.logging;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
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.helpers.NOPAppender;
import ch.qos.logback.core.rolling.FixedWindowRollingPolicy;
import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.util.FileSize;
import dagger.Module;
import dagger.Provides;
import org.cryptomator.common.Environment;
import org.slf4j.ILoggerFactory;
import org.slf4j.LoggerFactory;
import javax.inject.Named;
import javax.inject.Singleton;
import java.nio.file.Path;
import java.util.Map;
@Module
public class LoggerModule {
private static final String UPGRADE_FILENAME = "upgrade.log";
private static final String LOGFILE_NAME = "cryptomator0.log";
private static final String LOGFILE_ROLLING_PATTERN = "cryptomator%i.log";
private static final int LOGFILE_ROLLING_MIN = 1;
private static final int LOGFILE_ROLLING_MAX = 9;
private static final String LOG_PATTERN = "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n";
private static final String LOG_MAX_SIZE = "100mb";
static final Map<String, Level> DEFAULT_LOG_LEVELS = Map.of( //
Logger.ROOT_LOGGER_NAME, Level.INFO, //
"org.cryptomator", Level.INFO //
);
static final Map<String, Level> DEBUG_LOG_LEVELS = Map.of( //
Logger.ROOT_LOGGER_NAME, Level.INFO, //
"org.cryptomator", Level.TRACE //
);
@Provides
@Singleton
static LoggerContext provideLoggerContext() {
ILoggerFactory loggerFactory = LoggerFactory.getILoggerFactory();
if (loggerFactory instanceof LoggerContext context) {
return context;
} else {
throw new IllegalStateException("SLF4J not bound to Logback.");
}
}
@Provides
@Singleton
static PatternLayoutEncoder provideLayoutEncoder(LoggerContext context) {
PatternLayoutEncoder ple = new PatternLayoutEncoder();
ple.setPattern(LOG_PATTERN);
ple.setContext(context);
ple.start();
return ple;
}
@Provides
@Singleton
@Named("stdoutAppender")
static Appender<ILoggingEvent> provideStdoutAppender(LoggerContext context, PatternLayoutEncoder encoder) {
ConsoleAppender<ILoggingEvent> appender = new ConsoleAppender<>();
appender.setContext(context);
appender.setEncoder(encoder);
appender.start();
return appender;
}
@Provides
@Singleton
@Named("fileAppender")
static Appender<ILoggingEvent> provideFileAppender(LoggerContext context, PatternLayoutEncoder encoder, Environment environment) {
var optionalLogDir = environment.getLogDir();
if (optionalLogDir.isPresent()) {
Path logDir = optionalLogDir.get();
RollingFileAppender<ILoggingEvent> appender = new RollingFileAppender<>();
appender.setContext(context);
appender.setFile(logDir.resolve(LOGFILE_NAME).toString());
appender.setEncoder(encoder);
LaunchAndSizeBasedTriggeringPolicy triggeringPolicy = new LaunchAndSizeBasedTriggeringPolicy(FileSize.valueOf(LOG_MAX_SIZE));
triggeringPolicy.setContext(context);
triggeringPolicy.start();
appender.setTriggeringPolicy(triggeringPolicy);
FixedWindowRollingPolicy rollingPolicy = new FixedWindowRollingPolicy();
rollingPolicy.setContext(context);
rollingPolicy.setFileNamePattern(logDir.resolve(LOGFILE_ROLLING_PATTERN).toString());
rollingPolicy.setMinIndex(LOGFILE_ROLLING_MIN);
rollingPolicy.setMaxIndex(LOGFILE_ROLLING_MAX);
rollingPolicy.setParent(appender);
rollingPolicy.start();
appender.setRollingPolicy(rollingPolicy);
appender.start();
return appender;
} else {
NOPAppender appender = new NOPAppender<>();
appender.setContext(context);
return appender;
}
}
@Provides
@Singleton
@Named("upgradeAppender")
static Appender<ILoggingEvent> provideUpgradeAppender(LoggerContext context, PatternLayoutEncoder encoder, Environment environment) {
var optionalLogDir = environment.getLogDir();
if (optionalLogDir.isPresent()) {
FileAppender<ILoggingEvent> appender = new FileAppender<>();
appender.setFile(optionalLogDir.get().resolve(UPGRADE_FILENAME).toString());
appender.setContext(context);
appender.setEncoder(encoder);
appender.start();
return appender;
} else {
NOPAppender appender = new NOPAppender<>();
appender.setContext(context);
return appender;
}
}
}