Support asynchronous logging (#38094)

Closes #38578

Closes #28851

Signed-off-by: Martin Bartoš <mabartos@redhat.com>
This commit is contained in:
Martin Bartoš 2025-04-16 17:08:15 +02:00 committed by GitHub
parent 4aa6f51f26
commit 60fb7a5fa7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 686 additions and 56 deletions

View File

@ -4,4 +4,9 @@ Previously, usage of remote stores was discouraged and the experimental feature
In this release, the experimental feature was removed and usage of remote stores was restricted.
If you previously used the `cache-embedded-remote-store` feature, see the link:{upgradingguide_link}[{upgradingguide_name}] for migration steps.
= Asynchronous logging
All available log handlers now support asynchronous logging capabilities.
Asynchronous logging might be useful for deployments requiring **high throughput** and **low latency** to move log operations in a separate thread.
For more details, see the https://www.keycloak.org/server/logging[Logging guide].

View File

@ -176,6 +176,57 @@ If you want to have JSON logs in *ECS* (Elastic Common Schema) format for the co
{"@timestamp":"2025-02-03T14:53:22.539484211+01:00","event.sequence":9608,"log.logger":"io.quarkus","log.level":"INFO","message":"Keycloak 999.0.0-SNAPSHOT on JVM (powered by Quarkus 3.17.8) started in 4.615s. Listening on: http://0.0.0.0:8080","process.thread.name":"main","process.thread.id":1,"mdc":{},"ndc":"","host.hostname":"host-name","process.name":"/usr/lib/jvm/jdk-21.0.3+9/bin/java","process.pid":77561,"data_stream.type":"logs","ecs.version":"1.12.2","service.environment":"prod","service.name":"Keycloak","service.version":"999.0.0-SNAPSHOT"}
----
=== Asynchronous logging
{project_name} supports asynchronous logging, which might be useful for deployments requiring **high throughput** and **low latency**.
Asynchronous logging uses a separate thread to take care of processing all log records.
The logging handlers are invoked in exactly the same way as with synchronous logging, only done in separate threads.
You can enable asynchronous logging for all {project_name} log handlers.
A dedicated thread will be created for every log handler with enabled asynchronous logging.
The underlying mechanism for asynchronous logging uses a queue for processing log records.
Every new log record is added to the queue and then published to the particular log handler with enabled asynchronous logging.
Every log handler has a different queue.
If the queue is already full, it blocks the main thread and waits for free space in the queue.
==== When to use asynchronous logging
* You need **lower latencies** for incoming requests
* You need **higher throughput**
* You have **small worker thread pool** and want to offload logging to separate threads
* You want to reduce the impact of **I/O-heavy log handlers**
* You are logging to **remote destinations** (e.g., network syslog servers) and want to avoid blocking worker threads
WARNING: Be aware that enabling asynchronous logging might bring some **additional memory overhead** due to the additional separate thread and the inner queue.
In that case, it is not recommended to use it for resource-constrained environments.
Additionally, unexpected server shutdowns create a risk of **losing log records**.
==== Enable asynchronous logging
You can enable asynchronous logging globally for all log handlers by using `log-async` property as follows:
<@kc.start parameters="--log-async=true"/>
Or you can enable the asynchronous logging for every specific handler by using properties in the format `log-<handler>-async` (where `<handler>` is a log handler).
If the property for a specific handler is not set, the value from the parent `log-async` property is used.
You can use these properties as follows:
<@kc.start parameters="--log-console-async=true --log-file-async=true --log-syslog-async=true"/>
* `log-console-async` - Console log handler
* `log-file-async` - File log handler
* `log-syslog-async` - Syslog log handler
==== Change queue length
You can change the size of the queue used for the asynchronous logging.
The default size is **512** log records in the queue.
You can change the queue length as follows:
<@kc.start parameters="--log-console-async-queue-length=512 --log-file-async-queue-length=512 --log-syslog-async-queue-length=512"/>
These properties are available only when asynchronous logging is enabled for these specific log handlers.
== Console log handler
The console log handler is enabled by default, providing unstructured log messages for the console.

View File

@ -65,6 +65,12 @@ public class LoggingOptions {
.caseInsensitiveExpectedValues(true)
.build();
public static final Option<Boolean> LOG_ASYNC = new OptionBuilder<>("log-async", Boolean.class)
.category(OptionCategory.LOGGING)
.defaultValue(false)
.description("Indicates whether to log asynchronously to all handlers.")
.build();
public enum Output {
DEFAULT,
JSON;
@ -130,6 +136,19 @@ public class LoggingOptions {
.hidden()
.build();
// Console Async
public static final Option<Boolean> LOG_CONSOLE_ASYNC = new OptionBuilder<>("log-console-async", Boolean.class)
.category(OptionCategory.LOGGING)
.defaultValue(false)
.description("Indicates whether to log asynchronously to console. If not set, value from the parent property '%s' is used.".formatted(LOG_ASYNC.getKey()))
.build();
public static final Option<Integer> LOG_CONSOLE_ASYNC_QUEUE_LENGTH = new OptionBuilder<>("log-console-async-queue-length", Integer.class)
.category(OptionCategory.LOGGING)
.defaultValue(512)
.description("The queue length to use before flushing writing when logging to console.")
.build();
// File
public static final Option<Boolean> LOG_FILE_ENABLED = new OptionBuilder<>("log-file-enabled", Boolean.class)
.category(OptionCategory.LOGGING)
@ -175,6 +194,19 @@ public class LoggingOptions {
.description("Set the log output to JSON or default (plain) unstructured logging.")
.build();
// File async
public static final Option<Boolean> LOG_FILE_ASYNC = new OptionBuilder<>("log-file-async", Boolean.class)
.category(OptionCategory.LOGGING)
.defaultValue(false)
.description("Indicates whether to log asynchronously to file log. If not set, value from the parent property '%s' is used.".formatted(LOG_ASYNC.getKey()))
.build();
public static final Option<Integer> LOG_FILE_ASYNC_QUEUE_LENGTH = new OptionBuilder<>("log-file-async-queue-length", Integer.class)
.category(OptionCategory.LOGGING)
.defaultValue(512)
.description("The queue length to use before flushing writing when logging to file log.")
.build();
// Syslog
public static final Option<Boolean> LOG_SYSLOG_ENABLED = new OptionBuilder<>("log-syslog-enabled", Boolean.class)
.category(OptionCategory.LOGGING)
@ -247,4 +279,16 @@ public class LoggingOptions {
.description("Set the Syslog output to JSON or default (plain) unstructured logging.")
.build();
// Syslog async
public static final Option<Boolean> LOG_SYSLOG_ASYNC = new OptionBuilder<>("log-syslog-async", Boolean.class)
.category(OptionCategory.LOGGING)
.defaultValue(false)
.description("Indicates whether to log asynchronously to Syslog. If not set, value from the parent property '%s' is used.".formatted(LOG_ASYNC.getKey()))
.build();
public static final Option<Integer> LOG_SYSLOG_ASYNC_QUEUE_LENGTH = new OptionBuilder<>("log-syslog-async-queue-length", Integer.class)
.category(OptionCategory.LOGGING)
.defaultValue(512)
.description("The queue length to use before flushing writing when logging to Syslog.")
.build();
}

View File

@ -26,6 +26,7 @@ import static org.keycloak.quarkus.runtime.Environment.isRebuilt;
import static org.keycloak.quarkus.runtime.cli.OptionRenderer.decorateDuplicitOptionName;
import static org.keycloak.quarkus.runtime.cli.command.AbstractStartCommand.OPTIMIZED_BUILD_OPTION_LONG;
import static org.keycloak.quarkus.runtime.configuration.ConfigArgsConfigSource.parseConfigArgs;
import static org.keycloak.quarkus.runtime.configuration.Configuration.isUserModifiable;
import static org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider.NS_KEYCLOAK_PREFIX;
import static org.keycloak.quarkus.runtime.configuration.mappers.PropertyMappers.maskValue;
import static picocli.CommandLine.Model.UsageMessageSpec.SECTION_KEY_COMMAND_LIST;
@ -507,12 +508,6 @@ public class Picocli {
mapper.getDeprecatedMetadata().ifPresent(metadata -> handleDeprecated(deprecatedInUse, mapper, configValueStr, metadata));
}
private static boolean isUserModifiable(ConfigValue configValue) {
// This could check as low as SysPropConfigSource DEFAULT_ORDINAL, which is 400
// for now we won't validate these as it's not expected for the user to specify options via system properties
return configValue.getConfigSourceOrdinal() >= KeycloakPropertiesConfigSource.PROPERTIES_FILE_ORDINAL;
}
private static void checkRuntimeSpiOptions(String key, final List<String> ignoredRunTime) {
if (!key.startsWith(PropertyMappers.KC_SPI_PREFIX)) {
return;

View File

@ -20,6 +20,7 @@ package org.keycloak.quarkus.runtime.configuration;
import static org.keycloak.quarkus.runtime.cli.Picocli.ARG_PREFIX;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Properties;
@ -28,6 +29,7 @@ import io.smallrye.config.ConfigValue;
import io.smallrye.config.SmallRyeConfig;
import org.keycloak.config.Option;
import org.keycloak.quarkus.runtime.cli.Picocli;
import org.keycloak.utils.StringUtil;
import static org.keycloak.quarkus.runtime.configuration.MicroProfileConfigProvider.NS_KEYCLOAK_PREFIX;
@ -51,6 +53,18 @@ public final class Configuration {
return getOptionalBooleanValue(NS_KEYCLOAK_PREFIX + option.getKey()).orElse(false);
}
public static boolean isUserModifiable(ConfigValue configValue) {
// This could check as low as SysPropConfigSource DEFAULT_ORDINAL, which is 400
// for now we won't validate these as it's not expected for the user to specify options via system properties
return configValue.getConfigSourceOrdinal() >= KeycloakPropertiesConfigSource.PROPERTIES_FILE_ORDINAL;
}
public static boolean isSet(Option<?> option) {
return Optional.ofNullable(getKcConfigValue(option.getKey()))
.filter(Configuration::isUserModifiable)
.isPresent();
}
public static boolean isTrue(String propertyName) {
return getOptionalBooleanValue(propertyName).orElse(false);
}

View File

@ -1,6 +1,10 @@
package org.keycloak.quarkus.runtime.configuration.mappers;
import static org.keycloak.config.LoggingOptions.DEFAULT_LOG_FORMAT;
import static org.keycloak.config.LoggingOptions.LOG_CONSOLE_ENABLED;
import static org.keycloak.config.LoggingOptions.LOG_FILE_ENABLED;
import static org.keycloak.config.LoggingOptions.LOG_SYSLOG_ENABLED;
import static org.keycloak.quarkus.runtime.configuration.Configuration.isSet;
import static org.keycloak.quarkus.runtime.configuration.Configuration.isTrue;
import static org.keycloak.quarkus.runtime.configuration.mappers.PropertyMapper.fromOption;
@ -40,6 +44,8 @@ public final class LoggingPropertyMappers {
fromOption(LoggingOptions.LOG)
.paramLabel("<handler>")
.build(),
fromOption(LoggingOptions.LOG_ASYNC)
.build(),
// Console
fromOption(LoggingOptions.LOG_CONSOLE_OUTPUT)
.isEnabled(LoggingPropertyMappers::isConsoleEnabled, CONSOLE_ENABLED_MSG)
@ -60,7 +66,7 @@ public final class LoggingPropertyMappers {
.transformer((value, ctx) -> addTracingInfo(value, LoggingOptions.LOG_CONSOLE_INCLUDE_TRACE))
.build(),
fromOption(LoggingOptions.LOG_CONSOLE_JSON_FORMAT)
.isEnabled(LoggingPropertyMappers::isConsoleJsonEnabled, CONSOLE_ENABLED_MSG + " and output is set to 'json'")
.isEnabled(LoggingPropertyMappers::isConsoleJsonEnabled, "%s and output is set to 'json'".formatted(CONSOLE_ENABLED_MSG))
.to("quarkus.log.console.json.log-format")
.paramLabel("format")
.build(),
@ -76,6 +82,17 @@ public final class LoggingPropertyMappers {
.mapFrom(LoggingOptions.LOG, LoggingPropertyMappers.resolveLogHandler(LoggingOptions.DEFAULT_LOG_HANDLER.name()))
.to("quarkus.log.console.enable")
.build(),
// Console async
fromOption(LoggingOptions.LOG_CONSOLE_ASYNC)
.mapFrom(LoggingOptions.LOG_ASYNC)
.isEnabled(LoggingPropertyMappers::isConsoleEnabled, CONSOLE_ENABLED_MSG)
.to("quarkus.log.console.async")
.build(),
fromOption(LoggingOptions.LOG_CONSOLE_ASYNC_QUEUE_LENGTH)
.isEnabled(LoggingPropertyMappers::isConsoleAsyncEnabled, "%s and asynchronous logging is enabled".formatted(CONSOLE_ENABLED_MSG))
.to("quarkus.log.console.async.queue-length")
.paramLabel("queue-length")
.build(),
// File
fromOption(LoggingOptions.LOG_FILE_ENABLED)
.mapFrom(LoggingOptions.LOG, LoggingPropertyMappers.resolveLogHandler("file"))
@ -114,6 +131,17 @@ public final class LoggingPropertyMappers {
.paramLabel("output")
.transformer(LoggingPropertyMappers::resolveLogOutput)
.build(),
// File async
fromOption(LoggingOptions.LOG_FILE_ASYNC)
.mapFrom(LoggingOptions.LOG_ASYNC)
.isEnabled(LoggingPropertyMappers::isFileEnabled, FILE_ENABLED_MSG)
.to("quarkus.log.file.async")
.build(),
fromOption(LoggingOptions.LOG_FILE_ASYNC_QUEUE_LENGTH)
.isEnabled(LoggingPropertyMappers::isFileAsyncEnabled, "%s and asynchronous logging is enabled".formatted(FILE_ENABLED_MSG))
.to("quarkus.log.file.async.queue-length")
.paramLabel("queue-length")
.build(),
// Log level
fromOption(LoggingOptions.LOG_LEVEL)
.to("quarkus.log.level")
@ -187,33 +215,76 @@ public final class LoggingPropertyMappers {
.paramLabel("output")
.transformer(LoggingPropertyMappers::resolveLogOutput)
.build(),
// Syslog async
fromOption(LoggingOptions.LOG_SYSLOG_ASYNC)
.mapFrom(LoggingOptions.LOG_ASYNC)
.isEnabled(LoggingPropertyMappers::isSyslogEnabled, SYSLOG_ENABLED_MSG)
.to("quarkus.log.syslog.async")
.build(),
fromOption(LoggingOptions.LOG_SYSLOG_ASYNC_QUEUE_LENGTH)
.isEnabled(LoggingPropertyMappers::isSyslogAsyncEnabled, "%s and asynchronous logging is enabled".formatted(SYSLOG_ENABLED_MSG))
.to("quarkus.log.syslog.async.queue-length")
.paramLabel("queue-length")
.build(),
};
return defaultMappers;
}
public static boolean isConsoleEnabled() {
return isTrue(LoggingOptions.LOG_CONSOLE_ENABLED);
return isHandlerEnabled(LoggingOptions.Handler.console);
}
public static boolean isConsoleAsyncEnabled() {
return isHandlerAsyncEnabled(LoggingOptions.Handler.console);
}
public static boolean isConsoleJsonEnabled() {
return isConsoleEnabled() && Configuration.isTrue("quarkus.log.console.json.enabled");
return isConsoleEnabled() && isTrue("quarkus.log.console.json.enabled");
}
public static boolean isFileEnabled() {
return isTrue(LoggingOptions.LOG_FILE_ENABLED);
return isHandlerEnabled(LoggingOptions.Handler.file);
}
public static boolean isFileAsyncEnabled() {
return isHandlerAsyncEnabled(LoggingOptions.Handler.file);
}
public static boolean isFileJsonEnabled() {
return isFileEnabled() && Configuration.isTrue("quarkus.log.file.json.enabled");
return isFileEnabled() && isTrue("quarkus.log.file.json.enabled");
}
public static boolean isSyslogEnabled() {
return isTrue(LoggingOptions.LOG_SYSLOG_ENABLED);
return isHandlerEnabled(LoggingOptions.Handler.syslog);
}
public static boolean isSyslogAsyncEnabled() {
return isHandlerAsyncEnabled(LoggingOptions.Handler.syslog);
}
public static boolean isSyslogJsonEnabled() {
return isSyslogEnabled() && Configuration.isTrue("quarkus.log.syslog.json.enabled");
return isSyslogEnabled() && isTrue("quarkus.log.syslog.json.enabled");
}
private static boolean isHandlerEnabled(LoggingOptions.Handler handler) {
return switch (handler) {
case console -> isTrue(LOG_CONSOLE_ENABLED);
case file -> isTrue(LOG_FILE_ENABLED);
case syslog -> isTrue(LOG_SYSLOG_ENABLED);
};
}
private static boolean isHandlerAsyncEnabled(LoggingOptions.Handler handler) {
if (!isHandlerEnabled(handler)) {
return false;
}
var property = switch (handler) {
case console -> LoggingOptions.LOG_CONSOLE_ASYNC;
case file -> LoggingOptions.LOG_FILE_ASYNC;
case syslog -> LoggingOptions.LOG_SYSLOG_ASYNC;
};
return isSet(property) ? isTrue(property) : isTrue(LoggingOptions.LOG_ASYNC);
}
private static BiFunction<String, ConfigSourceInterceptorContext, String> resolveLogHandler(String handler) {
@ -318,7 +389,7 @@ public final class LoggingPropertyMappers {
*/
private static String addTracingInfo(String value, Option<Boolean> includeTraceOption) {
var isTracingEnabled = TracingPropertyMappers.isTracingEnabled();
var includeTrace = Configuration.isTrue(includeTraceOption);
var includeTrace = isTrue(includeTraceOption);
var isChangedLogFormat = !DEFAULT_LOG_FORMAT.equals(value);
if (!isTracingEnabled || !includeTrace || isChangedLogFormat) {

View File

@ -35,6 +35,7 @@ import java.util.stream.Stream;
import org.junit.Ignore;
import org.junit.Test;
import org.keycloak.config.LoggingOptions;
import org.keycloak.quarkus.runtime.Environment;
import org.keycloak.quarkus.runtime.KeycloakMain;
import org.keycloak.quarkus.runtime.configuration.ConfigArgsConfigSource;
@ -314,7 +315,7 @@ public class PicocliTest extends AbstractConfigurationTest {
NonRunningPicocli nonRunningPicocli = pseudoLaunch("start-dev", "--hostname=name", "--http-enabled=true");
assertEquals(CommandLine.ExitCode.OK, nonRunningPicocli.exitCode);
assertTrue(nonRunningPicocli.reaug);
assertEquals("dev", nonRunningPicocli.buildProps.getProperty(org.keycloak.common.util.Environment.PROFILE));;
assertEquals("dev", nonRunningPicocli.buildProps.getProperty(org.keycloak.common.util.Environment.PROFILE));
}
/**
@ -393,7 +394,7 @@ public class PicocliTest extends AbstractConfigurationTest {
NonRunningPicocli nonRunningPicocli = pseudoLaunch("export", "--db=dev-file", "--file=file");
assertEquals(CommandLine.ExitCode.OK, nonRunningPicocli.exitCode);
assertTrue(nonRunningPicocli.reaug);
assertEquals("prod", nonRunningPicocli.buildProps.getProperty(org.keycloak.common.util.Environment.PROFILE));;
assertEquals("prod", nonRunningPicocli.buildProps.getProperty(org.keycloak.common.util.Environment.PROFILE));
}
@Test
@ -593,4 +594,92 @@ public class PicocliTest extends AbstractConfigurationTest {
// second class kc form should not
assertThat(nonRunningPicocli.getOutString(), not(containsString("kc.spi-events-listener-micrometer-user-event-metrics-enabled")));
}
@Test
public void logAsyncDisabledParent() {
NonRunningPicocli nonRunningPicocli = pseudoLaunch("start-dev", "--log=file", "--log-console-async=true");
assertEquals(CommandLine.ExitCode.USAGE, nonRunningPicocli.exitCode);
assertThat(nonRunningPicocli.getErrString(), containsString("Disabled option: '--log-console-async'. Available only when Console log handler is activated"));
nonRunningPicocli = pseudoLaunch("start-dev", "--log=console", "--log-file-async=true");
assertEquals(CommandLine.ExitCode.USAGE, nonRunningPicocli.exitCode);
assertThat(nonRunningPicocli.getErrString(), containsString("Disabled option: '--log-file-async'. Available only when File log handler is activated"));
nonRunningPicocli = pseudoLaunch("start-dev", "--log=file", "--log-syslog-async=true");
assertEquals(CommandLine.ExitCode.USAGE, nonRunningPicocli.exitCode);
assertThat(nonRunningPicocli.getErrString(), containsString("Disabled option: '--log-syslog-async'. Available only when Syslog is activated"));
}
@Test
public void logAsyncGlobal() {
NonRunningPicocli nonRunningPicocli = pseudoLaunch("start-dev", "--log-async=true", "--log-console-async=false", "--log-console-async-queue-length=222");
assertEquals(CommandLine.ExitCode.USAGE, nonRunningPicocli.exitCode);
assertThat(nonRunningPicocli.getErrString(), containsString("Disabled option: '--log-console-async-queue-length'. Available only when Console log handler is activated"));
onAfter();
nonRunningPicocli = pseudoLaunch("start-dev", "--log-async=true", "--log-console-async-queue-length=222");
assertEquals(CommandLine.ExitCode.OK, nonRunningPicocli.exitCode);
onAfter();
nonRunningPicocli = pseudoLaunch("start-dev", "--log=console,file", "--log-async=true", "--log-console-async=false", "--log-console-async-queue-length=222");
assertEquals(CommandLine.ExitCode.USAGE, nonRunningPicocli.exitCode);
assertThat(nonRunningPicocli.getErrString(), containsString("Disabled option: '--log-console-async-queue-length'. Available only when Console log handler is activated"));
onAfter();
nonRunningPicocli = pseudoLaunch("start-dev", "--log=console,file", "--log-async=true", "--log-console-async=false", "--log-file-async-queue-length=222");
assertEquals(CommandLine.ExitCode.OK, nonRunningPicocli.exitCode);
}
@Test
public void logAsyncConsoleDisabledOptions() {
assertLogAsyncHandlerDisabledOptions(LoggingOptions.Handler.file, LoggingOptions.Handler.console, "Console log handler");
}
@Test
public void logAsyncFileDisabledOptions() {
assertLogAsyncHandlerDisabledOptions(LoggingOptions.Handler.console, LoggingOptions.Handler.file, "File log handler");
}
@Test
public void logAsyncSyslogDisabledOptions() {
assertLogAsyncHandlerDisabledOptions(LoggingOptions.Handler.console, LoggingOptions.Handler.syslog, "Syslog");
}
private void assertLogAsyncHandlerDisabledOptions(LoggingOptions.Handler logHandler, LoggingOptions.Handler logHandlerOptions, String logHandlerFullName) {
var logHandlerName = logHandler.toString();
var logHandlerOptionsName = logHandlerOptions.toString();
NonRunningPicocli nonRunningPicocli = pseudoLaunch("start-dev", "--log=%s".formatted(logHandlerName), "--log-%s-async-queue-length=invalid".formatted(logHandlerOptionsName));
assertEquals(CommandLine.ExitCode.USAGE, nonRunningPicocli.exitCode);
assertThat(nonRunningPicocli.getErrString(), containsString("Invalid value for option '--log-%s-async-queue-length': 'invalid' is not an int".formatted(logHandlerOptionsName)));
nonRunningPicocli = pseudoLaunch("start-dev", "--log=%s".formatted(logHandlerName), "--log-%s-async-queue-length=768".formatted(logHandlerOptionsName));
assertEquals(CommandLine.ExitCode.USAGE, nonRunningPicocli.exitCode);
assertThat(nonRunningPicocli.getErrString(), containsString("Disabled option: '--log-%s-async-queue-length'. Available only when %s is activated and asynchronous logging is enabled".formatted(logHandlerOptionsName, logHandlerFullName)));
}
@Test
public void logAsyncConsoleInvalidValues() {
assertLogAsyncHandlerInvalidValues(LoggingOptions.Handler.console);
}
@Test
public void logAsyncFileInvalidValues() {
assertLogAsyncHandlerInvalidValues(LoggingOptions.Handler.file);
}
@Test
public void logAsyncSyslogInvalidValues() {
assertLogAsyncHandlerInvalidValues(LoggingOptions.Handler.syslog);
}
protected void assertLogAsyncHandlerInvalidValues(LoggingOptions.Handler handler) {
var handlerName = handler.toString();
var nonRunningPicocli = pseudoLaunch("start-dev", "--log=%s".formatted(handlerName), "--log-%s-async=true".formatted(handlerName), "--log-%s-async-queue-length=invalid".formatted(handlerName));
assertEquals(CommandLine.ExitCode.USAGE, nonRunningPicocli.exitCode);
assertThat(nonRunningPicocli.getErrString(), containsString("Invalid value for option '--log-%s-async-queue-length': 'invalid' is not an int".formatted(handlerName)));
}
}

View File

@ -31,6 +31,7 @@ import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.hamcrest.CoreMatchers;
import org.jboss.logmanager.handlers.AsyncHandler;
import org.junit.Test;
import org.keycloak.config.LoggingOptions;
import org.keycloak.quarkus.runtime.Environment;
@ -319,4 +320,128 @@ public class LoggingConfigurationTest extends AbstractConfigurationTest {
assertEquals("true", createConfig().getConfigValue("quarkus.log.console.enable").getValue());
}
@Test
public void asyncDefaults() {
initConfig();
boolean defaultEnabled = false;
int defaultQueueLength = 512;
for (var handler : LoggingOptions.Handler.values()) {
assertAsyncProperties(handler, defaultEnabled, defaultQueueLength);
}
}
@Test
public void asyncProperties() {
boolean enabled = true;
int queueLength = 1024;
for (var handler : LoggingOptions.Handler.values()) {
setAsyncProperties(handler, enabled, queueLength);
}
initConfig();
for (var handler : LoggingOptions.Handler.values()) {
assertAsyncProperties(handler, enabled, queueLength);
}
}
@Test
public void asyncPropertiesIndividual() {
setAsyncProperties(LoggingOptions.Handler.console, true, 768);
setAsyncProperties(LoggingOptions.Handler.file, false, 1523);
setAsyncProperties(LoggingOptions.Handler.syslog, true, 888);
initConfig();
assertAsyncProperties(LoggingOptions.Handler.console, true, 768);
assertAsyncProperties(LoggingOptions.Handler.file, false, 1523);
assertAsyncProperties(LoggingOptions.Handler.syslog, true, 888);
}
@Test
public void asyncGlobalProperty() {
putEnvVar("KC_LOG_ASYNC", "true");
initConfig();
assertAsyncLoggingEnabled(LoggingOptions.Handler.console, true);
assertAsyncLoggingEnabled(LoggingOptions.Handler.file, true);
assertAsyncLoggingEnabled(LoggingOptions.Handler.syslog, true);
onAfter();
putEnvVar("KC_LOG_ASYNC", "false");
initConfig();
assertAsyncLoggingEnabled(LoggingOptions.Handler.console, false);
assertAsyncLoggingEnabled(LoggingOptions.Handler.file, false);
assertAsyncLoggingEnabled(LoggingOptions.Handler.syslog, false);
}
@Test
public void asyncGlobalPropertyOverrides() {
putEnvVar("KC_LOG_ASYNC", "true");
setAsyncLoggingEnabled(LoggingOptions.Handler.console, false);
initConfig();
assertAsyncLoggingEnabled(LoggingOptions.Handler.console, false);
assertAsyncLoggingEnabled(LoggingOptions.Handler.file, true);
assertAsyncLoggingEnabled(LoggingOptions.Handler.syslog, true);
setAsyncLoggingEnabled(LoggingOptions.Handler.file, false);
initConfig();
assertAsyncLoggingEnabled(LoggingOptions.Handler.console, false);
assertAsyncLoggingEnabled(LoggingOptions.Handler.file, false);
assertAsyncLoggingEnabled(LoggingOptions.Handler.syslog, true);
setAsyncLoggingEnabled(LoggingOptions.Handler.file, false);
initConfig();
assertAsyncLoggingEnabled(LoggingOptions.Handler.console, false);
assertAsyncLoggingEnabled(LoggingOptions.Handler.file, false);
assertAsyncLoggingEnabled(LoggingOptions.Handler.syslog, true);
onAfter();
putEnvVar("KC_LOG_ASYNC", "false");
setAsyncLoggingEnabled(LoggingOptions.Handler.console, true);
initConfig();
assertAsyncLoggingEnabled(LoggingOptions.Handler.console, true);
assertAsyncLoggingEnabled(LoggingOptions.Handler.file, false);
assertAsyncLoggingEnabled(LoggingOptions.Handler.syslog, false);
}
protected void setAsyncLoggingEnabled(LoggingOptions.Handler handler, Boolean enabled) {
// default values
setAsyncProperties(handler, enabled, 512);
}
protected void setAsyncProperties(LoggingOptions.Handler handler, Boolean enabled, Integer queueLength) {
var handlerName = handler.name();
putEnvVars(Map.of(
"KC_LOG_%s_ASYNC".formatted(handlerName), enabled.toString(),
"KC_LOG_%s_ASYNC_QUEUE_LENGTH".formatted(handlerName), queueLength.toString()
));
}
protected void assertAsyncLoggingEnabled(LoggingOptions.Handler handler, Boolean expectedEnabled) {
var handlerName = handler.toString();
assertConfig("log-%s-async".formatted(handlerName), expectedEnabled.toString());
assertExternalConfig("quarkus.log.%s.async".formatted(handlerName), expectedEnabled.toString());
}
protected void assertAsyncProperties(LoggingOptions.Handler handler, Boolean enabled, Integer queueLength) {
assertAsyncLoggingEnabled(handler, enabled);
var handlerName = handler.toString();
assertConfig("log-%s-async-queue-length".formatted(handlerName), queueLength.toString());
assertExternalConfig("quarkus.log.%s.async.queue-length".formatted(handlerName), queueLength.toString());
}
}

View File

@ -31,6 +31,7 @@ import java.nio.charset.Charset;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.keycloak.config.LoggingOptions;
@ -41,6 +42,7 @@ import org.keycloak.it.junit5.extension.RawDistOnly;
import org.keycloak.it.utils.KeycloakDistribution;
import org.keycloak.it.utils.RawDistRootPath;
import org.keycloak.it.utils.RawKeycloakDistribution;
import org.keycloak.quarkus.runtime.configuration.Configuration;
import org.testcontainers.shaded.org.apache.commons.io.FileUtils;
import io.quarkus.deployment.util.FileUtil;
@ -258,6 +260,12 @@ public class LoggingDistTest {
assertThat(data, containsString("@timestamp"));
}
@Test
@Launch({"start-dev", "--log-async=true"})
void asyncLogging(CLIResult cliResult) {
cliResult.assertStartedDevMode();
}
protected static String readDefaultFileLog(RawDistRootPath path) {
Path logFilePath = Paths.get(path.getDistRootPath() + File.separator + LoggingOptions.DEFAULT_LOG_PATH);
File logFile = new File(logFilePath.toString());

View File

@ -20,8 +20,6 @@ package org.keycloak.it.cli.dist;
import java.nio.file.Paths;
import io.quarkus.test.junit.main.Launch;
import io.quarkus.test.junit.main.LaunchResult;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
@ -33,8 +31,6 @@ import org.keycloak.it.junit5.extension.RawDistOnly;
import org.keycloak.it.junit5.extension.WithEnvVars;
import org.keycloak.it.utils.KeycloakDistribution;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.keycloak.quarkus.runtime.cli.command.Main.CONFIG_FILE_LONG_NAME;
@DistributionTest
@ -45,33 +41,33 @@ public class OptionsDistTest {
@Test
@Order(1)
@Launch({"build", "--db=invalid"})
public void failInvalidOptionValue(LaunchResult result) {
Assertions.assertTrue(result.getErrorOutput().contains("Invalid value for option '--db': invalid. Expected values are: dev-file, dev-mem, mariadb, mssql, mysql, oracle, postgres"));
public void failInvalidOptionValue(CLIResult result) {
result.assertError("Invalid value for option '--db': invalid. Expected values are: dev-file, dev-mem, mariadb, mssql, mysql, oracle, postgres");
}
@DryRun
@Test
@Order(2)
@Launch({"start", "--db=dev-file", "--test=invalid"})
public void testServerDoesNotStartIfValidationFailDuringReAugStart(LaunchResult result) {
assertEquals(1, result.getErrorStream().stream().filter(s -> s.contains("Unknown option: '--test'")).count());
public void testServerDoesNotStartIfValidationFailDuringReAugStart(CLIResult result) {
result.assertError("Unknown option: '--test'");
}
@DryRun
@Test
@Order(3)
@Launch({"start", "--db=dev-file", "--log=console", "--log-file-output=json", "--http-enabled=true", "--hostname-strict=false"})
public void testServerDoesNotStartIfDisabledFileLogOption(LaunchResult result) {
assertEquals(1, result.getErrorStream().stream().filter(s -> s.contains("Disabled option: '--log-file-output'. Available only when File log handler is activated")).count());
assertEquals(1, result.getErrorStream().stream().filter(s -> s.contains("Possible solutions: --log, --log-console-output, --log-console-level, --log-console-format, --log-console-color, --log-level")).count());
public void testServerDoesNotStartIfDisabledFileLogOption(CLIResult result) {
result.assertError("Disabled option: '--log-file-output'. Available only when File log handler is activated");
result.assertError("--log, --log-async, --log-console-output, --log-console-level, --log-console-format, --log-console-color, --log-console-async, --log-level, --log-level-<category>");
}
@DryRun
@Test
@Order(4)
@Launch({"start", "--db=dev-file", "--log=file", "--log-file-output=json", "--http-enabled=true", "--hostname-strict=false"})
public void testServerStartIfEnabledFileLogOption(LaunchResult result) {
assertEquals(0, result.getErrorStream().stream().filter(s -> s.contains("Disabled option: '--log-file-output'. Available only when File log handler is activated")).count());
public void testServerStartIfEnabledFileLogOption(CLIResult result) {
result.assertNoError("Disabled option: '--log-file-output'. Available only when File log handler is activated");
}
@Test
@ -105,42 +101,42 @@ public class OptionsDistTest {
@Test
@Order(7)
@Launch({"start-dev", "--test=invalid"})
public void testServerDoesNotStartIfValidationFailDuringReAugStartDev(LaunchResult result) {
assertEquals(1, result.getErrorStream().stream().filter(s -> s.contains("Unknown option: '--test'")).count());
public void testServerDoesNotStartIfValidationFailDuringReAugStartDev(CLIResult result) {
result.assertError("Unknown option: '--test'");
}
@DryRun
@Test
@Order(8)
@Launch({"start-dev", "--log=console", "--log-file-output=json"})
public void testServerDoesNotStartDevIfDisabledFileLogOption(LaunchResult result) {
assertEquals(1, result.getErrorStream().stream().filter(s -> s.contains("Disabled option: '--log-file-output'. Available only when File log handler is activated")).count());
assertEquals(1, result.getErrorStream().stream().filter(s -> s.contains("Possible solutions: --log, --log-console-output, --log-console-level, --log-console-format, --log-console-color, --log-level")).count());
public void testServerDoesNotStartDevIfDisabledFileLogOption(CLIResult result) {
result.assertError("Disabled option: '--log-file-output'. Available only when File log handler is activated");
result.assertError("Possible solutions: --log, --log-async, --log-console-output, --log-console-level, --log-console-format, --log-console-color, --log-console-async, --log-level, --log-level-<category>");
}
@DryRun
@Test
@Order(9)
@Launch({"start-dev", "--log=file", "--log-file-output=json", "--log-console-color=true"})
public void testServerStartDevIfEnabledFileLogOption(LaunchResult result) {
assertEquals(0, result.getErrorStream().stream().filter(s -> s.contains("Disabled option: '--log-file-output'. Available only when File log handler is activated")).count());
assertEquals(1, result.getErrorStream().stream().filter(s -> s.contains("Disabled option: '--log-console-color'. Available only when Console log handler is activated")).count());
assertEquals(1, result.getErrorStream().stream().filter(s -> s.contains("Possible solutions: --log, --log-file, --log-file-level, --log-file-format, --log-file-json-format, --log-file-output, --log-level, --log-level")).count());
public void testServerStartDevIfEnabledFileLogOption(CLIResult result) {
result.assertNoError("Disabled option: '--log-file-output'. Available only when File log handler is activated");
result.assertError("Disabled option: '--log-console-color'. Available only when Console log handler is activated");
result.assertError("Possible solutions: --log, --log-async, --log-file, --log-file-level, --log-file-format, --log-file-json-format, --log-file-output, --log-file-async, --log-level, --log-level-<category>");
}
@DryRun
@Test
@Order(10)
@Launch({"start-dev", "--cache-remote-host=localhost"})
public void testCacheRemoteHostWithoutMultiSite(LaunchResult result) {
assertErrorStreamContains(result, "cache-remote-host available only when feature 'multi-site' or 'clusterless' is set");
public void testCacheRemoteHostWithoutMultiSite(CLIResult result) {
result.assertError( "cache-remote-host available only when feature 'multi-site' or 'clusterless' is set");
}
@DryRun
@Test
@Order(11)
@Launch({"start-dev", "--cache-remote-port=11222"})
public void testCacheRemotePortWithoutCacheRemoteHost(LaunchResult result) {
public void testCacheRemotePortWithoutCacheRemoteHost(CLIResult result) {
assertDisabledDueToMissingRemoteHost(result, "--cache-remote-port");
}
@ -148,7 +144,7 @@ public class OptionsDistTest {
@Test
@Order(12)
@Launch({"start-dev", "--cache-remote-username=user"})
public void testCacheRemoteUsernameWithoutCacheRemoteHost(LaunchResult result) {
public void testCacheRemoteUsernameWithoutCacheRemoteHost(CLIResult result) {
assertDisabledDueToMissingRemoteHost(result, "--cache-remote-username");
}
@ -156,7 +152,7 @@ public class OptionsDistTest {
@Test
@Order(13)
@Launch({"start-dev", "--cache-remote-password=pass"})
public void testCacheRemotePasswordWithoutCacheRemoteHost(LaunchResult result) {
public void testCacheRemotePasswordWithoutCacheRemoteHost(CLIResult result) {
assertDisabledDueToMissingRemoteHost(result, "--cache-remote-password");
}
@ -164,7 +160,7 @@ public class OptionsDistTest {
@Test
@Order(14)
@Launch({"start-dev", "--cache-remote-tls-enabled=false"})
public void testCacheRemoteTlsEnabledWithoutCacheRemoteHost(LaunchResult result) {
public void testCacheRemoteTlsEnabledWithoutCacheRemoteHost(CLIResult result) {
assertDisabledDueToMissingRemoteHost(result, "--cache-remote-tls-enabled");
}
@ -172,31 +168,27 @@ public class OptionsDistTest {
@Test
@Order(15)
@Launch({"start-dev", "--features=multi-site"})
public void testMultiSiteWithoutCacheRemoteHost(LaunchResult result) {
assertErrorStreamContains(result, "- cache-remote-host: Required when feature 'multi-site' or 'clusterless' is set.");
public void testMultiSiteWithoutCacheRemoteHost(CLIResult result) {
result.assertError("- cache-remote-host: Required when feature 'multi-site' or 'clusterless' is set.");
}
@DryRun
@Test
@Order(16)
@Launch({"start-dev", "--features=multi-site", "--cache-remote-host=localhost", "--cache-remote-username=user"})
public void testCacheRemoteUsernameWithoutCacheRemotePassword(LaunchResult result) {
assertErrorStreamContains(result, "The option 'cache-remote-password' is required when 'cache-remote-username' is set.");
public void testCacheRemoteUsernameWithoutCacheRemotePassword(CLIResult result) {
result.assertError("The option 'cache-remote-password' is required when 'cache-remote-username' is set.");
}
@DryRun
@Test
@Order(17)
@Launch({"start-dev", "--features=multi-site", "--cache-remote-host=localhost", "--cache-remote-password=secret"})
public void testCacheRemotePasswordWithoutCacheRemoteUsername(LaunchResult result) {
assertErrorStreamContains(result, "The option 'cache-remote-username' is required when 'cache-remote-password' is set.");
public void testCacheRemotePasswordWithoutCacheRemoteUsername(CLIResult result) {
result.assertError("The option 'cache-remote-username' is required when 'cache-remote-password' is set.");
}
private static void assertDisabledDueToMissingRemoteHost(LaunchResult result, String option) {
assertErrorStreamContains(result, "Disabled option: '%s'. Available only when remote host is set".formatted(option));
}
private static void assertErrorStreamContains(LaunchResult result, String msg) {
assertTrue(result.getErrorStream().stream().anyMatch(s -> s.contains(msg)));
private static void assertDisabledDueToMissingRemoteHost(CLIResult result, String option) {
result.assertError("Disabled option: '%s'. Available only when remote host is set".formatted(option));
}
}

View File

@ -135,6 +135,12 @@ Logging:
--log <handler> Enable one or more log handlers in a comma-separated list. Possible values
are: console, file, syslog. Default: console.
--log-async <true|false>
Indicates whether to log asynchronously to all handlers. Default: false.
--log-console-async <true|false>
Indicates whether to log asynchronously to console. If not set, value from the
parent property 'log-async' is used. Default: false. Available only when
Console log handler is activated.
--log-console-color <true|false>
Enable or disable colors when logging to console. Default: false. Available
only when Console log handler is activated.

View File

@ -137,6 +137,12 @@ Logging:
--log <handler> Enable one or more log handlers in a comma-separated list. Possible values
are: console, file, syslog. Default: console.
--log-async <true|false>
Indicates whether to log asynchronously to all handlers. Default: false.
--log-console-async <true|false>
Indicates whether to log asynchronously to console. If not set, value from the
parent property 'log-async' is used. Default: false. Available only when
Console log handler is activated.
--log-console-color <true|false>
Enable or disable colors when logging to console. Default: false. Available
only when Console log handler is activated.

View File

@ -130,6 +130,12 @@ Logging:
--log <handler> Enable one or more log handlers in a comma-separated list. Possible values
are: console, file, syslog. Default: console.
--log-async <true|false>
Indicates whether to log asynchronously to all handlers. Default: false.
--log-console-async <true|false>
Indicates whether to log asynchronously to console. If not set, value from the
parent property 'log-async' is used. Default: false. Available only when
Console log handler is activated.
--log-console-color <true|false>
Enable or disable colors when logging to console. Default: false. Available
only when Console log handler is activated.

View File

@ -130,6 +130,16 @@ Logging:
--log <handler> Enable one or more log handlers in a comma-separated list. Possible values
are: console, file, syslog. Default: console.
--log-async <true|false>
Indicates whether to log asynchronously to all handlers. Default: false.
--log-console-async <true|false>
Indicates whether to log asynchronously to console. If not set, value from the
parent property 'log-async' is used. Default: false. Available only when
Console log handler is activated.
--log-console-async-queue-length <queue-length>
The queue length to use before flushing writing when logging to console.
Default: 512. Available only when Console log handler is activated and
asynchronous logging is enabled.
--log-console-color <true|false>
Enable or disable colors when logging to console. Default: false. Available
only when Console log handler is activated.
@ -158,6 +168,14 @@ Logging:
handler is activated.
--log-file <file> Set the log file path and filename. Default: data/log/keycloak.log. Available
only when File log handler is activated.
--log-file-async <true|false>
Indicates whether to log asynchronously to file log. If not set, value from
the parent property 'log-async' is used. Default: false. Available only when
File log handler is activated.
--log-file-async-queue-length <queue-length>
The queue length to use before flushing writing when logging to file log.
Default: 512. Available only when File log handler is activated and
asynchronous logging is enabled.
--log-file-format <format>
Set a format specific to file log entries. Default: %d{yyyy-MM-dd HH:mm:ss,
SSS} %-5p [%c] (%t) %s%e%n. Available only when File log handler is
@ -192,6 +210,14 @@ Logging:
--log-syslog-app-name <name>
Set the app name used when formatting the message in RFC5424 format. Default:
keycloak. Available only when Syslog is activated.
--log-syslog-async <true|false>
Indicates whether to log asynchronously to Syslog. If not set, value from the
parent property 'log-async' is used. Default: false. Available only when
Syslog is activated.
--log-syslog-async-queue-length <queue-length>
The queue length to use before flushing writing when logging to Syslog.
Default: 512. Available only when Syslog is activated and asynchronous
logging is enabled.
--log-syslog-endpoint <host:port>
Set the IP address and port of the Syslog server. Default: localhost:514.
Available only when Syslog is activated.

View File

@ -130,6 +130,12 @@ Logging:
--log <handler> Enable one or more log handlers in a comma-separated list. Possible values
are: console, file, syslog. Default: console.
--log-async <true|false>
Indicates whether to log asynchronously to all handlers. Default: false.
--log-console-async <true|false>
Indicates whether to log asynchronously to console. If not set, value from the
parent property 'log-async' is used. Default: false. Available only when
Console log handler is activated.
--log-console-color <true|false>
Enable or disable colors when logging to console. Default: false. Available
only when Console log handler is activated.

View File

@ -130,6 +130,16 @@ Logging:
--log <handler> Enable one or more log handlers in a comma-separated list. Possible values
are: console, file, syslog. Default: console.
--log-async <true|false>
Indicates whether to log asynchronously to all handlers. Default: false.
--log-console-async <true|false>
Indicates whether to log asynchronously to console. If not set, value from the
parent property 'log-async' is used. Default: false. Available only when
Console log handler is activated.
--log-console-async-queue-length <queue-length>
The queue length to use before flushing writing when logging to console.
Default: 512. Available only when Console log handler is activated and
asynchronous logging is enabled.
--log-console-color <true|false>
Enable or disable colors when logging to console. Default: false. Available
only when Console log handler is activated.
@ -158,6 +168,14 @@ Logging:
handler is activated.
--log-file <file> Set the log file path and filename. Default: data/log/keycloak.log. Available
only when File log handler is activated.
--log-file-async <true|false>
Indicates whether to log asynchronously to file log. If not set, value from
the parent property 'log-async' is used. Default: false. Available only when
File log handler is activated.
--log-file-async-queue-length <queue-length>
The queue length to use before flushing writing when logging to file log.
Default: 512. Available only when File log handler is activated and
asynchronous logging is enabled.
--log-file-format <format>
Set a format specific to file log entries. Default: %d{yyyy-MM-dd HH:mm:ss,
SSS} %-5p [%c] (%t) %s%e%n. Available only when File log handler is
@ -192,6 +210,14 @@ Logging:
--log-syslog-app-name <name>
Set the app name used when formatting the message in RFC5424 format. Default:
keycloak. Available only when Syslog is activated.
--log-syslog-async <true|false>
Indicates whether to log asynchronously to Syslog. If not set, value from the
parent property 'log-async' is used. Default: false. Available only when
Syslog is activated.
--log-syslog-async-queue-length <queue-length>
The queue length to use before flushing writing when logging to Syslog.
Default: 512. Available only when Syslog is activated and asynchronous
logging is enabled.
--log-syslog-endpoint <host:port>
Set the IP address and port of the Syslog server. Default: localhost:514.
Available only when Syslog is activated.

View File

@ -285,6 +285,12 @@ Logging:
--log <handler> Enable one or more log handlers in a comma-separated list. Possible values
are: console, file, syslog. Default: console.
--log-async <true|false>
Indicates whether to log asynchronously to all handlers. Default: false.
--log-console-async <true|false>
Indicates whether to log asynchronously to console. If not set, value from the
parent property 'log-async' is used. Default: false. Available only when
Console log handler is activated.
--log-console-color <true|false>
Enable or disable colors when logging to console. Default: false. Available
only when Console log handler is activated.

View File

@ -345,6 +345,16 @@ Logging:
--log <handler> Enable one or more log handlers in a comma-separated list. Possible values
are: console, file, syslog. Default: console.
--log-async <true|false>
Indicates whether to log asynchronously to all handlers. Default: false.
--log-console-async <true|false>
Indicates whether to log asynchronously to console. If not set, value from the
parent property 'log-async' is used. Default: false. Available only when
Console log handler is activated.
--log-console-async-queue-length <queue-length>
The queue length to use before flushing writing when logging to console.
Default: 512. Available only when Console log handler is activated and
asynchronous logging is enabled.
--log-console-color <true|false>
Enable or disable colors when logging to console. Default: false. Available
only when Console log handler is activated.
@ -373,6 +383,14 @@ Logging:
handler is activated.
--log-file <file> Set the log file path and filename. Default: data/log/keycloak.log. Available
only when File log handler is activated.
--log-file-async <true|false>
Indicates whether to log asynchronously to file log. If not set, value from
the parent property 'log-async' is used. Default: false. Available only when
File log handler is activated.
--log-file-async-queue-length <queue-length>
The queue length to use before flushing writing when logging to file log.
Default: 512. Available only when File log handler is activated and
asynchronous logging is enabled.
--log-file-format <format>
Set a format specific to file log entries. Default: %d{yyyy-MM-dd HH:mm:ss,
SSS} %-5p [%c] (%t) %s%e%n. Available only when File log handler is
@ -407,6 +425,14 @@ Logging:
--log-syslog-app-name <name>
Set the app name used when formatting the message in RFC5424 format. Default:
keycloak. Available only when Syslog is activated.
--log-syslog-async <true|false>
Indicates whether to log asynchronously to Syslog. If not set, value from the
parent property 'log-async' is used. Default: false. Available only when
Syslog is activated.
--log-syslog-async-queue-length <queue-length>
The queue length to use before flushing writing when logging to Syslog.
Default: 512. Available only when Syslog is activated and asynchronous
logging is enabled.
--log-syslog-endpoint <host:port>
Set the IP address and port of the Syslog server. Default: localhost:514.
Available only when Syslog is activated.

View File

@ -317,6 +317,12 @@ Logging:
--log <handler> Enable one or more log handlers in a comma-separated list. Possible values
are: console, file, syslog. Default: console.
--log-async <true|false>
Indicates whether to log asynchronously to all handlers. Default: false.
--log-console-async <true|false>
Indicates whether to log asynchronously to console. If not set, value from the
parent property 'log-async' is used. Default: false. Available only when
Console log handler is activated.
--log-console-color <true|false>
Enable or disable colors when logging to console. Default: false. Available
only when Console log handler is activated.

View File

@ -346,6 +346,16 @@ Logging:
--log <handler> Enable one or more log handlers in a comma-separated list. Possible values
are: console, file, syslog. Default: console.
--log-async <true|false>
Indicates whether to log asynchronously to all handlers. Default: false.
--log-console-async <true|false>
Indicates whether to log asynchronously to console. If not set, value from the
parent property 'log-async' is used. Default: false. Available only when
Console log handler is activated.
--log-console-async-queue-length <queue-length>
The queue length to use before flushing writing when logging to console.
Default: 512. Available only when Console log handler is activated and
asynchronous logging is enabled.
--log-console-color <true|false>
Enable or disable colors when logging to console. Default: false. Available
only when Console log handler is activated.
@ -374,6 +384,14 @@ Logging:
handler is activated.
--log-file <file> Set the log file path and filename. Default: data/log/keycloak.log. Available
only when File log handler is activated.
--log-file-async <true|false>
Indicates whether to log asynchronously to file log. If not set, value from
the parent property 'log-async' is used. Default: false. Available only when
File log handler is activated.
--log-file-async-queue-length <queue-length>
The queue length to use before flushing writing when logging to file log.
Default: 512. Available only when File log handler is activated and
asynchronous logging is enabled.
--log-file-format <format>
Set a format specific to file log entries. Default: %d{yyyy-MM-dd HH:mm:ss,
SSS} %-5p [%c] (%t) %s%e%n. Available only when File log handler is
@ -408,6 +426,14 @@ Logging:
--log-syslog-app-name <name>
Set the app name used when formatting the message in RFC5424 format. Default:
keycloak. Available only when Syslog is activated.
--log-syslog-async <true|false>
Indicates whether to log asynchronously to Syslog. If not set, value from the
parent property 'log-async' is used. Default: false. Available only when
Syslog is activated.
--log-syslog-async-queue-length <queue-length>
The queue length to use before flushing writing when logging to Syslog.
Default: 512. Available only when Syslog is activated and asynchronous
logging is enabled.
--log-syslog-endpoint <host:port>
Set the IP address and port of the Syslog server. Default: localhost:514.
Available only when Syslog is activated.

View File

@ -266,6 +266,12 @@ Logging:
--log <handler> Enable one or more log handlers in a comma-separated list. Possible values
are: console, file, syslog. Default: console.
--log-async <true|false>
Indicates whether to log asynchronously to all handlers. Default: false.
--log-console-async <true|false>
Indicates whether to log asynchronously to console. If not set, value from the
parent property 'log-async' is used. Default: false. Available only when
Console log handler is activated.
--log-console-color <true|false>
Enable or disable colors when logging to console. Default: false. Available
only when Console log handler is activated.

View File

@ -295,6 +295,16 @@ Logging:
--log <handler> Enable one or more log handlers in a comma-separated list. Possible values
are: console, file, syslog. Default: console.
--log-async <true|false>
Indicates whether to log asynchronously to all handlers. Default: false.
--log-console-async <true|false>
Indicates whether to log asynchronously to console. If not set, value from the
parent property 'log-async' is used. Default: false. Available only when
Console log handler is activated.
--log-console-async-queue-length <queue-length>
The queue length to use before flushing writing when logging to console.
Default: 512. Available only when Console log handler is activated and
asynchronous logging is enabled.
--log-console-color <true|false>
Enable or disable colors when logging to console. Default: false. Available
only when Console log handler is activated.
@ -323,6 +333,14 @@ Logging:
handler is activated.
--log-file <file> Set the log file path and filename. Default: data/log/keycloak.log. Available
only when File log handler is activated.
--log-file-async <true|false>
Indicates whether to log asynchronously to file log. If not set, value from
the parent property 'log-async' is used. Default: false. Available only when
File log handler is activated.
--log-file-async-queue-length <queue-length>
The queue length to use before flushing writing when logging to file log.
Default: 512. Available only when File log handler is activated and
asynchronous logging is enabled.
--log-file-format <format>
Set a format specific to file log entries. Default: %d{yyyy-MM-dd HH:mm:ss,
SSS} %-5p [%c] (%t) %s%e%n. Available only when File log handler is
@ -357,6 +375,14 @@ Logging:
--log-syslog-app-name <name>
Set the app name used when formatting the message in RFC5424 format. Default:
keycloak. Available only when Syslog is activated.
--log-syslog-async <true|false>
Indicates whether to log asynchronously to Syslog. If not set, value from the
parent property 'log-async' is used. Default: false. Available only when
Syslog is activated.
--log-syslog-async-queue-length <queue-length>
The queue length to use before flushing writing when logging to Syslog.
Default: 512. Available only when Syslog is activated and asynchronous
logging is enabled.
--log-syslog-endpoint <host:port>
Set the IP address and port of the Syslog server. Default: localhost:514.
Available only when Syslog is activated.

View File

@ -316,6 +316,12 @@ Logging:
--log <handler> Enable one or more log handlers in a comma-separated list. Possible values
are: console, file, syslog. Default: console.
--log-async <true|false>
Indicates whether to log asynchronously to all handlers. Default: false.
--log-console-async <true|false>
Indicates whether to log asynchronously to console. If not set, value from the
parent property 'log-async' is used. Default: false. Available only when
Console log handler is activated.
--log-console-color <true|false>
Enable or disable colors when logging to console. Default: false. Available
only when Console log handler is activated.

View File

@ -345,6 +345,16 @@ Logging:
--log <handler> Enable one or more log handlers in a comma-separated list. Possible values
are: console, file, syslog. Default: console.
--log-async <true|false>
Indicates whether to log asynchronously to all handlers. Default: false.
--log-console-async <true|false>
Indicates whether to log asynchronously to console. If not set, value from the
parent property 'log-async' is used. Default: false. Available only when
Console log handler is activated.
--log-console-async-queue-length <queue-length>
The queue length to use before flushing writing when logging to console.
Default: 512. Available only when Console log handler is activated and
asynchronous logging is enabled.
--log-console-color <true|false>
Enable or disable colors when logging to console. Default: false. Available
only when Console log handler is activated.
@ -373,6 +383,14 @@ Logging:
handler is activated.
--log-file <file> Set the log file path and filename. Default: data/log/keycloak.log. Available
only when File log handler is activated.
--log-file-async <true|false>
Indicates whether to log asynchronously to file log. If not set, value from
the parent property 'log-async' is used. Default: false. Available only when
File log handler is activated.
--log-file-async-queue-length <queue-length>
The queue length to use before flushing writing when logging to file log.
Default: 512. Available only when File log handler is activated and
asynchronous logging is enabled.
--log-file-format <format>
Set a format specific to file log entries. Default: %d{yyyy-MM-dd HH:mm:ss,
SSS} %-5p [%c] (%t) %s%e%n. Available only when File log handler is
@ -407,6 +425,14 @@ Logging:
--log-syslog-app-name <name>
Set the app name used when formatting the message in RFC5424 format. Default:
keycloak. Available only when Syslog is activated.
--log-syslog-async <true|false>
Indicates whether to log asynchronously to Syslog. If not set, value from the
parent property 'log-async' is used. Default: false. Available only when
Syslog is activated.
--log-syslog-async-queue-length <queue-length>
The queue length to use before flushing writing when logging to Syslog.
Default: 512. Available only when Syslog is activated and asynchronous
logging is enabled.
--log-syslog-endpoint <host:port>
Set the IP address and port of the Syslog server. Default: localhost:514.
Available only when Syslog is activated.

View File

@ -314,6 +314,12 @@ Logging:
--log <handler> Enable one or more log handlers in a comma-separated list. Possible values
are: console, file, syslog. Default: console.
--log-async <true|false>
Indicates whether to log asynchronously to all handlers. Default: false.
--log-console-async <true|false>
Indicates whether to log asynchronously to console. If not set, value from the
parent property 'log-async' is used. Default: false. Available only when
Console log handler is activated.
--log-console-color <true|false>
Enable or disable colors when logging to console. Default: false. Available
only when Console log handler is activated.

View File

@ -343,6 +343,16 @@ Logging:
--log <handler> Enable one or more log handlers in a comma-separated list. Possible values
are: console, file, syslog. Default: console.
--log-async <true|false>
Indicates whether to log asynchronously to all handlers. Default: false.
--log-console-async <true|false>
Indicates whether to log asynchronously to console. If not set, value from the
parent property 'log-async' is used. Default: false. Available only when
Console log handler is activated.
--log-console-async-queue-length <queue-length>
The queue length to use before flushing writing when logging to console.
Default: 512. Available only when Console log handler is activated and
asynchronous logging is enabled.
--log-console-color <true|false>
Enable or disable colors when logging to console. Default: false. Available
only when Console log handler is activated.
@ -371,6 +381,14 @@ Logging:
handler is activated.
--log-file <file> Set the log file path and filename. Default: data/log/keycloak.log. Available
only when File log handler is activated.
--log-file-async <true|false>
Indicates whether to log asynchronously to file log. If not set, value from
the parent property 'log-async' is used. Default: false. Available only when
File log handler is activated.
--log-file-async-queue-length <queue-length>
The queue length to use before flushing writing when logging to file log.
Default: 512. Available only when File log handler is activated and
asynchronous logging is enabled.
--log-file-format <format>
Set a format specific to file log entries. Default: %d{yyyy-MM-dd HH:mm:ss,
SSS} %-5p [%c] (%t) %s%e%n. Available only when File log handler is
@ -405,6 +423,14 @@ Logging:
--log-syslog-app-name <name>
Set the app name used when formatting the message in RFC5424 format. Default:
keycloak. Available only when Syslog is activated.
--log-syslog-async <true|false>
Indicates whether to log asynchronously to Syslog. If not set, value from the
parent property 'log-async' is used. Default: false. Available only when
Syslog is activated.
--log-syslog-async-queue-length <queue-length>
The queue length to use before flushing writing when logging to Syslog.
Default: 512. Available only when Syslog is activated and asynchronous
logging is enabled.
--log-syslog-endpoint <host:port>
Set the IP address and port of the Syslog server. Default: localhost:514.
Available only when Syslog is activated.