Skip to content

Commit

Permalink
Move logging to @ConfigMapping
Browse files Browse the repository at this point in the history
  • Loading branch information
radcortez committed Jul 26, 2024
1 parent 72297fb commit 5686b7a
Show file tree
Hide file tree
Showing 23 changed files with 757 additions and 847 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import static io.quarkus.deployment.util.ReflectUtil.toError;
import static io.quarkus.deployment.util.ReflectUtil.typeOfParameter;
import static io.quarkus.deployment.util.ReflectUtil.unwrapInvocationTargetException;
import static io.quarkus.runtime.configuration.PropertiesUtil.isPropertyInRoots;
import static io.smallrye.config.ConfigMappings.ConfigClassWithPrefix.configClassWithPrefix;
import static io.smallrye.config.Expressions.withoutExpansion;
import static io.smallrye.config.SmallRyeConfig.SMALLRYE_CONFIG_PROFILE;
Expand Down Expand Up @@ -72,6 +71,9 @@
import io.quarkus.runtime.configuration.HyphenateEnumConverter;
import io.quarkus.runtime.configuration.NameIterator;
import io.quarkus.runtime.configuration.PropertiesUtil;
import io.quarkus.runtime.console.ConsoleRuntimeConfig;
import io.quarkus.runtime.logging.LogBuildTimeConfig;
import io.quarkus.runtime.logging.LogRuntimeConfig;
import io.smallrye.config.ConfigMapping;
import io.smallrye.config.ConfigMappings;
import io.smallrye.config.ConfigMappings.ConfigClassWithPrefix;
Expand Down Expand Up @@ -405,6 +407,12 @@ public SmallRyeConfig initConfiguration(LaunchMode launchMode, Properties buildS
builder.withMapping(mapping.getKlass(), mapping.getPrefix());
}

// Even if the Log and Console mappings are marked as runtime, they are also used during build time
// see io.quarkus.runtime.logging.LoggingSetupRecorder.initializeBuildTimeLogging
builder.withMapping(LogBuildTimeConfig.class);
builder.withMapping(LogRuntimeConfig.class);
builder.withMapping(ConsoleRuntimeConfig.class);

builder.withInterceptors(buildConfigTracker);
builder.withInterceptors(ConfigCompatibility.FrontEnd.instance(), ConfigCompatibility.BackEnd.instance());
var config = builder.build();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,42 @@
package io.quarkus.deployment.console;

import io.quarkus.runtime.annotations.ConfigItem;
import io.quarkus.runtime.annotations.ConfigRoot;
import java.util.Optional;

@ConfigRoot
public class ConsoleConfig {
import io.quarkus.runtime.annotations.ConfigPhase;
import io.quarkus.runtime.annotations.ConfigRoot;
import io.smallrye.config.ConfigMapping;
import io.smallrye.config.WithDefault;

@ConfigMapping(prefix = "quarkus.console")
@ConfigRoot(phase = ConfigPhase.BUILD_TIME)
public interface ConsoleConfig {
/**
* If test results and status should be displayed in the console.
* <p>
* If this is false results can still be viewed in the dev console.
*/
@ConfigItem(defaultValue = "true")
public boolean enabled;
@WithDefault("true")
boolean enabled();

/**
* Disables the ability to enter input on the console.
*/
@ConfigItem(defaultValue = "false")
public boolean disableInput;
@WithDefault("false")
boolean disableInput();

/**
* Disable the testing status/prompt message at the bottom of the console
* and log these messages to STDOUT instead.
* <p>
* Use this option if your terminal does not support ANSI escape sequences.
*/
@ConfigItem(defaultValue = "false")
public boolean basic;
@WithDefault("false")
boolean basic();

/**
* If color should be enabled or disabled.
* <p>
* If this is not present then an attempt will be made to guess if the terminal supports color
*/
Optional<Boolean> color();
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,19 @@
import io.quarkus.deployment.dev.testing.TestConfig;
import io.quarkus.dev.console.BasicConsole;
import io.quarkus.dev.console.QuarkusConsole;
import io.quarkus.runtime.console.ConsoleRuntimeConfig;
import io.quarkus.runtime.util.ColorSupport;

public class ConsoleHelper {

public static synchronized void installConsole(TestConfig config, ConsoleConfig consoleConfig,
ConsoleRuntimeConfig consoleRuntimeConfig, io.quarkus.runtime.logging.ConsoleConfig logConfig, boolean test) {
public static synchronized void installConsole(TestConfig config, ConsoleConfig consoleConfig, boolean test) {
if (QuarkusConsole.installed) {
return;
}
boolean colorEnabled = ColorSupport.isColorEnabled(consoleRuntimeConfig, logConfig);
boolean colorEnabled = consoleConfig.color().orElse(QuarkusConsole.hasColorSupport());
QuarkusConsole.installed = true;
//if there is no color we need a basic console
//note that we never enable input for tests
//surefire communicates of stdin, so this can mess with it
boolean inputSupport = !test && !config.disableConsoleInput.orElse(consoleConfig.disableInput);
boolean inputSupport = !test && !config.disableConsoleInput.orElse(consoleConfig.disableInput());
if (!inputSupport) {
//note that in this case we don't hold onto anything from this class loader
//which is important for the test suite
Expand All @@ -37,7 +34,7 @@ public static synchronized void installConsole(TestConfig config, ConsoleConfig
new TerminalConnection(new Consumer<Connection>() {
@Override
public void accept(Connection connection) {
if (connection.supportsAnsi() && !config.basicConsole.orElse(consoleConfig.basic)) {
if (connection.supportsAnsi() && !config.basicConsole.orElse(consoleConfig.basic())) {
QuarkusConsole.INSTANCE = new AeshConsole(connection);
} else {
LinkedBlockingDeque<Integer> queue = new LinkedBlockingDeque<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import org.aesh.command.CommandException;
import org.aesh.command.CommandResult;
import org.aesh.command.invocation.CommandInvocation;
import org.eclipse.microprofile.config.ConfigProvider;
import org.jboss.logging.Logger;

import io.quarkus.deployment.Capabilities;
Expand All @@ -41,7 +40,6 @@
import io.quarkus.deployment.ide.EffectiveIdeBuildItem;
import io.quarkus.deployment.ide.Ide;
import io.quarkus.dev.console.QuarkusConsole;
import io.quarkus.runtime.console.ConsoleRuntimeConfig;

public class ConsoleProcessor {

Expand All @@ -59,25 +57,18 @@ public class ConsoleProcessor {
*/
@BuildStep(onlyIf = IsDevelopment.class)
@Produce(TestSetupBuildItem.class)
ConsoleInstalledBuildItem setupConsole(TestConfig config,
BuildProducer<TestListenerBuildItem> testListenerBuildItemBuildProducer,
LaunchModeBuildItem launchModeBuildItem, ConsoleConfig consoleConfig) {
ConsoleInstalledBuildItem setupConsole(
final TestConfig config,
final ConsoleConfig consoleConfig,
final LaunchModeBuildItem launchModeBuildItem,
final BuildProducer<TestListenerBuildItem> testListenerBuildItemBuildProducer) {

if (consoleInstalled) {
return ConsoleInstalledBuildItem.INSTANCE;
}
consoleInstalled = true;
if (config.console.orElse(consoleConfig.enabled)) {
//this is a bit of a hack, but we can't just inject this normally
//this is a runtime property value, but also a build time property value
//as when running in dev mode they are both basically equivalent
ConsoleRuntimeConfig consoleRuntimeConfig = new ConsoleRuntimeConfig();
consoleRuntimeConfig.color = ConfigProvider.getConfig().getOptionalValue("quarkus.console.color", Boolean.class);
io.quarkus.runtime.logging.ConsoleConfig loggingConsoleConfig = new io.quarkus.runtime.logging.ConsoleConfig();
loggingConsoleConfig.color = ConfigProvider.getConfig().getOptionalValue("quarkus.console.color",
Boolean.class);
ConsoleHelper.installConsole(config, consoleConfig, consoleRuntimeConfig, loggingConsoleConfig,
launchModeBuildItem.isTest());
if (config.console.orElse(consoleConfig.enabled())) {
ConsoleHelper.installConsole(config, consoleConfig, launchModeBuildItem.isTest());
ConsoleStateManager.init(QuarkusConsole.INSTANCE, launchModeBuildItem.getDevModeType().get());
//note that this bit needs to be refactored so it is no longer tied to continuous testing
if (TestSupport.instance().isEmpty() || config.continuousTesting == TestConfig.Mode.DISABLED
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.quarkus.deployment.logging;

import static io.quarkus.runtime.logging.LoggingSetupRecorder.initializeBuildTimeLogging;

import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collection;
Expand Down Expand Up @@ -32,6 +34,7 @@
import org.aesh.command.completer.OptionCompleter;
import org.aesh.command.invocation.CommandInvocation;
import org.aesh.command.option.Option;
import org.eclipse.microprofile.config.ConfigProvider;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationTarget;
import org.jboss.jandex.ClassInfo;
Expand Down Expand Up @@ -103,18 +106,17 @@
import io.quarkus.gizmo.ResultHandle;
import io.quarkus.logging.LoggingFilter;
import io.quarkus.runtime.RuntimeValue;
import io.quarkus.runtime.configuration.ConfigInstantiator;
import io.quarkus.runtime.console.ConsoleRuntimeConfig;
import io.quarkus.runtime.logging.CategoryBuildTimeConfig;
import io.quarkus.runtime.logging.CleanupFilterConfig;
import io.quarkus.runtime.logging.DiscoveredLogComponents;
import io.quarkus.runtime.logging.InheritableLevel;
import io.quarkus.runtime.logging.LogBuildTimeConfig;
import io.quarkus.runtime.logging.LogBuildTimeConfig.CategoryBuildTimeConfig;
import io.quarkus.runtime.logging.LogCleanupFilterElement;
import io.quarkus.runtime.logging.LogConfig;
import io.quarkus.runtime.logging.LogFilterFactory;
import io.quarkus.runtime.logging.LogMetricsHandlerRecorder;
import io.quarkus.runtime.logging.LogRuntimeConfig;
import io.quarkus.runtime.logging.LoggingSetupRecorder;
import io.smallrye.config.SmallRyeConfig;

public final class LoggingResourceProcessor {

Expand Down Expand Up @@ -149,10 +151,10 @@ SystemPropertyBuildItem setProperty() {
void setMinLevelForInitialConfigurator(LogBuildTimeConfig logBuildTimeConfig,
BuildProducer<SystemPropertyBuildItem> systemPropertyBuildItemBuildProducer,
BuildProducer<NativeImageSystemPropertyBuildItem> nativeImageSystemPropertyBuildItemBuildProducer) {
Level effectiveMinLevel = logBuildTimeConfig.minLevel;
Level effectiveMinLevel = logBuildTimeConfig.minLevel();
// go through the category config and if there exists a min-level lower than the root min-level, use it
for (CategoryBuildTimeConfig categoryBuildTimeConfig : logBuildTimeConfig.categories.values()) {
InheritableLevel inheritableLevel = categoryBuildTimeConfig.minLevel;
for (CategoryBuildTimeConfig categoryBuildTimeConfig : logBuildTimeConfig.categories().values()) {
InheritableLevel inheritableLevel = categoryBuildTimeConfig.minLevel();
if (inheritableLevel.isInherited()) {
continue;
}
Expand Down Expand Up @@ -223,23 +225,26 @@ void miscSetup(

@BuildStep
@Record(ExecutionTime.RUNTIME_INIT)
LoggingSetupBuildItem setupLoggingRuntimeInit(RecorderContext context, LoggingSetupRecorder recorder, LogConfig log,
LogBuildTimeConfig buildLog,
CombinedIndexBuildItem combinedIndexBuildItem,
LogCategoryMinLevelDefaultsBuildItem categoryMinLevelDefaults,
Optional<StreamingLogHandlerBuildItem> streamingLogStreamHandlerBuildItem,
List<LogHandlerBuildItem> handlerBuildItems,
List<NamedLogHandlersBuildItem> namedHandlerBuildItems,
List<LogConsoleFormatBuildItem> consoleFormatItems,
List<LogFileFormatBuildItem> fileFormatItems,
List<LogSyslogFormatBuildItem> syslogFormatItems,
Optional<ConsoleFormatterBannerBuildItem> possibleBannerBuildItem,
List<LogStreamBuildItem> logStreamBuildItems,
BuildProducer<ShutdownListenerBuildItem> shutdownListenerBuildItemBuildProducer,
LaunchModeBuildItem launchModeBuildItem,
List<LogCleanupFilterBuildItem> logCleanupFilters,
BuildProducer<ReflectiveClassBuildItem> reflectiveClassBuildItemBuildProducer,
BuildProducer<ServiceProviderBuildItem> serviceProviderBuildItemBuildProducer) {
LoggingSetupBuildItem setupLoggingRuntimeInit(
final RecorderContext context,
final LoggingSetupRecorder recorder,
final LogRuntimeConfig logRuntimeConfig,
final LogBuildTimeConfig logBuildTimeConfig,
final CombinedIndexBuildItem combinedIndexBuildItem,
final LogCategoryMinLevelDefaultsBuildItem categoryMinLevelDefaults,
final Optional<StreamingLogHandlerBuildItem> streamingLogStreamHandlerBuildItem,
final List<LogHandlerBuildItem> handlerBuildItems,
final List<NamedLogHandlersBuildItem> namedHandlerBuildItems,
final List<LogConsoleFormatBuildItem> consoleFormatItems,
final List<LogFileFormatBuildItem> fileFormatItems,
final List<LogSyslogFormatBuildItem> syslogFormatItems,
final Optional<ConsoleFormatterBannerBuildItem> possibleBannerBuildItem,
final List<LogStreamBuildItem> logStreamBuildItems,
final BuildProducer<ShutdownListenerBuildItem> shutdownListenerBuildItemBuildProducer,
final LaunchModeBuildItem launchModeBuildItem,
final List<LogCleanupFilterBuildItem> logCleanupFilters,
final BuildProducer<ReflectiveClassBuildItem> reflectiveClassBuildItemBuildProducer,
final BuildProducer<ServiceProviderBuildItem> serviceProviderBuildItemBuildProducer) {
if (!launchModeBuildItem.isAuxiliaryApplication()
|| launchModeBuildItem.getAuxiliaryDevModeType().orElse(null) == DevModeType.TEST_ONLY) {
final List<RuntimeValue<Optional<Handler>>> handlers = handlerBuildItems.stream()
Expand Down Expand Up @@ -288,25 +293,29 @@ LoggingSetupBuildItem setupLoggingRuntimeInit(RecorderContext context, LoggingSe
}

shutdownListenerBuildItemBuildProducer.produce(new ShutdownListenerBuildItem(
recorder.initializeLogging(log, buildLog, discoveredLogComponents,
recorder.initializeLogging(logRuntimeConfig, logBuildTimeConfig, discoveredLogComponents,
categoryMinLevelDefaults.content, alwaysEnableLogStream,
streamingDevUiLogHandler, handlers, namedHandlers,
possibleConsoleFormatters, possibleFileFormatters, possibleSyslogFormatters,
possibleSupplier, launchModeBuildItem.getLaunchMode(), true)));
LogConfig logConfig = new LogConfig();
ConfigInstantiator.handleObject(logConfig);

List<LogCleanupFilterElement> additionalLogCleanupFilters = new ArrayList<>(logCleanupFilters.size());
for (LogCleanupFilterBuildItem i : logCleanupFilters) {
CleanupFilterConfig value = new CleanupFilterConfig();
LogCleanupFilterElement filterElement = i.getFilterElement();
value.ifStartsWith = filterElement.getMessageStarts();
value.targetLevel = filterElement.getTargetLevel() == null ? org.jboss.logmanager.Level.DEBUG
: filterElement.getTargetLevel();
logConfig.filters.put(filterElement.getLoggerName(), value);
additionalLogCleanupFilters.add(new LogCleanupFilterElement(
filterElement.getLoggerName(),
filterElement.getTargetLevel() == null ? org.jboss.logmanager.Level.DEBUG
: filterElement.getTargetLevel(),
filterElement.getMessageStarts()));
}
ConsoleRuntimeConfig crc = new ConsoleRuntimeConfig();
ConfigInstantiator.handleObject(crc);
LoggingSetupRecorder.initializeBuildTimeLogging(logConfig, buildLog, categoryMinLevelDefaults.content,
crc, launchModeBuildItem.getLaunchMode());

SmallRyeConfig config = ConfigProvider.getConfig().unwrap(SmallRyeConfig.class);
LogRuntimeConfig logRuntimeConfigInBuild = config.getConfigMapping(LogRuntimeConfig.class);
ConsoleRuntimeConfig consoleRuntimeConfig = config.getConfigMapping(ConsoleRuntimeConfig.class);

initializeBuildTimeLogging(logRuntimeConfigInBuild, logBuildTimeConfig, consoleRuntimeConfig,
categoryMinLevelDefaults.content, additionalLogCleanupFilters, launchModeBuildItem.getLaunchMode());

((QuarkusClassLoader) Thread.currentThread().getContextClassLoader()).addCloseTask(new Runnable() {
@Override
public void run() {
Expand Down Expand Up @@ -440,7 +449,7 @@ void setUpDarkeningDefault(Consumer<RunTimeConfigurationDefaultBuildItem> rtcCon
void registerMetrics(LogMetricsHandlerRecorder recorder, LogBuildTimeConfig log,
BuildProducer<MetricsFactoryConsumerBuildItem> metrics,
BuildProducer<LogHandlerBuildItem> logHandler, Optional<MetricsCapabilityBuildItem> metricsCapability) {
if (metricsCapability.isPresent() && log.metricsEnabled) {
if (metricsCapability.isPresent() && log.metricsEnabled()) {
recorder.initCounters();
metrics.produce(new MetricsFactoryConsumerBuildItem(recorder.registerMetrics()));
logHandler.produce(new LogHandlerBuildItem(recorder.getLogHandler()));
Expand All @@ -452,21 +461,22 @@ void setUpMinLevelLogging(LogBuildTimeConfig log,
LogCategoryMinLevelDefaultsBuildItem categoryMinLevelDefaults,
final BuildProducer<GeneratedClassBuildItem> generatedTraceLogger) {
ClassOutput output = new GeneratedClassGizmoAdaptor(generatedTraceLogger, false);
if (allRootMinLevelOrHigher(log.minLevel.intValue(), log.categories, categoryMinLevelDefaults.content)) {
generateDefaultLoggers(log.minLevel, output);
if (allRootMinLevelOrHigher(log.minLevel().intValue(), log.categories(), categoryMinLevelDefaults.content)) {
generateDefaultLoggers(log.minLevel(), output);
} else {
generateCategoryMinLevelLoggers(log.categories, categoryMinLevelDefaults.content, log.minLevel, output);
generateCategoryMinLevelLoggers(log.categories(), categoryMinLevelDefaults.content, log.minLevel(), output);
}
}

private static boolean allRootMinLevelOrHigher(int rootMinLogLevel,
private static boolean allRootMinLevelOrHigher(
int rootMinLogLevel,
Map<String, CategoryBuildTimeConfig> categories,
Map<String, InheritableLevel> categoryMinLevelDefaults) {
Set<String> allConfiguredCategoryNames = new LinkedHashSet<>(categories.keySet());
allConfiguredCategoryNames.addAll(categoryMinLevelDefaults.keySet());
for (String categoryName : allConfiguredCategoryNames) {
InheritableLevel categoryMinLevel = LoggingSetupRecorder.getLogLevelNoInheritance(categoryName, categories,
CategoryBuildTimeConfig::getMinLevel, categoryMinLevelDefaults);
CategoryBuildTimeConfig::minLevel, categoryMinLevelDefaults);
if (!categoryMinLevel.isInherited() && categoryMinLevel.getLevel().intValue() < rootMinLogLevel) {
return false;
}
Expand Down Expand Up @@ -511,7 +521,8 @@ private static void generateMinLevelCompute(Map<String, CategoryBuildTimeConfig>
for (Map.Entry<String, CategoryBuildTimeConfig> entry : categories.entrySet()) {
final String category = entry.getKey();
final int categoryLevelIntValue = LoggingSetupRecorder
.getLogLevel(category, categories, CategoryBuildTimeConfig::getMinLevel, categoryMinLevelDefaults,
.getLogLevel(category, categories, CategoryBuildTimeConfig::minLevel,
categoryMinLevelDefaults,
rootMinLevel)
.intValue();

Expand Down
Loading

0 comments on commit 5686b7a

Please sign in to comment.